Canvas LMS

Canvas Learning Management System

What is Canvas LMS?

Canvas LMS (Learning Management System) is an open-source online learning platform designed to help educators create, manage, and deliver courses online or in a blended learning environment. It provides tools for course management, communication, assessment, reporting, and integration with third-party applications.


Prerequisites

  • Ubuntu Server 22.04

Dependencies

> sudo apt install -y git curl libssl-dev libreadline-dev zlib1g-dev \
                    autoconf bison build-essential libyaml-dev libreadline-dev \
                    libncurses5-dev libffi-dev libgdbm-dev zlib1g-dev \
                    libxml2-dev libsqlite3-dev postgresql libpq-dev \
                    libxmlsec1-dev libyaml-dev libidn11-dev make g++

User and Directory

> sudo adduser canvas
> sudo visudo

Copy the line under # User privilege specification and duplicate it like this:

# User privilege specification
root    ALL=(ALL:ALL) ALL
canvas  ALL=(ALL:ALL) ALL

Create Canvas Installation Folder

> sudo mkdir -p /data
> sudo chown canvas:canvas /data

Checkout Git

> cd /data
> git clone https://github.com/instructure/canvas-lms.git canvas
> cd canvas
> git checkout prod

Install Ruby

Instructure Repo

> sudo apt install software-properties-common
> sudo add-apt-repository ppa:instructure/ruby
> sudo apt update
> sudo apt install -y ruby3.1 ruby3.1-dev zlib1g-dev libxml2-dev \
                       libsqlite3-dev libxmlsec1-dev libyaml-dev  \
                       libidn11-dev curl make g++

Rbenv

  1. Switch to the canvas user and run the following commands:
> git clone https://github.com/rbenv/rbenv.git ~/.rbenv
> echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
> echo 'eval "$(rbenv init - bash)"' >> ~/.bashrc
> source ~/.bashrc
  1. Install rbenv-build plugin:
> git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
  1. Verify installation
> rbenv -v
  1. Install Ruby
> rbenv install 3.3.3
> rbenv global 3.3.3

Using Ruby

Check these commands first:

> which bundle
> which bundler
> which gem
> bundle config set --local path vendor/bundle

Install Node.js

apt

> curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
> sudo apt-get install nodejs
> sudo npm install -g npm@latest

NVM

> curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
> nvm install 22
> nvm use 22

NPM Mirror (optional)

> npm config set registry https://registry.npmmirror.com

Yarn

If the node.js was installed by apt:

> sudo npm -g install yarn

Since we use NVM to manage Node.js, run the following command without sudo:

> npm -g install yarn

Switch to the Canvas installation folder:

> yarn install

Canvas Configuration

> for config in amazon_s3 database vault_contents \
  delayed_jobs domain file_store outgoing_mail security external_migration; \
  do cp config/$config.yml.example config/$config.yml; done

Dynamic Settings Configuration

> cp config/dynamic_settings.yml.example config/dynamic_settings.yml
> nano config/dynamic_settings.yml

Database Configuration

If you want to use a remote RDS instance, make sure the database user has a high privilege role.

> cp config/database.yml.example config/database.yml
> nano config/database.yml

Security Configuration

> cp config/security.yml.example config/security.yml
> nano config/security.yml

Domain URL Configuration

> cp config/domain.yml.example config/domain.yml
> nano config/domain.yml

Outgoing Email Configuration

> cp config/outgoing_mail.yml.example config/outgoing_mail.yml
> nano config/outgoing_mail.yml

Replace example.com with your production domain

production:
  domain: "example.com"
  # whether this instance of canvas is served over ssl (https) or not
  # defaults to true for production, false for test/development
  ssl: true
  # files_domain: "canvasfiles.example.com"

Delayed Jobs Configuration

> cp config/delayed_jobs.yml.example config/delayed_jobs.yml
> nano config/delayed_jobs.yml

The max_priority will split jobs by priority level.

production:
  workers:
  - queue: canvas_queue
    workers: 2
    max_priority: 10
  - queue: canvas_queue
    workers: 4

Database Migration

Gulp runs the rev task, which likely:

  • Appends hash-based revisions to asset filenames.
  • Updates references in your HTML, CSS, or JavaScript files.
  • Prevents browser caching issues when assets are updated.

To fully understand what the rev task does, check the gulpfile.js in your project, especially where gulp-rev or similar plugins are used.

> yarn gulp rev
> RAILS_ENV=production bundle exec rake db:initial_setup

Generate Assets

> cd <your_canvas_root_folder>
> mkdir -p log tmp/pids public/assets app/stylesheets/brandable_css_brands
> touch app/stylesheets/_brandable_variables_defaults_autogenerated.scss
> touch Gemfile.lock
> sudo chown -R <canvas_user_name> config/environment.rb log tmp public/assets \
        app/stylesheets/_brandable_variables_defaults_autogenerated.scss \
        app/stylesheets/brandable_css_brands Gemfile.lock config.ru
> RAILS_ENV=production bundle exec rake canvas:compile_assets
> chown -R <canvas_user_name> public/dist/brandable_css

Permissions

> sudo chown <canvas_user_name> config/*.yml
> sudo chmod 400 config/*.yml

Apache & Passenger

You're now going to need to set up the webserver. We're going to use Apache and Passenger to serve the Canvas content. If you are on Debian/Ubuntu, you can do this quickly by following the instructions in Phusion's Deployment Guide:

Dependencies

> sudo apt install -y dirmngr gnupg apt-transport-https ca-certificates

Install Apache

> sudo apt install apache2

Install Passenger

> curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
      gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null
> sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger \
      $(lsb_release -cs) main > /etc/apt/sources.list.d/passenger.list'

Apache Modules

> sudo a2enmod rewrite
> sudo a2enmod passenger
> sudo a2enmod ssl

Passenger Configurations

Get the ruby executable file by running the command which ruby, then copy the returned path and update the configuration below:

> sudo nano /etc/apache2/mods-enabled/passenger.conf

Replace the copied path with the value of PassengerDefaultRuby:

PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
PassengerDefaultRuby /usr/bin/passenger_free_ruby
PassengerInstanceRegistryDir /var/run/passenger-instreg
PassengerDefaultUser canvas

Apache VHost

<VirtualHost *:80>
    ServerName canvas_domain
    ServerAdmin your_email@domain.com
    DocumentRoot /data/canvas/public

    # Block /external_content/retrieve/oembed
    RewriteCond %{REQUEST_URI} ^/external_content/retrieve/oembed
    RewriteRule ^ - [F]

    ErrorLog /var/log/apache2/canvas_errors.log

    LogLevel warn
    CustomLog /var/log/apache2/canvas_access.log combined

    SetEnv RAILS_ENV production
    PassengerEnabled on
    PassengerPreloadBundler off
    
    #XSendFile On
    #XSendFilePath /data/canvas

    <Directory /data/canvas/public>
        Options All
        AllowOverride All
        Require all granted
    </Directory>
    
</VirtualHost>

Redis Server

> sudo apt install -y redis-server
> redis-server --daemonize yes
> redis-cli ping

Canvas Scripts

Run the following command to get the GEM_HOME path for the Canvas script if you are using rbenv:

> gem env home

returns: /home/canvas/.rbenv/versions/3.3.3/lib/ruby/gems/3.3.0

Edit the canvas_init file:

> nano <canvas_root_folder>/script/canvas_init

Uncomment the export GEM_HOME and replace the path:

export GEM_HOME=/home/canvas/.rbenv/versions/3.3.3/lib/ruby/gems/3.3.0

Link script as a system startup script:

> sudo ln -s /data/canvas/script/canvas_init /etc/init.d/canvas_init
> sudo update-rc.d canvas_init defaults
> sudo /etc/init.d/canvas_init start

Logging

You can configure the Canvas logging.yaml file to use a database for logging:

production:
  adapter: postgresql
  encoding: utf8
  database: canvas_production
  host: localhost
  username: canvas
  password: password
  timeout: 5000
  queue:
    adapter: postgresql
    encoding: utf8
    database: canvas_queue_production
    host: localhost
    username: canvas
    password: password
    timeout: 5000

Troubleshooting

The application encountered the following error: You have already activated stringio 3.1.1, but your Gemfile requires stringio 3.1.2. Since stringio is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports stringio as a default gem.

PassengerEnabled on
PassengerPreloadBundler off

Alternatively, try these:

> bundle update --bundler
> gem update stringio
> gem update --system
> bundle install
Previous
AliCloud
Next
Docker