...
How to install canvas lms on ubuntu vps
Learn how to install canvas lms on ubuntu vps!

This article provides a guide demonstrating how to install Canvas LMS on Ubuntu VPS.

Table of Contents

What is Canvas LMS?

Canvas LMS is a powerful open-source Learning Management System developed by Instructure. It provides course management, assignments, grading, discussions, quizzes, user enrollment, integrations, APIs, and many of the features commonly required by schools, universities, training organizations, and corporate learning environments.

Although Instructure offers Canvas as a hosted commercial service, the open-source edition can be installed on your own Ubuntu VPS.

This guide walks through deploying a production-ready Canvas LMS server on Ubuntu 22.04 LTS, including:

  • PostgreSQL
  • Ruby 3.4
  • Node.js 20
  • Yarn
  • Redis
  • Canvas LMS
  • Apache
  • Phusion Passenger
  • Background workers
  • HTTPS using Let’s Encrypt
  • SMTP configuration
  • Basic production hardening

Canvas is considerably more resource-intensive than a typical WordPress or small Rails application. Instructure recommends at least 8 GB of RAM when the web application, database, Redis, and background workers are running on the same machine.

For a small production installation, a sensible starting VPS configuration is:

Resource Recommended
CPU 4 vCPU or more
RAM 16 GB minimum
Storage 256 GB SSD/NVMe
OS Ubuntu 22.04 LTS
Database PostgreSQL 14+
Redis Redis 6+
Ruby Ruby 3.4.1+
Node.js Node.js 20+

For larger deployments, PostgreSQL, Redis, Canvas web nodes, background workers, and object storage should eventually be separated.
Launch 100% ssd ubuntu vps from $3. 19/mo!


Compare Ubuntu VPS Plans

KVM-SSD-1
KVM-SSD-8
KVM-SSD-16
KVM-SSD-32
CPU
1 Core
2 Cores
4 Cores
8 Cores
Memory
1 GB
8 GB
16 GB
32 GB
Storage
16 GB NVMe
128 GB NVMe
256 GB NVMe
512 GB NVMe
Bandwidth
1 TB
4 TB
8 TB
16 TB
Network
1 Gbps
1 Gbps
1 Gbps
1 Gbps
Delivery Time
⏱️ Instant
⏱️ Instant
⏱️ Instant
⏱️ Instant
Location
US/EU/APAC
US/EU/APAC
US/EU/APAC
US/EU/APAC
Price
$7.58*
$39.50*
$79.40*
$151.22*
KVM-SSD-1
$7.58*
CPU 1 Core
Memory 1 GB
Storage 16 GB NVMe
Bandwidth 1 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-8
$39.50*
CPU 2 Cores
Memory 8 GB
Storage 128 GB NVMe
Bandwidth 4 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-16
$79.40*
CPU 4 Cores
Memory 16 GB
Storage 256 GB NVMe
Bandwidth 8 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC
KVM-SSD-32
$151.22*
CPU 8 Cores
Memory 32 GB
Storage 512 GB NVMe
Bandwidth 16 TB
Network 1 Gbps
Delivery Time ⏱️ Instant
Location US/EU/APAC

How to Install Canvas LMS on Ubuntu VPS

To install Canvas LMS on Ubuntu VPS, follow the steps below:

1. Prepare the DNS Records

Before installing Canvas, create DNS records pointing to your VPS.

For example:

canvas.example.com       A       192.0.2.10
canvasfiles.example.com  A       192.0.2.10

Replace 192.0.2.10 with the public IP address of your VPS.

The second hostname is important because Canvas recommends serving user-uploaded content from a hostname separate from the main Canvas application. Instructure specifically notes that files_domain should be a different hostname from the browser’s perspective, even if both hostnames ultimately point to the same web server.

Throughout this guide, replace:

canvas.example.com

with your actual Canvas hostname.

2. Connect to the Ubuntu VPS

Connect over SSH:

ssh root@SERVER_IP

Update the server:

apt update
apt upgrade -y

Install some basic utilities:

apt install -y \
    curl \
    wget \
    git \
    nano \
    unzip \
    ca-certificates \
    gnupg \
    software-properties-common \
    build-essential

Set the hostname if necessary:

hostnamectl set-hostname canvas.example.com

Confirm:

See Also: How to Install Dokploy on Ubuntu VPS

hostnamectl

3. Create an Administrative User

Although you can initially configure the server as root, it is better to create a normal sudo-enabled administrator.

For example:

adduser canvasadmin

Add the account to the sudo group:

usermod -aG sudo canvasadmin

Switch to it:

su - canvasadmin

For the remainder of the guide, commands requiring elevated privileges use sudo.

4. Configure the Firewall

If UFW is enabled, allow SSH, HTTP, and HTTPS:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Enable UFW:

sudo ufw enable

Check the rules:

sudo ufw status

You should see ports 22, 80, and 443 allowed.

Do not expose PostgreSQL or Redis publicly when they are installed locally.

5. Install PostgreSQL

Canvas uses PostgreSQL for its production database and currently requires PostgreSQL 14 or newer.

Ubuntu 22.04 provides PostgreSQL 14:

sudo apt install -y postgresql postgresql-contrib libpq-dev

Start and enable PostgreSQL:

sudo systemctl enable --now postgresql

Verify:

sudo systemctl status postgresql

Check its version:

psql --version

You should have PostgreSQL 14 or newer.

6. Create the Canvas PostgreSQL User and Database

Create a dedicated PostgreSQL account:

sudo -u postgres createuser canvas \
    --no-createdb \
    --no-superuser \
    --no-createrole \
    --pwprompt

You will be prompted to create a database password.

Use a long random password and save it securely.

For example:

YOUR_STRONG_DATABASE_PASSWORD

Create the Canvas production database:

sudo -u postgres createdb canvas_production --owner=canvas

Verify:

sudo -u postgres psql -c "\l"

You should see:

canvas_production

owned by:

canvas

Test the database login:

psql -h localhost -U canvas -d canvas_production

Enter the database password.

If successful, quit PostgreSQL with:

\q

7. Install Redis

Redis is strongly recommended by Canvas and is required by some Canvas functionality, including OAuth-related functionality. The current production documentation specifies Redis 6.x or later.

Install Redis:

sudo apt install -y redis-server

Enable it:

sudo systemctl enable --now redis-server

Test Redis:

redis-cli ping

Expected response:

PONG

Check the version:

redis-server --version

For a single-server installation, Redis should remain bound to localhost.

Check:

sudo ss -lntp | grep 6379

You generally want Redis listening only on:

127.0.0.1:6379

or another private/internal address.

8. Install Canvas Ruby Dependencies

Current Canvas releases require at least Ruby 3.4.1. Ruby 3.5+ is currently described by the Canvas production documentation as untested.

Instructure maintains an Ubuntu Ruby PPA.

Add it:

sudo add-apt-repository -y ppa:instructure/ruby
sudo apt update

Install Ruby and the required development libraries:

See Also: 7 Steps to Easily Configure OpenLiteSpeed as a Reverse Proxy for Metabase

sudo apt install -y \
    ruby3.4 \
    ruby3.4-dev \
    zlib1g-dev \
    libxml2-dev \
    libsqlite3-dev \
    libpq-dev \
    libxmlsec1-dev \
    libyaml-dev \
    libidn11-dev \
    curl \
    make \
    g++

These dependencies closely follow Instructure’s current production installation recommendations.

Check Ruby:

ruby --version

You want something similar to:

ruby 3.4.x

If Ubuntu still points ruby at another version, inspect:

which ruby
ruby --version

9. Install Node.js 20

Canvas currently requires Node.js 20 or newer, and the current source tree specifies Node.js >=20.0.0. The repository’s .nvmrc currently points to Node 20.9.0.

Install Node.js 20 from NodeSource:

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -

Install Node:

sudo apt install -y nodejs

Check it:

node --version
npm --version

You should see Node 20.x or newer.

10. Install Yarn

Canvas continues to use Yarn 1.x for its JavaScript dependency tree. The current package configuration specifies Yarn ^1.19.1.

Install Yarn:

sudo npm install -g yarn

Check:

yarn --version

A Yarn 1.x release should be returned.

Do not use Yarn Berry/Yarn 2+ unless the Canvas source branch explicitly changes its package requirements.

11. Create the Canvas Runtime User

Create a dedicated system account that will run Canvas:

sudo adduser \
    --disabled-password \
    --gecos "" \
    canvasuser

Canvas will ultimately run under this account instead of root.

12. Download Canvas LMS

Move to a temporary working directory:

cd ~

Clone the official repository:

git clone https://github.com/instructure/canvas-lms.git

Enter it:

cd canvas-lms

For a production installation, use Instructure’s production branch:

git checkout prod

The official Production Start documentation currently recommends the prod branch for production deployments.

Confirm:

git branch --show-current

Expected:

prod

13. Move Canvas to /var/canvas

Create the production application directory:

sudo mkdir -p /var/canvas

Give your administrative user temporary ownership:

sudo chown -R "$USER":"$USER" /var/canvas

Copy the Canvas application:

cp -a ~/canvas-lms/. /var/canvas/

Enter the application directory:

cd /var/canvas

Confirm:

ls

You should see directories such as:

app
config
db
doc
gems
lib
public
script
ui

along with:

Gemfile
Rakefile
package.json

14. Install Bundler

Canvas uses Bundler to manage its Ruby dependencies.

The current Canvas lock file identifies Bundler 2.6.7, so installing that version avoids unnecessary dependency-resolution differences.

Install Bundler:

sudo gem install bundler -v 2.6.7

Verify:

bundle --version

Configure dependencies to install underneath the Canvas tree:

bundle config set --local path vendor/bundle

Then install the gems:

See Also: 🚀 How to Deploy Apache JMeter on Ubuntu VPS

bundle install

This can take several minutes and consume substantial CPU and RAM.

If compilation fails, review the error carefully. Most gem failures indicate a missing development library rather than a Canvas problem.

15. Install Canvas JavaScript Dependencies

From /var/canvas:

yarn install

This downloads a substantial dependency tree.

Verify it completes without errors.

If Yarn complains about Node compatibility, check:

node --version

and:

cat package.json | grep -A3 '"engines"'

Do not bypass engine checks unless you have a very specific reason to do so.

16. Create Canvas Configuration Files

Canvas ships example configuration files that must be copied before initialization.

Run:

cd /var/canvas

Then:

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

Also create the dynamic settings file:

cp config/dynamic_settings.yml.example config/dynamic_settings.yml

17. Configure the Database

Edit:

nano config/database.yml

Find the production section and configure it similar to:

production:
  adapter: postgresql
  encoding: utf8
  database: canvas_production
  host: localhost
  username: canvas
  password: "YOUR_STRONG_DATABASE_PASSWORD"
  timeout: 5000

Save the file.

Test the credentials independently if needed:

PGPASSWORD='YOUR_STRONG_DATABASE_PASSWORD' \
psql -h localhost -U canvas -d canvas_production -c "SELECT version();"

If PostgreSQL responds, Canvas should be able to connect as well.

18. Configure the Canvas Domain

Edit:

nano config/domain.yml

Configure the production section:

production:
  domain: "canvas.example.com"
  ssl: true
  files_domain: "canvasfiles.example.com"

The important values are:

domain
files_domain
ssl

Use only hostnames here; do not add:

https://

before the domain unless the particular setting explicitly calls for a URL.

19. Configure Canvas Security Secrets

Copying the example already created:

config/security.yml

Edit it:

nano config/security.yml

Canvas requires randomized secret values. The official documentation requires random strings of at least 20 characters.

Generate strong secrets with:

openssl rand -hex 64

Run the command separately for each required secret.

For example:

openssl rand -hex 64
openssl rand -hex 64
openssl rand -hex 64

Place the generated strings into the corresponding production values in security.yml.

Never reuse the example secrets in production.

Never publish this file.

20. Configure Redis

Create the Redis configuration:

cp config/redis.yml.example config/redis.yml

Edit it:

nano config/redis.yml

Configure:

production:
  url:
    - redis://127.0.0.1:6379/0

Now configure Canvas caching:

See Also: 🚀 How to Install and Run Rocket.Chat on Debian VPS

cp config/cache_store.yml.example config/cache_store.yml

Edit:

nano config/cache_store.yml

Use:

production:
  cache_store: redis_cache_store

This matches the Redis cache configuration recommended in the current Canvas Production Start documentation.

21. Configure Outgoing Email

Canvas relies heavily on email for notifications, invitations, password resets, announcements, and course activity.

Edit:

nano config/outgoing_mail.yml

A typical authenticated SMTP configuration resembles:

production:
  address: "smtp.example.com"
  port: "587"
  user_name: "canvas@example.com"
  password: "YOUR_SMTP_PASSWORD"
  authentication: "plain"
  enable_starttls_auto: true
  domain: "example.com"
  outgoing_address: "canvas@example.com"
  default_name: "Canvas LMS"

Replace these settings with your SMTP provider’s actual information.

The domain and outgoing_address fields describe Canvas’s outbound identity, while the SMTP address, credentials, and port describe the mail server connection.

For production email deliverability, also configure:

  • SPF
  • DKIM
  • DMARC
  • valid PTR/rDNS where applicable

22. Prepare Canvas Runtime Directories

Create required directories:

cd /var/canvas

Run:

mkdir -p \
    log \
    tmp/pids \
    public/assets \
    app/stylesheets/brandable_css_brands

Create required files:

touch app/stylesheets/_brandable_variables_defaults_autogenerated.scss
touch log/production.log

23. Initialize the Canvas Database

Before running initialization, generate the asset revision:

yarn gulp rev

Now run the initial Canvas database setup:

RAILS_ENV=production bundle exec rake db:initial_setup

Canvas will prompt for information including:

Admin email
Admin password
Organization/account name
Usage statistics preference

For example:

Admin email:
admin@example.com

Account name:
Example University

Use a strong administrator password.

Canvas also supports environment variables for automating these answers:

CANVAS_LMS_ADMIN_EMAIL
CANVAS_LMS_ADMIN_PASSWORD
CANVAS_LMS_ACCOUNT_NAME
CANVAS_LMS_STATS_COLLECTION

The official installer supports opt_in, opt_out, or anonymized for statistics collection.

After initialization, your Canvas database should contain the required schema and initial administrator account.

24. Compile Canvas Production Assets

Canvas must build its CSS, JavaScript, branding, and other static assets before the interface will work correctly.

Run:

cd /var/canvas

Then:

RAILS_ENV=production \
SASS_STYLE=compressed \
bundle exec rake canvas:compile_assets

Asset compilation is one of the most resource-intensive stages of the installation.

On a smaller VPS, compilation may fail because of memory exhaustion.

If necessary, temporarily create swap:

sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Verify:

free -h

You can also reduce Canvas build concurrency:

See Also: 🚀 How to Deploy Coolify on Ubuntu VPS

export CANVAS_BUILD_CONCURRENCY=1

Then rerun the asset compilation.

Recent Canvas deployment experience confirms that missing or failed asset compilation can leave the Rails application technically accessible while the UI is incomplete, broken, or unstyled.

25. Set Canvas File Ownership

Set the Canvas runtime user as the owner of files it must modify:

sudo chown -R canvasuser:canvasuser \
    /var/canvas/log \
    /var/canvas/tmp \
    /var/canvas/public/assets \
    /var/canvas/public/dist \
    /var/canvas/app/stylesheets/brandable_css_brands

Also:

sudo chown canvasuser:canvasuser \
    /var/canvas/config/environment.rb \
    /var/canvas/config.ru \
    /var/canvas/app/stylesheets/_brandable_variables_defaults_autogenerated.scss

Protect sensitive configuration files:

sudo chown canvasuser:canvasuser /var/canvas/config/*.yml
sudo chmod 400 /var/canvas/config/*.yml

Canvas’s production documentation specifically recommends restricting these YAML files because they can contain database passwords, SMTP credentials, encryption keys, and other secrets.

26. Install Apache

Canvas’s official production deployment guide uses Apache + Phusion Passenger.

Install Apache:

sudo apt install -y apache2

Enable common required modules:

sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers

27. Install Phusion Passenger

Install the repository prerequisites:

sudo apt install -y \
    dirmngr \
    gnupg \
    apt-transport-https \
    ca-certificates \
    curl

Install Phusion’s current signing key:

curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key-2025.txt \
    | gpg --dearmor \
    | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null

Add the Ubuntu 22.04/Jammy Passenger repository:

echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger jammy main" \
    | sudo tee /etc/apt/sources.list.d/passenger.list

Update:

sudo apt update

Install Passenger’s Apache module:

sudo apt install -y libapache2-mod-passenger

Enable Passenger:

sudo a2enmod passenger

Restart Apache:

sudo systemctl restart apache2

These commands use Phusion’s current repository/key installation method rather than the older deprecated apt-key workflow.

Validate Passenger:

sudo passenger-config validate-install

All checks should pass.

28. Tell Passenger Which Ruby to Use

Determine Ruby’s location:

which ruby

For example:

/usr/bin/ruby

Inspect Passenger configuration:

sudo nano /etc/apache2/mods-available/passenger.conf

Ensure Passenger is using the correct Ruby.

For example:

PassengerRuby /usr/bin/ruby
PassengerDefaultUser canvasuser

Verify Ruby:

/usr/bin/ruby --version

Make sure it reports Ruby 3.4.x.

Restart Apache:

sudo systemctl restart apache2

29. Create the Canvas Apache VirtualHost

Disable the default Apache site:

sudo a2dissite 000-default.conf

Create:

sudo nano /etc/apache2/sites-available/canvas.conf

Initially configure HTTP:

    ServerName canvas.example.com
    ServerAlias canvasfiles.example.com

    ServerAdmin admin@example.com

    DocumentRoot /var/canvas/public

    SetEnv RAILS_ENV production

    PassengerAppEnv production
    PassengerDefaultUser canvasuser

    
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    

    ErrorLog ${APACHE_LOG_DIR}/canvas_error.log
    CustomLog ${APACHE_LOG_DIR}/canvas_access.log combined


Enable it:

See Also: Easily Deploy NodeBB Community Forum on Ubuntu VPS

sudo a2ensite canvas.conf

Check the configuration:

sudo apachectl configtest

Expected:

Syntax OK

Restart Apache:

sudo systemctl restart apache2

30. Test Canvas Before Adding SSL

Check Apache:

sudo systemctl status apache2

Check Canvas:

curl -I http://canvas.example.com/

Also check:

curl -I http://canvas.example.com/health_check

If Canvas starts correctly, you should receive an HTTP response rather than a Passenger application error.

You can also watch Canvas’s production log:

sudo tail -f /var/canvas/log/production.log

And Apache:

sudo tail -f /var/log/apache2/canvas_error.log

These two logs are extremely useful during initial deployment.

31. Install Let’s Encrypt SSL

Install Certbot:

sudo apt install -y certbot python3-certbot-apache

Request certificates for both Canvas hostnames:

sudo certbot --apache \
    -d canvas.example.com \
    -d canvasfiles.example.com

Certbot will:

  1. Validate the DNS records.
  2. Request the certificates.
  3. Modify the Apache VirtualHost.
  4. Configure HTTPS.
  5. Optionally redirect HTTP to HTTPS.

Verify renewal:

sudo certbot renew --dry-run

Check the timer:

systemctl status certbot.timer

32. Verify HTTPS

Test:

curl -I https://canvas.example.com/

Then:

curl -I https://canvas.example.com/health_check

Open:

https://canvas.example.com

in your browser.

You should reach the Canvas login interface.

Log in using the administrator credentials created during:

RAILS_ENV=production bundle exec rake db:initial_setup

33. Configure Canvas Background Jobs

Canvas relies heavily on background jobs for:

  • email notifications
  • reports
  • statistics
  • course operations
  • file processing
  • scheduled tasks
  • imports and exports
  • other asynchronous actions

Canvas will not function correctly without the background job worker.

The Canvas source includes:

/var/canvas/script/canvas_init

Create the service link:

sudo ln -s /var/canvas/script/canvas_init /etc/init.d/canvas_init

Register it:

sudo update-rc.d canvas_init defaults

Start it:

sudo /etc/init.d/canvas_init start

Check processes:

ps aux | grep delayed_job

You should see Canvas delayed job workers.

The current Canvas source still contains the canvas_init script, and its purpose is specifically to start and stop Canvas background jobs under RAILS_ENV=production.

For a larger installation, you can dedicate one or more separate Canvas application nodes exclusively to processing these background jobs.

34. Verify Canvas Services

Check PostgreSQL:

sudo systemctl status postgresql

Check Redis:

sudo systemctl status redis-server

Check Apache:

See Also: 🚀 Deploy Poweradmin to Manage PowerDNS on Ubuntu VPS

sudo systemctl status apache2

Check Passenger:

sudo passenger-memory-stats

Check workers:

ps aux | grep delayed_job

Check HTTP:

curl -I https://canvas.example.com/

Check health endpoint:

curl -I https://canvas.example.com/health_check

35. Test Redis from Canvas

You can verify that Rails boots in production mode:

cd /var/canvas

Run:

sudo -u canvasuser \
RAILS_ENV=production \
bundle exec rails runner 'puts Rails.env'

Expected:

production

You can also check Redis directly:

redis-cli ping

Expected:

PONG

36. Test Outgoing Email

After logging into Canvas, configure an account with a valid email address and trigger a notification or password reset.

Watch:

sudo tail -f /var/canvas/log/production.log

If delivery fails, common causes include:

  • incorrect SMTP password
  • blocked SMTP port
  • wrong TLS mode
  • invalid sender address
  • provider requiring SMTP AUTH
  • SPF/DKIM misconfiguration
  • VPS provider blocking outbound port 25

Where possible, use authenticated SMTP submission over:

587

rather than sending directly over port 25.

37. Optional: Enable X-Sendfile

If Canvas stores uploaded files locally, Apache’s X-Sendfile support can improve file download performance by allowing Apache to serve file content directly instead of passing it through Rails.

Install:

sudo apt install -y libapache2-mod-xsendfile

Verify:

sudo apachectl -M | grep xsendfile

You should see:

xsendfile_module

Add to the Canvas VirtualHost:

XSendFile On
XSendFilePath /var/canvas

Canvas’s production documentation recommends this optimization for installations using local file storage.

Restart Apache:

sudo systemctl restart apache2

38. Understand the Canvas Files Domain

Canvas should ideally use:

canvas.example.com

for the application and:

canvasfiles.example.com

for uploaded content.

This provides a security boundary between the Canvas application and user-controlled files.

Both DNS records can point to the same VPS:

canvas.example.com       -> VPS IP
canvasfiles.example.com  -> VPS IP

and both can be handled by the same Apache configuration.

What matters is that browsers see them as separate origins.

39. Consider Object Storage for Production

Local disk storage works for a small Canvas installation, but it becomes a limitation as course uploads grow.

For a more scalable deployment, consider S3-compatible object storage.

That allows Canvas web servers to remain relatively disposable while uploaded content lives independently.

A more scalable architecture might look like:

                         +-------------------+
                         |  Load Balancer    |
                         +---------+---------+
                                   |
                         +---------+---------+
                         |                   |
                  +------v------+     +------v------+
                  | Canvas Web 1 |     | Canvas Web 2 |
                  +------+------+     +------+-------+
                         |                   |
                         +---------+---------+
                                   |
              +--------------------+--------------------+
              |                    |                    |
       +------v------+      +------v------+      +------v------+
       | PostgreSQL  |      |    Redis    |      | Object/S3   |
       +-------------+      +-------------+      +-------------+
                                   |
                            +------v------+
                            | Canvas Jobs |
                            +-------------+

For a small VPS, however, running everything on one host is a reasonable starting point.

40. Configure Automatic Security Updates

Install:

See Also: Top 12 Best VPS Control Panels

sudo apt install -y unattended-upgrades

Enable:

sudo dpkg-reconfigure --priority=low unattended-upgrades

Remember that Canvas itself is not updated through Ubuntu’s package manager because it was installed from Git.

41. Back Up Canvas

At minimum, back up:

PostgreSQL

sudo -u postgres pg_dump \
    -Fc \
    canvas_production \
    > /root/canvas_production.dump

Canvas configuration

sudo tar czf /root/canvas-config.tar.gz \
    /var/canvas/config

Uploaded files

If using local file storage, back up the Canvas file store as well.

SSL certificates

Certbot certificates live under:

/etc/letsencrypt

A proper backup strategy should therefore protect:

PostgreSQL database
Canvas uploaded files
/var/canvas/config
/etc/letsencrypt
custom branding/themes
external integration credentials

Do not rely only on a VPS snapshot as your sole backup.

42. Updating Canvas LMS

Before every update:

  1. Back up PostgreSQL.
  2. Back up configuration.
  3. Take a VPS snapshot if available.
  4. Review Canvas changes before deploying.
  5. Schedule maintenance if necessary.

Enter Canvas:

cd /var/canvas

Confirm the branch:

git status
git branch --show-current

Retrieve updates:

git fetch origin

Update the production branch:

git checkout prod
git pull

Install Ruby dependencies:

bundle install

Install JavaScript dependencies:

yarn install

Run database migrations:

RAILS_ENV=production bundle exec rake db:migrate

Recompile assets:

RAILS_ENV=production \
SASS_STYLE=compressed \
bundle exec rake canvas:compile_assets

Canvas’s production documentation also recommends regenerating existing themes after subsequent updates:

RAILS_ENV=production \
bundle exec rake brand_configs:generate_and_upload_all

Restore ownership:

sudo chown -R canvasuser:canvasuser \
    /var/canvas/log \
    /var/canvas/tmp \
    /var/canvas/public/assets \
    /var/canvas/public/dist

Restart workers:

sudo /etc/init.d/canvas_init restart

Restart Apache:

sudo systemctl restart apache2

Then test:

curl -I https://canvas.example.com/health_check

43. Useful Troubleshooting Commands

Check Canvas

sudo tail -100 /var/canvas/log/production.log

Or follow live:

sudo tail -f /var/canvas/log/production.log

Check Apache

sudo tail -100 /var/log/apache2/canvas_error.log

Check Apache syntax

sudo apachectl configtest

Expected:

Syntax OK

Check Passenger

sudo passenger-config validate-install

And:

sudo passenger-memory-stats

Check PostgreSQL

sudo systemctl status postgresql

Test the database:

psql -h localhost \
    -U canvas \
    -d canvas_production

Check Redis

redis-cli ping

Expected:

PONG

Check Canvas workers

ps aux | grep delayed_job

Verify the installed versions

ruby --version
node --version
yarn --version
psql --version
redis-server --version
apache2 -v

44. Canvas Returns HTTP 500

Start with:

sudo tail -100 /var/canvas/log/production.log

Then:

sudo tail -100 /var/log/apache2/canvas_error.log

Common causes are:

See Also: Laravel vs Symfony: A Comprehensive Comparison of PHP Frameworks

  • database credentials are incorrect
  • security.yml is incomplete
  • Canvas cannot read configuration files
  • Passenger is using the wrong Ruby
  • database initialization was not completed
  • pending database migrations
  • Redis configuration is invalid
  • Canvas runtime directories are not writable

Check database state:

cd /var/canvas
RAILS_ENV=production bundle exec rake db:migrate:status

45. Canvas Loads but Has No CSS

This almost always indicates a problem with compiled assets or static asset delivery.

Recompile:

cd /var/canvas

Then:

RAILS_ENV=production \
SASS_STYLE=compressed \
bundle exec rake canvas:compile_assets

Check:

ls -lah public/dist

And:

ls -lah public/assets

Repair ownership:

sudo chown -R canvasuser:canvasuser \
    public/dist \
    public/assets

Then restart Apache:

sudo systemctl restart apache2

Asset compilation is mandatory; Canvas may otherwise answer requests while presenting a broken interface.

46. Passenger Reports a Ruby Error

Check what Canvas itself sees:

cd /var/canvas
ruby --version
bundle exec ruby --version

Then inspect Passenger:

sudo passenger-config about ruby-command

If Passenger is using the wrong Ruby, explicitly configure:

PassengerRuby /usr/bin/ruby

then:

sudo systemctl restart apache2

47. Background Tasks Are Not Running

Check:

ps aux | grep delayed_job

Restart:

sudo /etc/init.d/canvas_init restart

Then examine:

sudo tail -f /var/canvas/log/delayed_job.log

and:

sudo tail -f /var/canvas/log/production.log

Pay particular attention to file permissions on:

/var/canvas/config
/var/canvas/log
/var/canvas/tmp

Canvas workers need to read the protected configuration files and write to their runtime directories.

48. Production Security Checklist

Before opening the LMS to users, verify all of the following:

  • HTTPS is enabled.
  • HTTP redirects to HTTPS.
  • PostgreSQL is not exposed publicly.
  • Redis is not exposed publicly.
  • Canvas runs as canvasuser, not root.
  • Configuration files are protected.
  • SSH root authentication is restricted where practical.
  • Password authentication is disabled if SSH keys are used.
  • UFW or another firewall is configured.
  • Automatic operating-system security updates are enabled.
  • SMTP credentials are protected.
  • PostgreSQL backups are automated.
  • User-uploaded files are backed up.
  • Off-server backups exist.
  • DNS has been configured correctly.
  • SPF/DKIM/DMARC are configured for outgoing mail.
  • Canvas background workers are running.
  • /health_check responds normally.
  • PostgreSQL, Redis, Apache, and Canvas logs are monitored.

49. Recommended Production Architecture

For a small organization:

Ubuntu VPS
|
+-- Apache + Passenger
|
+-- Canvas LMS
|
+-- Canvas delayed jobs
|
+-- PostgreSQL
|
+-- Redis
|
+-- Local or S3-compatible file storage

For modest production usage, start with roughly:

See Also: Which Windows Server Versions are Available for Windows VPS?

4-8 vCPU
8-16 GB RAM
100+ GB NVMe

For heavier usage, separate components:

2+ Canvas web servers
1+ Canvas jobs server
Dedicated PostgreSQL
Dedicated Redis
S3-compatible object storage
Load balancer
Central backups
Monitoring

Canvas’s own production documentation explicitly notes that the web application, database, and job processing can be separated and that busy environments benefit from moving job processing onto dedicated nodes.

50. Final Verification

Run:

curl -I https://canvas.example.com/

Then:

curl -I https://canvas.example.com/health_check

Check all major services:

sudo systemctl status apache2
sudo systemctl status postgresql
sudo systemctl status redis-server

Check Passenger:

sudo passenger-memory-stats

Check jobs:

ps aux | grep delayed_job

Finally visit:

https://canvas.example.com

and log in with the administrator account created during db:initial_setup.

You now have a self-hosted Canvas LMS installation running on an Ubuntu VPS with PostgreSQL, Redis, Apache, Passenger, HTTPS, and Canvas background processing.

Important Version Note

Canvas LMS is under active development, so dependency requirements can change relatively quickly. As of the current Canvas source and production documentation:

Ubuntu reference platform: 22.04 LTS
Ruby:                     3.4.1+
Node.js:                  20+
PostgreSQL:               14+
Redis:                    6+
Yarn:                     1.x / ^1.19.1
Web server:               Apache + Passenger
Production branch:        prod

Instructure’s Production Start documentation was most recently updated in May 2026, and the source tree currently pins Ruby 3.4.1 in Gemfile.lock while requiring Node.js 20 or later in package.json.

Before installing a future Canvas release or performing a major upgrade, always compare these values with the current prod branch instead of assuming an older Canvas installation guide remains accurate.
Launch 100% ssd ubuntu vps from $3. 19/mo!

Conclusion

You now know how to install Canvas LMS on Ubuntu VPS.

Avatar of editorial staff

Editorial Staff

Rad Web Hosting is a leading provider of web hosting, Cloud VPS, and Dedicated Servers in Dallas, TX.

Leave a Reply

lg