What do I need to do to setup KennethWare 2.0 for my Canvas instance?

Community Contributor

Many thanks go out to  @kenneth_larsen  and the CIDI team at Utah State University, who built a fantastic Canvas Template Engine that make course creation a breeze!   However, there are many moving parts to get KennethWare 2.0 working inside of your Canvas instance. In an effort to make the installation easier for the Canvas community, I created this general discussion and process guide.

People Needs:

  1. A Canvas Administrator.
  2. A Systems Admin (or some really clever person who can create and manage a Web Server).
  3. Someone who can use and has access to an Image Manipulation tool.
  4. Someone who is comfortable coding and making edits to PHP, JavaScript and XML files.

Note: Other than the setup and IP provisioning on our Windows Server, I did the rest of the configuration, coding, and graphic asset development.  Please feel free comment on this discussion if you get stuck or have questions!  I will do my best to address any issues that come up.

Software Needs

  1. KennethWare 2.0 needs a Server! There are lots of options here:
    1. You can use a Hosted Server service or Internally Managed Server
    2. Picking the Server Operating System comes down to Windows Server, Linux, Mac OSX Server. From there it deciding the version or distribution.
    3. Configuring the Web Server.  You can pick IIS (Windows) or Apache (Can be used on any Server Operating System)
      1. The Web Server needs to have PHP enabled and MySQL installed and enabled. *While you’re at it, you may want to enable Python, since there are many Python Canvas scripts!
      2. The Web Server needs to have a IP Address (Example: and a Domain Address (Example: https://mydomain.com/) that are Public.
      3. HTTPS needs to be enabled and you will need a Digital Certificate. 
        1. IIS and Apache can create a Self-Signed Certificate (free!) or you can buy one from a Certificate Authority Provider like DigiCert.com
      4. PHP, MySQL, and cURL must be enabled on the web server

Important Note: I strongly advise you to NOT use a prepackaged “WAMP Stack”. WAMPServer, Bitnami, XAMPP, are excellent for Desktop Operating like Windows 10 for creating a code testing environment.  They are not recommended for a “Production” Web Server. Proceed at your own risk with this route! 

  1. A Code Editor. KennethWare 2.0 uses PHP and XML files.
    1. Adobe makes a really good, free(!) Code Editor called Brackets.io that works on Windows, Apple OSX. There’s a Linux version in development.
    2. TinyMCE is another great multi-OS tool!      
    3. Other choices include Adobe Dreamweaver, Sublime Text, Apple Xcode, Microsoft Visual Studio, etc.
    4. There are also many Browser extensions for Web Development and Coding for Chrome and Firefox users.
  2. An Image Manipulation tool.  There are JPEGs, GIFs, and PNGs that will need to be modified if you want to make the banner images and banner thumbnails.
  3. Again, many options to pick from like Adobe Photoshop, Adobe Fireworks, GIMP, etc.

Server Setup

Most of our processes came from the article “How to manually install Apache, PHP and MySQL on Windows?” from SuperUser.com. If you opt for Linux or Mac OSX Server, these tools are very easy to install and configure.  We were more comfortable with Windows Servers based on our team’s experience.

Windows and Apache Setup

  1. We started with a Windows Server 2008 R2 that was assigned a Public IP address.
  2. We downloaded and extracted the Apache24 folder to the root of the hard drive with a path of C:\Apache24\.
  3. We opened a command line window (Windows+R and type cmd then press Enter), change directory into C:\Apache24\bin and run httpd.exe, normally it shouldn't print any errors.
  4. If you get an error dialog stating that MSVCR110.dll is missing on your system, you'll need to install the Visual C++ Redistributable for Visual Studio 2012 - as always, when prompted, select the appropriate bit-version : vcredist_x86.exe for 32-Bit systems and vcredist_x64.exe for 64-Bit ones.
  5. If you get an error saying that it can't bind to port 80, check if another application uses that port - also Skype is known to use ports 80 and 443 by default; uncheck "Use port 80 and 443 as alternatives for incoming connections" in its advanced connection se..., restart Skype to apply the changes, and then you should be able to start Apache without issues.
  6. A warning like Could not reliably determine the server's fully qualified domain name can be ignored for now.
  7. Windows Firewall may prompt you to allow Apache to communicate on specific networks, I recommend you use the default settings : allow it on home and work networks, but not on public/untrusted networks.
  8. Then, we opened a browser (Google Chrome) and browsed http://localhost, we saw a page saying It works ! which meant our Apache installation was working.
  9. Note: If you got a warning about not being able to determine the system's fully qualified domain name, fix it by editing C:\Apache24\conf\httpd.conf and editing the ServerName variable (it should be already there in a comment, just uncomment it and change it) :

     Replace <yourhostname> with either the system's host name or localhost.

10. Finally, if you want to run the server automatically when the system starts (even if nobody logs in), you'll need to run it as a service - in a new elevated (as an administrator) command prompt, type :

   ServerName <yourhostname>
httpd.exe -k install

11. That's it, now you have a new service in Services (Windows+R then type "services.msc" then press Enter) named "Apache24" that you can control just like any other Windows service.


  1. We downloaded the latest PHP binaries (PHP 7.0.3) from the official PHP for Windows download page. Choose the thread-safe version that matches your Apache installation's bit-version (x86 for 32-Bit, x64 for 64-Bit).
  2. We created an empty PHP folder at the root of the hard drive, and extracted the previously downloaded archive there. You should have a path like C:\PHP\
  3. In C:\PHP, we renamed the php.ini-production to php.ini.
  4. We opened that php.ini file, search for extension_dir = "ext" and uncommented that line (remove the first ;). This sets the default extension dir to ext (which resolves to C:\PHP\ext and avoids having to prepend ext/ to all extension's paths manually like in previous versions of this post.
  5. We then configured Apache to use that PHP, by editing C:\Apache24\conf\httpd.conf - after all the LoadModule lines, add the following :
  6. We started Apache manually by opening a command prompt in C:\Apache24\bin and running httpd.exe - If you see no errors, it means your configuration file is valid and PHP is most likely working.
  7. You can test your PHP installation by creating a file like info.php with <?php phpinfo(); inside and going to http://localhost/info.php - you should see quite a bit of info about your system and your PHP installation and all its modules. If you get something else like an "Internal server error" that means something's wrong.
  8. You can now kill your current Apache process (Ctrl+C in the console) and start the service - the following part doesn't interact with Apache and can be done with the server already started.
  9. If you want to access your MySQL database from PHP, you'll need to enable extensions that allow you to do so, like php_mysqli or php_pdo_mysql - I recommend enabling them both.

10.  Open PHP's configuration file C:\PHP\php.ini in your text editor and search for php_mysqli or php_pdo_mysql - they should already be there, uncomment them.

11.  Done, now you can access any MySQL database using either mysqli or PDO.

LoadModule php5_module C:/PHP/php5apache2_4.dll
<IfModule php5_module>
    DirectoryIndex index.html index.php
    AddHandler application/x-httpd-php .php
    PHPIniDir "C:/PHP"


  1. On the MySQL Installer download page download the web installer mysql-installer-web-community-xxxxx.msi.
  2. We used MySQL Community Server 5.7.12 - it was the latest version when this answer was last updated (look at the edit date at the bottom of the post).
  3. The installer will automatically install the appropriate version (32-Bit or 64-Bit) depending on your system, even though MySQL's bit version doesn't have to match Apache's and PHP's one but it's still beneficial to use the 64-bit version of your system supports it to take advantage of more than 3 GB of RAM, that's quite important as database servers tend to use a lot of RAM.
  4. We followed the steps in the installer, if you're installing this for development then the Developer defaultwill be your best option, it'll also install MySQL Workbench which is a native GUI client, thus avoiding you having to install slow web-based tools such as PHPMyAdmin if you aren't comfortable with using the command line client.
  5. Once everything is installed the installer will ask you for some basic configuration values, I recommend disabling "Open firewall port for network access" unless you want to access the database from another machine on the network.
  6. We set the root password - if it's only for development purposes and your firewall blocks incoming connections from the network then a strong password isn't necessary.
  7. Finally, you can disable the useless MySQL Notifier by right-clicking the tray icon, going into Actions -> Options, then untick the Run at Windows Startup checkbox and apply. That'll save you a few MBs of RAM and avoid slowing your machine down when it's booting.
  8. And that's it, you now have a fully functional WAMP server that runs as a service and doesn't depend on any user (accessible even if no one is logged in).

Setting up HTTPS on a Windows Server:

  1. We created a self-signed SSL Certificate using OpenSSL

2.     We then opened the command prompt and cd to your Apache installations "bin" directory. Usually it would be:

cd "C:\Apache24\bin"

3.     We created the SSL certificate we will need the openssl.cnf files location but the default location set by OpenSSL for this file is setup according to a Linux distribution, so we needed to fix it for Windows.

4.     We setup the Windows environment variable OPENSSL_CONF to point to the openssl.cnf files location. It is usually located in "C:\ Apache24\conf\openssl.cnf" directory.

5.     So we can set it up by the following command or through the GUI interface:

6.     set OPENSSL_CONF=C:\ Apache24\conf\openssl.cnf

7.     All files generated from the following commands will reside in "C:\ Apache24\bin" folder.

8.     Now that we had the environment variable set we need to create a new OpenSSL certificate request using the following command:

openssl req -new -out server.csr

9.     It will ask you some questions and you can safely ignore them and just answer the following questions:
PEM pass phrase: Password associated with the private key you’re generating (anything of your choice). 
Common Name: The fully-qualified domain name associated with this certificate (i.e. www.your-domain.com).

10.  Now we needed to remove the passphrase from the private key. The file "server.key" was created from the following command should be only readable by the Apache server and the administrator. You should also delete the .rnd file because it contains the entropy information for creating the key and could be used for cryptographic attacks against your private key.

openssl rsa -in privkey.pem -out server.key

11.  We needed to set up an expiration date. This could be any time of your choice, we used a limit of 365 days below:

openssl x509 -in server.csr -out server.cert -req -signkey server.key -days 365

12.  We then had a Self-signed SSL certificates ready to go. We need to MOVE the "server.cert" and "server.key" file to the

C:\ Apache24\conf" location.

Configuring Apache to run SSL/HTTPS server:

1.     Now that we had the Self-signed SSL certificate ready, all we needed was to configure Apache to start the SSL server.

2.     First we modified the "C:\ Apache24\conf\httpd.conf" file.

3.     We opened up conf\httpd.conf in a text editor and looked for the line:

4.     LoadModule ssl_module modules/mod_ssl.so and remove any pound sign (#) characters preceding it.

5.     We included conf/extra/httpd-ssl.conf and removed any pound sign (#) characters preceding it.

6.     We modied the "C:\ Apache24\conf\extra\httpd-ssl.conf". We let all the default options as is but make sure to modify the following section according to your need:

<VirtualHost _default_:443>
ServerAdmin some@email.com
DocumentRoot "Your Root folder location"
ServerName www.domain.com:443
ServerAlias domain.com:443
ErrorLog "logs/anyFile-error.log"
CustomLog "logs/anyFile-access.log" common
SSLEngine on

SSLCertificateFile "C:/Apache24/conf/server.cert"

SSLCertificateKeyFile "C:/Apache24/conf/server.key"

7.     Make sure that "SSLCertificateFile" and "SSLCertificateKeyFile" are properly located.

8.     For better organization, you can also put the whole <VirtualHost></VirtualHost> section in the "C:\ Apache24\conf\extra\httpd-vhosts.conf" along with your other Virtual Host settings there but you need to uncomment “Include conf/extra/httpd-vhosts.conf” in your conf\httpd.conf file to use that format.

Opening SSL/HTTPS port on Windows:

1.     Now we need to open an exception in Windows Firewall for TCP port 443. You can do that by going to “Windows Firewall” settings in Control Panel and adding a port in the exception section.

2.     We restarted the server and everything worked!

Getting PHP CURL to Call HTTPS URLs on Windows:

We ran into a snag with using PHP CURL, but the Community helped us out! Here’s what we did to fix the issue.

1.     We downloaded the root CA certificates from a known good source. The most common is:http://curl.haxx.se/docs/caextract.html (If you don’t want to download it this way and instead want to build it yourself you can use the perl script on that page or the VBS script here: https://raw.github.com/bagder/curl/master/lib/mk-ca-bundle.vbs

2.     We copied this file to the location c:\apache24\conf\cacert.pem

3.     If you’re running PHP version 5.3.7 or later you can edit your PHP.INI file to include: curl.cainfo = “C:/apache24/conf/cacert.pem”  Where PATH_TO is your actual path (c:/windows for example)

4.     That’s it!!! Problem fixed.  If you’re not running 5.3.7 or don’t have access to the PHP.INI file then you’ll add these two lines to your php script where you set your CURL options in the script:

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt ($ch, CURLOPT_CAINFO, “pathto/cacert.pem”);

KennethWare Setup

You will need to download the KennethWare 2.0 files from GitHub (https://github.com/CIDI/kennethware-2.0)

Note: It is highly recommended that you initially setup KennethWare in the Beta or Test instance of Canvas!

Where to start off was our “chicken vs. the egg” conundrum.  We started with the Canvas instance setup.

1.     We created an API token.  Anyone can create the API token, but we recommend that you have one of your Canvas Admin’s create it.

2.     We went to https://yourcanvasinstance.instructure.com/profile/settings and generated the API Token.  We labeled our Purpose: Canvas Tools and did not set an expiration date.

3.     We copied the code to safe place:


4.     We created Developer Keys. https://ourcanvasinstance.instructure.com/accounts/1/developer_keys and used the following settings on Developer Key

Key Name: Canvas Tools

Owner Email: lmsadmin@ourschool.edu

Tool ID: canvastools

Redirect URI:  https://yourwindowsserver.com/canvastools

Icon URL: https://yourwindowsserver.com/canvastools/images/icon.png

(You can leave Icon URL blank or use https://community.canvaslms.com/resources/images/palette-1035/faviconImage-1441869781885-16x16-no-bg... if you want to use a gray Canvas Logo.)

5.     We took Developer Keys ID and Key and copied it to a safe place that could copied and pasted later.  The ID and Key values are going to be copied into the config.php into $client_id =  and $clientSecret = fields.

6.     We added the code from canvasGlobal.js and canvasGlobal.css to our global Javascript and CSS files on our Canvas instance.

7.     We saved a copy the config-example.php to config.php and modified the following code:


            // Display any php errors (for development purposes)


            ini_set('display_errors', '1');


            /* TEMPLATE WIZARD CONFIG  */


            // The URL for where the "wizard" folder is located

            $_SESSION['template_wizard_url'] = 'https://yourwindowsserver.com/canvastools/wizard';

            require_once __DIR__.'/wizard/resources/blti.php';

            require_once __DIR__.'/wizard/resources/cryptastic.php';

            require_once __DIR__.'/wizard/resources/meekrodb2.2.class.php';


            // Database connection information for Template Wizard

            DB::$host ='localhost';

    DB::$port = '3306';

            DB::$user = 'root';

            DB::$password = 'OurDBPass';

            DB::$dbName = 'templatewizard';

            // Strings to help encrypt/decrypt user OAuth tokens

            $pass = 'xyz123';

            $salt = '123xyz';

            // Your Canvas OAuth2 Developer information. Used for getting OAuth tokens from users

            $client_id = '#############';

            $clientSecret = 'anotherrandomlistoflettersandnumbers';


            // The Shared Secret you use when setting up the Template Wizard LTI tool

            $lti_secret = "canvastools2016";

//You will need to use this field if you add KennethWare as an LTI.

            // Message to display if the OAuth token request fails

            $oauth_error_message = 'There is a problem, contact someone to fix it';

            // TEMPLATE ARRAY (templateName, minWidth,minHeight, ratioX,ratioY)

            // This array is for customizing banner images for template themes

            $templates = array (

                        array('kl_fp_horizontal_nav_2', 1050,312, 215,64),

                        array('kl_fp_panel_nav_2', 1050,312,  215,64),

                        array('kl_fp_squares_1x1', 320,320,  1,1),

                        array('kl_fp_circles_1x1', 320,320,  1,1)


            // RATIO ARRAY (ratioX, ratioY)

            $ratios = array (

                        array (1,1),








            /* TOOLS API CONFIG  */


            // These variables for the Content Tools to make API calls

            $canvasDomain = 'https://yourcanvasinstance.com';

            // This OAuth token needs to make GET API calls for any course in your institution

            $apiToken = "1345~ thisisjustasamplestringtoshowthereallylongapicode ";


8.     We imported the tokens.sql file to our MySQL Database called Canvas_Tools

9.     We went to the folder and file js\tools-variables-example.js and saved as a new file called tools-variables.js

10.  We navigated to the images and wizard\resources\images and used Photoshop to modify the USU-related images to fit our school’s branding. We did this same for all banners and template_thumbs.

11.  We uploaded our KennethWare folder to our Windows Server C:\apache24\htdocs\canvastools\

12.  We opened the folder and file wizard\ltiCode-example-enabled.xml and modified the following settings:

<?xml version="1.0" encoding="UTF-8"?>

<cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"

    xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"

    xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"

    xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"

    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd

http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd

    http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd

    http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">

    <blti:title>Canvas Tools</blti:title>

    <blti:description>Canvas course design and templating tools to help customize look of a course</blti:description>


    <blti:launch_url> https://yourwindowsserver.com/canvastools/wizard/controller.php</blti:launch_url>

    <blti:extensions platform="canvas.instructure.com">

      <lticm:property name="tool_id">course_design_tools_1</lticm:property>

      <lticm:property name="privacy_level">public</lticm:property>

      <lticm:property name="domain">yourwindowsserver.com/canvastools/</lticm:property>

      <lticm:options name="course_navigation">

        <lticm:property name="url">https:// yourwindowsserver.com/canvastools/wizard/controller.php</lticm:property>

        <lticm:property name="text">Canvas Tools</lticm:property>

        <lticm:property name="visibility">admins</lticm:property>

        <lticm:property name="default">enabled</lticm:property>

        <lticm:property name="enabled">true</lticm:property>



    <cartridge_bundle identifierref="BLTI001_Bundle"/>

    <cartridge_icon identifierref="BLTI001_Icon"/>


13.  We went to the Settings/Apps tab and clicked “View App Configurations” and then “Add App”

14.  We went set the Configuration Type to “Paste XML” and used the settings

Name: Canvas Tools

Consumer Key: canvastools 

Shared Secret: canvastools2016

XML Configuration: copied all text inside the ltiCode-example-enabled.xml file to the field

Click Submit.

KennethWare is Now Ready to Test

1.     We opened a Demo Course on our Canvas instance and clicked on the external tool link “Canvas Tools”. 

2.     You will need to Authorize the LTI. 

3.     You will see a large chunk of text that will include lines like “OAuth2 Response Code:” and “OAuth token response:”, etc. This is normal!

4.     Click the link Proceed to tool index page

5.     Hurray!!!

You are now officially a KennethWare campus!  Rejoice as your faculty, administration, and course designers are heralding your mere footsteps!!!

Many thanks go out to the Community for posting so many excellent questions and responses about setting up KennethWare!  

Special thanks to  @kenneth_larsen ,  @tatiana_peisl ​, &  @enorthrup  for contributing numerous invaluable threads on KennethWare that helped to make our Canvas instance harness the awesomeness of KennethWare 2.0!!!