Skip to content

Deploying Canvas LMS

Introduction

Canvas LMS is a modern, open-source learning management system developed and maintained by Instructure Inc. Used by millions of educators and learners worldwide, Canvas provides a flexible, scalable platform for creating engaging online courses and managing educational content. Built on Ruby on Rails with modern JavaScript and TypeScript, Canvas integrates seamlessly with 1000+ external tools and delivers an accessible, community-powered learning experience. Deploy Canvas LMS on Klutch.sh to create a self-hosted learning management system that gives you complete control over your educational technology infrastructure while maintaining the power and flexibility of a professional LMS.

Key Features

  • Course Management: Create and organize courses with rich content and learning materials
  • SpeedGrader: Streamlined grading interface for giving contextual feedback on student submissions
  • Gradebook: Comprehensive gradebook with customizable grading schemes and rubrics
  • Discussion Forums: Threaded discussions for student-to-student and teacher-to-student interaction
  • Assignment Management: Create, distribute, and grade assignments with multiple submission types
  • Quizzes and Assessments: Build interactive quizzes with various question types and randomization
  • Rubric Creation: Define detailed rubrics for consistent, transparent grading
  • Student Groups: Organize students into groups for collaborative projects and discussions
  • Rich Content Editor: Create course content with embedded media, links, and formatted text
  • Calendar Integration: Unified calendar for course events, assignments, and due dates
  • Notifications System: Automated notifications for events, announcements, and assignments
  • Mobile Learning: Full-featured mobile app for teachers and students on the go
  • API-First Architecture: Comprehensive REST API for integration and customization
  • Authentication Flexibility: Support for multiple authentication methods including LTI and SAML
  • Accessibility Standards: Strong commitment to WCAG compliance and inclusive design
  • Analytics and Reporting: Detailed course analytics and student engagement reports
  • File Management: Robust file storage and sharing system for course materials
  • Video Integration: Native support for video uploads and Canvas Studio integration
  • Plagiarism Detection: Optional integration with third-party plagiarism detection services
  • Badge and Achievement System: Gamification features for student engagement
  • Communication Tools: Announcements, messages, and notification system
  • Blueprint Courses: Template system for creating reusable course shells
  • Custom Branding: Customize colors, logos, and interface elements
  • Role-Based Access Control: Flexible permission system for administrators, instructors, and students

Prerequisites

Before deploying Canvas LMS on Klutch.sh, ensure you have:

  • A Klutch.sh account with access to the dashboard
  • A GitHub repository for your Canvas LMS deployment (public or private)
  • PostgreSQL database for user and course data storage
  • Redis instance for caching and background jobs
  • SMTP email service for notifications and communications
  • Understanding of learning management systems and educational workflows
  • Domain name for accessing your Canvas instance

Important Considerations

Deployment Steps

  1. Create a Dockerfile

    Create a Dockerfile in the root of your repository to containerize Canvas LMS:

    FROM ruby:3.2-alpine
    # Install system dependencies
    RUN apk add --no-cache \
    build-base \
    curl \
    git \
    libxml2-dev \
    libxslt-dev \
    postgresql-client \
    postgresql-dev \
    nodejs \
    yarn \
    python3 \
    python3-dev
    # Set working directory
    WORKDIR /app
    # Clone Canvas LMS repository
    RUN git clone https://github.com/instructure/canvas-lms.git . && \
    git checkout stable
    # Install Ruby dependencies
    RUN bundle install --without development test
    # Build JavaScript assets
    RUN yarn install --pure-lockfile
    RUN yarn run build
    # Compile assets
    RUN bundle exec rake canvas:compile_assets
    # Create necessary directories
    RUN mkdir -p /data /logs /tmp/canvas
    # Expose port
    EXPOSE 3000
    # Copy entrypoint script
    COPY entrypoint.sh /app/entrypoint.sh
    RUN chmod +x /app/entrypoint.sh
    # Start Canvas
    CMD ["/app/entrypoint.sh"]
  2. Create Canvas Configuration Files

    Create a config/database.yml file for database configuration:

    production:
    adapter: postgresql
    database: <%= ENV['DATABASE_NAME'] || 'canvas' %>
    host: <%= ENV['DATABASE_HOST'] || 'localhost' %>
    port: <%= ENV['DATABASE_PORT'] || 5432 %>
    username: <%= ENV['DATABASE_USER'] || 'postgres' %>
    password: <%= ENV['DATABASE_PASSWORD'] %>
    timeout: 15000
    pool: <%= ENV['DB_POOL_SIZE'] || '10' %>
    min_messages: warning

    Create a config/redis.yml file for caching:

    production:
    url: <%= ENV['REDIS_URL'] || 'redis://localhost:6379' %>
    timeout: 30
    expires_in: 3600
    race_condition_ttl: 10

    Create a config/mailbox.yml file for email configuration:

    production:
    address: <%= ENV['SMTP_HOST'] %>
    port: <%= ENV['SMTP_PORT'] || 587 %>
    user_name: <%= ENV['SMTP_USERNAME'] %>
    password: <%= ENV['SMTP_PASSWORD'] %>
    authentication: plain
    enable_starttls_auto: true
    domain: <%= ENV['CANVAS_DOMAIN'] %>
    outgoing_address: <%= ENV['CANVAS_OUTGOING_ADDRESS'] %>
  3. Create Environment Configuration

    Create a .env.example file to document required environment variables:

    # Canvas LMS Environment Configuration
    # Application Settings
    CANVAS_DOMAIN=example-app.klutch.sh
    CANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.sh
    SECRET_KEY_BASE=your-secret-key-base-here
    DEFAULT_TIMEZONE=America/Los_Angeles
    # Database Configuration
    DATABASE_HOST=localhost
    DATABASE_PORT=5432
    DATABASE_NAME=canvas
    DATABASE_USER=canvas
    DATABASE_PASSWORD=secure-password-here
    DB_POOL_SIZE=10
    # Redis Configuration
    REDIS_HOST=localhost
    REDIS_PORT=6379
    REDIS_URL=redis://localhost:6379
    # SMTP Email Configuration
    SMTP_HOST=smtp.gmail.com
    SMTP_PORT=587
    SMTP_USERNAME=your-email@gmail.com
    SMTP_PASSWORD=your-app-password
    SMTP_ENABLE_STARTTLS=true
    # Canvas Configuration
    CANVAS_API_DOMAIN=example-app.klutch.sh
    CANVAS_HTTP_CONTEXT_HOST=example-app.klutch.sh
    RAILS_ENV=production
    RAILS_LOG_TO_STDOUT=true
    RAILS_LOG_LEVEL=notice
    # Security
    ALLOW_INSECURE_COOKIES=false
    ENFORCE_SSL=true
    # Performance
    WEB_CONCURRENCY=2
    MAX_THREADS=5
  4. Create Entrypoint Script

    Create an entrypoint.sh file to initialize Canvas on container startup:

    #!/bin/bash
    set -e
    echo "Starting Canvas LMS initialization..."
    # Wait for database to be ready
    echo "Waiting for database at $DATABASE_HOST:$DATABASE_PORT..."
    until pg_isready -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER"; do
    sleep 2
    done
    # Generate SECRET_KEY_BASE if not provided
    if [ -z "$SECRET_KEY_BASE" ]; then
    echo "Generating SECRET_KEY_BASE..."
    export SECRET_KEY_BASE=$(bundle exec rake secret)
    fi
    # Run database migrations
    echo "Running database migrations..."
    bundle exec rake db:migrate || true
    # Compile assets if needed
    echo "Checking assets..."
    bundle exec rake canvas:compile_assets || true
    # Clear cache
    echo "Clearing cache..."
    bundle exec rake cache:clear || true
    # Start Canvas with Puma
    echo "Starting Canvas LMS..."
    exec bundle exec rails server -b 0.0.0.0 -p 3000 -e production

    Make it executable:

    Terminal window
    chmod +x entrypoint.sh
  5. Create .gitignore File

    Create a .gitignore file to exclude sensitive data from version control:

    # Environment and secrets
    .env
    .env.local
    .env.*.local
    SECRET_KEY_BASE
    # Ruby/Rails
    _build/
    .bundle/
    vendor/bundle/
    log/
    tmp/
    *.log
    # Node
    node_modules/
    yarn-error.log
    dist/
    build/
    # Database
    *.db
    *.sqlite3
    # IDE
    .vscode/
    .idea/
    *.swp
    *.swo
    *~
    .DS_Store
    # Canvas specific
    public/assets/
    public/stylesheets/
    public/javascripts/
    canvas_uploads/
    pem/
    .canvas_encryption_key
    # Generated files
    coverage/
    doc/
    .elixir_ls/
    # OS
    Thumbs.db
  6. Create docker-compose.yml for Local Testing

    Create a docker-compose.yml file for local development and testing (not for Klutch.sh deployment):

    version: '3.8'
    services:
    canvas:
    build: .
    container_name: canvas-lms-dev
    ports:
    - "3000:3000"
    environment:
    - DATABASE_HOST=canvas-db
    - DATABASE_NAME=canvas
    - DATABASE_USER=canvas
    - DATABASE_PASSWORD=canvaspassword
    - REDIS_URL=redis://canvas-redis:6379
    - CANVAS_DOMAIN=localhost:3000
    - CANVAS_OUTGOING_ADDRESS=noreply@localhost
    - SMTP_HOST=mailhog
    - SMTP_PORT=1025
    - RAILS_ENV=production
    depends_on:
    - canvas-db
    - canvas-redis
    - mailhog
    networks:
    - canvas-network
    canvas-db:
    image: postgres:15-alpine
    container_name: canvas-db
    environment:
    - POSTGRES_USER=canvas
    - POSTGRES_PASSWORD=canvaspassword
    - POSTGRES_DB=canvas
    volumes:
    - canvas_db_data:/var/lib/postgresql/data
    networks:
    - canvas-network
    canvas-redis:
    image: redis:7-alpine
    container_name: canvas-redis
    networks:
    - canvas-network
    mailhog:
    image: mailhog/mailhog:latest
    container_name: mailhog
    ports:
    - "1025:1025"
    - "8025:8025"
    networks:
    - canvas-network
    volumes:
    canvas_db_data:
    networks:
    canvas-network:
    driver: bridge
  7. Push to GitHub

    Push your repository to GitHub with all configuration files:

    Terminal window
    git add Dockerfile entrypoint.sh .env.example \
    config/database.yml config/redis.yml config/mailbox.yml \
    docker-compose.yml .gitignore
    git commit -m "Initial Canvas LMS deployment configuration"
    git push origin main
  8. Deploy on Klutch.sh

    1. Navigate to klutch.sh/app and log in to your dashboard
    2. Click Create New App
    3. Select Docker as the deployment method (detected automatically from your Dockerfile)
    4. Connect your GitHub repository containing the Canvas LMS deployment files
    5. Confirm the Dockerfile is detected from your root directory
    6. Click Deploy to start the deployment process
    7. Wait for the deployment to complete and your app to become active
  9. Configure Traffic Rules and Persistent Storage

    1. In your app dashboard, navigate to Traffic settings
    2. Select HTTP as the traffic type
    3. Set the internal port to 3000 (Canvas Rails server default)
    4. Save your traffic configuration
    5. Navigate to Volumes settings
    6. Click Add Volume
    7. Enter mount path: /app/public/assets
    8. Set volume size to 100GB (for storing course materials and user uploads)
    9. Click Attach to create and mount the persistent volume
    10. Your Canvas LMS application will be accessible at example-app.klutch.sh

Initial Setup and Configuration

After deploying Canvas LMS on Klutch.sh, configure your instance for educational use.

Access Your Canvas Instance

  1. Navigate to http://example-app.klutch.sh in your browser
  2. You’ll see the Canvas login page
  3. Click Create New Account to create your administrator account
  4. Enter your details and create your account
  5. Log in with your new credentials
  6. Complete the initial setup wizard

Configure Institution Settings

  1. Log in as administrator
  2. Navigate to AdminSettings
  3. Configure institutional information:
    • Institution Name: Your organization or school name
    • Support Contact: Help desk email or contact info
    • Default Time Zone: Your institution’s primary time zone
    • Default Locale: Language and regional settings
  4. Review and configure authentication settings
  5. Set up branding with your institution’s colors and logo

Configure Email (SMTP)

Canvas requires SMTP configuration for sending notifications:

  1. Navigate to AdminEmail Settings
  2. Enter your SMTP configuration:
    • SMTP Host: Your email provider’s SMTP server
    • SMTP Port: Typically 587 (TLS) or 465 (SSL)
    • Username: Your email service account username
    • Password: Your email service app-specific password
    • From Address: Email address notifications will appear from
  3. Test the configuration by sending a test email
  4. Save your SMTP settings

Create Your First Course

  1. Navigate to Dashboard
  2. Click Create a New Course
  3. Enter course details:
    • Course Name: Title of your course
    • Course Code: Unique identifier (e.g., CS101)
    • Term: Academic term or period
    • Course Sections: Add initial sections if needed
  4. Click Create Course
  5. Access your course and add content

Add Course Content

  1. In your course, navigate to the Modules section
  2. Click Add Module to create a course section
  3. Add items to modules:
    • Click Add Item within a module
    • Select content type (Assignment, Quiz, Discussion, File, etc.)
    • Configure the item settings
  4. Arrange items by dragging to reorder
  5. Publish your course when ready

Set Up Gradebook and Rubrics

  1. Navigate to Grades in your course
  2. Click Create a new Rubric
  3. Define rubric criteria:
    • Enter criterion name
    • Set point values for each rating
    • Add detailed descriptions for each rating level
  4. Save your rubric
  5. Use the rubric when grading assignments in SpeedGrader

Enroll Students

  1. Navigate to Admissions or People section
  2. Click Enroll Users
  3. Enter student emails one per line or upload a CSV file
  4. Select the role (Student, TA, Observer)
  5. Confirm and send enrollment invitations
  6. Students will receive emails with enrollment links

Create Discussion Forums

  1. Navigate to Discussions in your course
  2. Click Create a New Topic
  3. Enter discussion details:
    • Topic Name: Title of the discussion
    • Description: Instructions or prompt
    • Permissions: Set who can post, reply, etc.
  4. Configure notification settings
  5. Publish the discussion
  6. Students can now participate in discussions

Configure Assignments and Grading

  1. Navigate to Assignments in your course
  2. Click Create New Assignment
  3. Set assignment details:
    • Name: Assignment title
    • Description: Instructions for students
    • Submission Type: Online, file upload, discussion post, etc.
    • Points: Total points possible
    • Due Date: When assignment is due
  4. Assign a rubric if applicable
  5. Publish the assignment
  6. Students submit work, instructors grade in SpeedGrader

Back Up Your Data

  1. Use PostgreSQL tools to backup your database:
    Terminal window
    pg_dump canvas > canvas_backup.sql
  2. Store backups securely
  3. Test restore procedures regularly
  4. Consider automated daily backups

Environment Variables

Basic Configuration

Configure these essential environment variables for your Canvas LMS deployment:

  • CANVAS_DOMAIN=example-app.klutch.sh - External domain for Canvas
  • CANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.sh - Notification sender address
  • SECRET_KEY_BASE - Secret key for Rails session encryption
  • DATABASE_HOST - PostgreSQL server hostname
  • DATABASE_NAME - Canvas database name
  • DATABASE_USER - Database user account
  • DATABASE_PASSWORD - Database password
  • REDIS_URL - Redis connection URL for caching
  • SMTP_HOST - Email service SMTP server
  • RAILS_ENV=production - Rails environment

Production Environment Variables

For production deployments using Nixpacks, configure these environment variables for optimal performance:

# Application Core
RAILS_ENV=production
RAILS_LOG_TO_STDOUT=true
RAILS_LOG_LEVEL=notice
RAILS_MAX_THREADS=5
# Domain and Security
CANVAS_DOMAIN=example-app.klutch.sh
CANVAS_API_DOMAIN=example-app.klutch.sh
CANVAS_HTTP_CONTEXT_HOST=example-app.klutch.sh
CANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.sh
SECRET_KEY_BASE=your-generated-secret-key-base-here
ENFORCE_SSL=true
ALLOW_INSECURE_COOKIES=false
# Database Configuration
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=canvas
DATABASE_USER=canvas
DATABASE_PASSWORD=secure-database-password
DB_POOL_SIZE=10
DB_TIMEOUT=15000
# Redis Cache and Jobs
REDIS_URL=redis://localhost:6379
REDIS_CACHE_STORE=redis
REDIS_CACHE_TTL=3600
# Email Configuration (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-specific-password
SMTP_ENABLE_STARTTLS=true
CANVAS_EMAIL_FROM_ADDRESS=noreply@example-app.klutch.sh
CANVAS_EMAIL_FROM_NAME=Canvas LMS
# Performance and Concurrency
WEB_CONCURRENCY=2
MAX_THREADS=5
CANVAS_API_RATE_LIMIT=120
CANVAS_SESSION_TIMEOUT=14400
# Features and Settings
DEFAULT_TIMEZONE=America/Los_Angeles
LOCALE=en
ENABLE_ANALYTICS=true
ENABLE_ACCOUNT_REPORTS=true
ENABLE_DEVELOPER_KEYS=true

Code Examples

Ruby - Canvas Course and Assignment Management

# Canvas LMS Course and Assignment Management
require 'canvas_api'
class CanvasManager
def initialize(domain, access_token)
@canvas = CanvasApi::Client.new(domain: domain, token: access_token)
end
def create_course(course_name, course_code, term_id)
@canvas.post(
'/api/v1/accounts/1/courses',
course: {
name: course_name,
course_code: course_code,
term_id: term_id,
is_public: false
}
)
end
def get_course(course_id)
@canvas.get("/api/v1/courses/#{course_id}")
end
def add_students_to_course(course_id, student_emails)
results = []
student_emails.each do |email|
result = @canvas.post(
"/api/v1/courses/#{course_id}/enrollments",
enrollment: {
user_id: get_user_id_by_email(email),
type: 'StudentEnrollment',
notify: true
}
)
results << result
end
results
end
def create_assignment(course_id, title, description, points_possible)
@canvas.post(
"/api/v1/courses/#{course_id}/assignments",
assignment: {
name: title,
description: description,
points_possible: points_possible,
submission_types: ['online_text_entry', 'online_upload']
}
)
end
def get_submissions(course_id, assignment_id)
@canvas.get(
"/api/v1/courses/#{course_id}/assignments/#{assignment_id}/submissions"
)
end
def grade_submission(course_id, assignment_id, user_id, score, comment)
@canvas.put(
"/api/v1/courses/#{course_id}/assignments/#{assignment_id}/submissions/#{user_id}",
submission: {
posted_grade: score
},
comment: {
text_comment: comment
}
)
end
def create_discussion_topic(course_id, title, message)
@canvas.post(
"/api/v1/courses/#{course_id}/discussion_topics",
discussion_topic: {
title: title,
message: message,
discussion_type: 'threaded'
}
)
end
def get_course_analytics(course_id)
@canvas.get("/api/v1/courses/#{course_id}/analytics/student_summaries")
end
def export_gradebook(course_id, output_file)
gradebook = @canvas.get(
"/api/v1/courses/#{course_id}/gradebook_csv",
includes_sis_id: true
)
File.write(output_file, gradebook)
end
def get_user_id_by_email(email)
users = @canvas.get(
'/api/v1/users',
search_term: email
)
users.first['id'] if users.any?
end
def create_rubric(course_id, rubric_title, criteria_list)
@canvas.post(
"/api/v1/courses/#{course_id}/rubrics",
rubric: {
title: rubric_title,
criteria: format_criteria(criteria_list)
}
)
end
private
def format_criteria(criteria_list)
criteria_list.map do |criterion|
{
id: criterion[:id],
description: criterion[:description],
points: criterion[:points],
ratings: criterion[:ratings]
}
end
end
end
# Usage example
if __FILE__ == $0
manager = CanvasManager.new(
'example-app.klutch.sh',
'your-access-token-here'
)
# Create a course
puts "Creating course..."
course = manager.create_course('Introduction to Canvas', 'CANVAS101', 1)
course_id = course['id']
# Add students
puts "Enrolling students..."
students = ['student1@example.com', 'student2@example.com']
manager.add_students_to_course(course_id, students)
# Create an assignment
puts "Creating assignment..."
assignment = manager.create_assignment(
course_id,
'Welcome Assignment',
'Introduce yourself to the class',
100
)
# Get submissions
puts "Fetching submissions..."
submissions = manager.get_submissions(course_id, assignment['id'])
submissions.each do |sub|
puts " Student #{sub['user_id']}: #{sub['workflow_state']}"
end
# Get analytics
puts "Fetching course analytics..."
analytics = manager.get_course_analytics(course_id)
puts "Course analytics: #{analytics}"
end

Bash - Canvas Administration Script

#!/bin/bash
# Canvas LMS Administration and Management Script
# Perform common administration tasks
CANVAS_HOST="example-app.klutch.sh"
CANVAS_URL="http://${CANVAS_HOST}"
ACCESS_TOKEN="${CANVAS_ACCESS_TOKEN}"
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Check if instance is online
check_status() {
echo -e "${BLUE}Checking Canvas LMS instance status...${NC}"
if curl -s "${CANVAS_URL}" > /dev/null 2>&1; then
echo -e "${GREEN}✓ Canvas is online${NC}"
return 0
else
echo -e "${RED}✗ Canvas is offline${NC}"
return 1
fi
}
# Get course information
get_course() {
local course_id=$1
if [ -z "$course_id" ]; then
echo -e "${RED}Usage: get_course <course_id>${NC}"
return 1
fi
echo -e "${BLUE}Getting course $course_id:${NC}"
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq . 2>/dev/null || curl -s "${CANVAS_URL}/api/v1/courses/${course_id}" \
-H "Authorization: Bearer $ACCESS_TOKEN"
}
# List courses
list_courses() {
echo -e "${BLUE}Listing courses:${NC}"
curl -s "${CANVAS_URL}/api/v1/courses" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq '.[] | {id: .id, name: .name, code: .course_code}' 2>/dev/null || \
curl -s "${CANVAS_URL}/api/v1/courses" \
-H "Authorization: Bearer $ACCESS_TOKEN"
}
# Get course users
get_course_users() {
local course_id=$1
if [ -z "$course_id" ]; then
echo -e "${RED}Usage: get_course_users <course_id>${NC}"
return 1
fi
echo -e "${BLUE}Listing users in course $course_id:${NC}"
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/users" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq '.[] | {id: .id, name: .name, email: .email}' 2>/dev/null || \
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/users" \
-H "Authorization: Bearer $ACCESS_TOKEN"
}
# Get assignments
get_assignments() {
local course_id=$1
if [ -z "$course_id" ]; then
echo -e "${RED}Usage: get_assignments <course_id>${NC}"
return 1
fi
echo -e "${BLUE}Listing assignments in course $course_id:${NC}"
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/assignments" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq '.[] | {id: .id, name: .name, points: .points_possible}' 2>/dev/null || \
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/assignments" \
-H "Authorization: Bearer $ACCESS_TOKEN"
}
# Get submissions
get_submissions() {
local course_id=$1
local assignment_id=$2
if [ -z "$course_id" ] || [ -z "$assignment_id" ]; then
echo -e "${RED}Usage: get_submissions <course_id> <assignment_id>${NC}"
return 1
fi
echo -e "${BLUE}Listing submissions for assignment $assignment_id:${NC}"
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/assignments/${assignment_id}/submissions" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq '.[] | {user_id: .user_id, workflow_state: .workflow_state, score: .score}' 2>/dev/null || \
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/assignments/${assignment_id}/submissions" \
-H "Authorization: Bearer $ACCESS_TOKEN"
}
# Backup database
backup_database() {
local output_file=${1:-canvas_backup_$(date +%s).sql}
echo -e "${YELLOW}Backing up Canvas database...${NC}"
pg_dump -h localhost -U canvas canvas > "$output_file" && \
echo -e "${GREEN}✓ Database backed up to $output_file${NC}" || \
echo -e "${RED}✗ Backup failed${NC}"
}
# Restore database
restore_database() {
local backup_file=$1
if [ -z "$backup_file" ] || [ ! -f "$backup_file" ]; then
echo -e "${RED}Usage: restore_database <backup_file>${NC}"
return 1
fi
echo -e "${YELLOW}Restoring Canvas database from $backup_file...${NC}"
psql -h localhost -U canvas canvas < "$backup_file" && \
echo -e "${GREEN}✓ Database restored${NC}" || \
echo -e "${RED}✗ Restore failed${NC}"
}
# Export gradebook
export_gradebook() {
local course_id=$1
local output_file=${2:-gradebook_$(date +%s).csv}
if [ -z "$course_id" ]; then
echo -e "${RED}Usage: export_gradebook <course_id> [output_file]${NC}"
return 1
fi
echo -e "${YELLOW}Exporting gradebook for course $course_id...${NC}"
curl -s "${CANVAS_URL}/api/v1/courses/${course_id}/outcome_rollups?sort=name&include=alignments" \
-H "Authorization: Bearer $ACCESS_TOKEN" > "$output_file" && \
echo -e "${GREEN}✓ Gradebook exported to $output_file${NC}" || \
echo -e "${RED}✗ Export failed${NC}"
}
# Main menu
case "${1:-help}" in
status)
check_status
;;
course)
get_course "$2"
;;
courses)
list_courses
;;
users)
get_course_users "$2"
;;
assignments)
get_assignments "$2"
;;
submissions)
get_submissions "$2" "$3"
;;
backup)
backup_database "${2:-canvas_backup_$(date +%s).sql}"
;;
restore)
restore_database "$2"
;;
export-gradebook)
export_gradebook "$2" "${3:-gradebook_$(date +%s).csv}"
;;
*)
echo -e "${YELLOW}Canvas LMS Administration Tool${NC}"
echo "Usage: $0 {status|course|courses|users|assignments|submissions|backup|restore|export-gradebook} [args]"
echo ""
echo "Commands:"
echo " status - Check instance status"
echo " course <id> - Get course details"
echo " courses - List all courses"
echo " users <course_id> - List course users"
echo " assignments <course_id> - List assignments"
echo " submissions <course_id> <assignment_id> - List submissions"
echo " backup [file] - Backup database"
echo " restore <file> - Restore from backup"
echo " export-gradebook <course_id> [file] - Export gradebook"
;;
esac

Shell - Canvas Initialization and Monitoring

#!/bin/sh
# Canvas LMS Initialization and Monitoring Script
# Initialize a fresh Canvas instance and monitor its health
CANVAS_CONTAINER="canvas-lms"
CANVAS_DB="canvas-db"
CANVAS_REDIS="canvas-redis"
CANVAS_PORT=3000
CANVAS_URL="http://localhost:${CANVAS_PORT}"
# Initialize Canvas application
init_canvas() {
echo "Initializing Canvas LMS application..."
echo "Step 1: Waiting for dependencies..."
sleep 5
echo "Step 2: Running database migrations..."
docker exec $CANVAS_CONTAINER bundle exec rake db:migrate || \
echo "Migrations may have already run"
echo "Step 3: Compiling assets..."
docker exec $CANVAS_CONTAINER bundle exec rake canvas:compile_assets || \
echo "Assets may already be compiled"
echo "Step 4: Clearing cache..."
docker exec $CANVAS_CONTAINER bundle exec rake cache:clear || true
echo ""
echo "Initialization complete!"
echo "Access Canvas at: $CANVAS_URL"
echo "Create your admin account on first login"
}
# Monitor container health
monitor_health() {
echo "Monitoring Canvas LMS health..."
while true; do
clear
echo "=== Canvas LMS Health Monitor ==="
echo "Time: $(date)"
echo ""
# Check containers running
if docker ps | grep -q $CANVAS_CONTAINER; then
echo "✓ Canvas container running"
else
echo "✗ Canvas container stopped"
fi
if docker ps | grep -q $CANVAS_DB; then
echo "✓ Database container running"
else
echo "✗ Database container stopped"
fi
if docker ps | grep -q $CANVAS_REDIS; then
echo "✓ Redis container running"
else
echo "✗ Redis container stopped"
fi
# Check web interface
if curl -s "$CANVAS_URL" > /dev/null 2>&1; then
echo "✓ Web interface responding"
else
echo "✗ Web interface not responding"
fi
# Check database
if docker exec $CANVAS_DB pg_isready > /dev/null 2>&1; then
echo "✓ Database ready"
else
echo "✗ Database not responding"
fi
echo ""
echo "Container Stats:"
docker stats --no-stream $CANVAS_CONTAINER | tail -1
echo ""
echo "Recent logs (last 5 lines):"
docker logs --tail 5 $CANVAS_CONTAINER
sleep 10
done
}
# Perform database maintenance
maintain_database() {
echo "Running database maintenance..."
echo "Analyzing tables..."
docker exec $CANVAS_DB psql -U canvas -d canvas -c "ANALYZE;" && \
echo "✓ Analysis complete"
echo ""
echo "Vacuuming tables..."
docker exec $CANVAS_DB psql -U canvas -d canvas -c "VACUUM ANALYZE;" && \
echo "✓ Vacuum complete"
echo ""
echo "Checking table sizes..."
docker exec $CANVAS_DB psql -U canvas -d canvas -c \
"SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC LIMIT 20;" && \
echo "✓ Size report complete"
}
# Generate database backup
backup_canvas() {
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="canvas_backup_${timestamp}.sql"
echo "Creating Canvas database backup..."
docker exec $CANVAS_DB pg_dump -U canvas canvas > "$backup_file" && \
echo "✓ Backup complete: $backup_file" || \
echo "✗ Backup failed"
}
# View application logs
view_logs() {
local lines=${1:-50}
echo "Displaying last $lines lines of Canvas logs..."
docker logs --tail $lines $CANVAS_CONTAINER
}
# Clear cache and rebuild assets
rebuild_assets() {
echo "Rebuilding Canvas assets..."
echo "Clearing cache..."
docker exec $CANVAS_CONTAINER bundle exec rake cache:clear
echo "Compiling assets..."
docker exec $CANVAS_CONTAINER bundle exec rake canvas:compile_assets
echo "✓ Assets rebuilt"
}
# Main function
case "${1:-help}" in
init)
init_canvas
;;
monitor)
monitor_health
;;
maintain)
maintain_database
;;
backup)
backup_canvas
;;
logs)
view_logs "${2:-50}"
;;
rebuild)
rebuild_assets
;;
*)
echo "Canvas LMS Initialization and Monitoring"
echo "Usage: $0 {init|monitor|maintain|backup|logs|rebuild} [args]"
echo ""
echo "Commands:"
echo " init - Initialize fresh Canvas instance"
echo " monitor - Monitor instance health and status"
echo " maintain - Run database maintenance tasks"
echo " backup - Create database backup"
echo " logs [lines] - View application logs (default: 50 lines)"
echo " rebuild - Clear cache and rebuild assets"
;;
esac

Best Practices

  • Regular Backups: Implement daily automated backups of both the database and file storage
  • Security: Use HTTPS/SSL with proper certificates, enforce strong passwords, and enable authentication
  • Update Schedule: Keep Canvas and dependencies updated to receive security patches
  • Monitoring: Set up alerts for database, application, and server health
  • Performance: Monitor resource usage and scale components as needed (web servers, database connections)
  • Data Privacy: Configure FERPA compliance settings and privacy policies
  • Access Control: Implement proper role-based access control and permissions
  • Email Testing: Test email delivery thoroughly before relying on notifications
  • User Training: Provide documentation and training for instructors and students
  • API Security: Secure API endpoints and access tokens
  • Analytics: Review course analytics and student engagement data regularly
  • Database Optimization: Vacuum and analyze database regularly to maintain performance

Troubleshooting

Issue: “Can’t connect to database” errors

  • Verify PostgreSQL is running and accessible
  • Check DATABASE_URL and credentials are correct
  • Ensure database user has proper permissions
  • Check network connectivity to database server

Issue: Emails not sending

  • Verify SMTP credentials and settings
  • Test SMTP connection with telnet or similar
  • Check email provider’s authentication requirements
  • Review logs for SMTP error messages

Issue: Slow course loading or page timeouts

  • Check database performance and connection pool size
  • Monitor web server resource usage
  • Consider increasing WEB_CONCURRENCY or MAX_THREADS
  • Run database maintenance (VACUUM ANALYZE)

Issue: Assets not loading (CSS, JavaScript missing)

  • Run bundle exec rake canvas:compile_assets
  • Check file permissions on public directory
  • Verify persistent volume is properly mounted
  • Clear browser cache and hard refresh

Issue: Background jobs not processing

  • Verify Redis is running and accessible
  • Check for job queue backlog
  • Monitor background worker processes
  • Review job queue logs for errors

Issue: File uploads failing

  • Check disk space on persistent volume
  • Verify file permissions on upload directory
  • Confirm volume is properly mounted
  • Review file size limits in Canvas configuration

Update Instructions

To update Canvas LMS to the latest version:

  1. Pull Latest Changes: Update your repository to the latest stable branch

    Terminal window
    git pull origin stable
  2. Test Locally: Build and test locally with docker-compose first

    Terminal window
    docker-compose build
    docker-compose up
  3. Backup Database: Always backup before updating

    Terminal window
    pg_dump canvas > canvas_backup_pre_update.sql
  4. Commit Changes: Push updated Dockerfile to GitHub

    Terminal window
    git add Dockerfile
    git commit -m "Update Canvas LMS to latest stable"
    git push origin main
  5. Redeploy: In Klutch.sh dashboard, trigger a manual redeploy

    • The new Docker image will be built and deployed
    • Database migrations will run automatically
  6. Verify: Test core functionality after update completes

Use Cases

  • K-12 Education: Classroom management and student assessment
  • Higher Education: University course delivery and grading
  • Corporate Training: Employee onboarding and professional development
  • Distance Learning: Fully remote course delivery and synchronous/asynchronous learning
  • Hybrid Learning: Blended in-person and online instruction
  • Professional Certification: Continuing education and certification programs
  • Student Collaboration: Group projects and peer learning
  • Assessment and Analytics: Track student progress and learning outcomes
  • Multi-institution: Manage courses across multiple schools or departments
  • Open Educational Resources: Share and distribute OER content
  • Accessibility-First Education: Inclusive learning environments for all learners

Additional Resources

Conclusion

Deploying Canvas LMS on Klutch.sh provides a powerful, open-source learning management system that gives you complete control over your educational technology infrastructure. By following this guide, you’ve set up a production-ready Canvas instance with PostgreSQL database storage for reliable course and user data management.

Your Canvas LMS deployment is now ready to serve educators and learners with an accessible, feature-rich learning platform. Whether you’re running a single classroom, managing multiple courses, or building a comprehensive institutional learning environment, Canvas provides the flexibility, scalability, and community support needed for modern education.

For advanced configurations, customizations, or additional support, refer to the official Canvas documentation, community forums, and GitHub repository. Regular maintenance, backups, and updates will keep your Canvas instance secure, performant, and aligned with your educational goals.