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
Create a Dockerfile
Create a
Dockerfilein the root of your repository to containerize Canvas LMS:FROM ruby:3.2-alpine# Install system dependenciesRUN apk add --no-cache \build-base \curl \git \libxml2-dev \libxslt-dev \postgresql-client \postgresql-dev \nodejs \yarn \python3 \python3-dev# Set working directoryWORKDIR /app# Clone Canvas LMS repositoryRUN git clone https://github.com/instructure/canvas-lms.git . && \git checkout stable# Install Ruby dependenciesRUN bundle install --without development test# Build JavaScript assetsRUN yarn install --pure-lockfileRUN yarn run build# Compile assetsRUN bundle exec rake canvas:compile_assets# Create necessary directoriesRUN mkdir -p /data /logs /tmp/canvas# Expose portEXPOSE 3000# Copy entrypoint scriptCOPY entrypoint.sh /app/entrypoint.shRUN chmod +x /app/entrypoint.sh# Start CanvasCMD ["/app/entrypoint.sh"]Create Canvas Configuration Files
Create a
config/database.ymlfile for database configuration:production:adapter: postgresqldatabase: <%= ENV['DATABASE_NAME'] || 'canvas' %>host: <%= ENV['DATABASE_HOST'] || 'localhost' %>port: <%= ENV['DATABASE_PORT'] || 5432 %>username: <%= ENV['DATABASE_USER'] || 'postgres' %>password: <%= ENV['DATABASE_PASSWORD'] %>timeout: 15000pool: <%= ENV['DB_POOL_SIZE'] || '10' %>min_messages: warningCreate a
config/redis.ymlfile for caching:production:url: <%= ENV['REDIS_URL'] || 'redis://localhost:6379' %>timeout: 30expires_in: 3600race_condition_ttl: 10Create a
config/mailbox.ymlfile for email configuration:production:address: <%= ENV['SMTP_HOST'] %>port: <%= ENV['SMTP_PORT'] || 587 %>user_name: <%= ENV['SMTP_USERNAME'] %>password: <%= ENV['SMTP_PASSWORD'] %>authentication: plainenable_starttls_auto: truedomain: <%= ENV['CANVAS_DOMAIN'] %>outgoing_address: <%= ENV['CANVAS_OUTGOING_ADDRESS'] %>Create Environment Configuration
Create a
.env.examplefile to document required environment variables:# Canvas LMS Environment Configuration# Application SettingsCANVAS_DOMAIN=example-app.klutch.shCANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.shSECRET_KEY_BASE=your-secret-key-base-hereDEFAULT_TIMEZONE=America/Los_Angeles# Database ConfigurationDATABASE_HOST=localhostDATABASE_PORT=5432DATABASE_NAME=canvasDATABASE_USER=canvasDATABASE_PASSWORD=secure-password-hereDB_POOL_SIZE=10# Redis ConfigurationREDIS_HOST=localhostREDIS_PORT=6379REDIS_URL=redis://localhost:6379# SMTP Email ConfigurationSMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_USERNAME=your-email@gmail.comSMTP_PASSWORD=your-app-passwordSMTP_ENABLE_STARTTLS=true# Canvas ConfigurationCANVAS_API_DOMAIN=example-app.klutch.shCANVAS_HTTP_CONTEXT_HOST=example-app.klutch.shRAILS_ENV=productionRAILS_LOG_TO_STDOUT=trueRAILS_LOG_LEVEL=notice# SecurityALLOW_INSECURE_COOKIES=falseENFORCE_SSL=true# PerformanceWEB_CONCURRENCY=2MAX_THREADS=5Create Entrypoint Script
Create an
entrypoint.shfile to initialize Canvas on container startup:#!/bin/bashset -eecho "Starting Canvas LMS initialization..."# Wait for database to be readyecho "Waiting for database at $DATABASE_HOST:$DATABASE_PORT..."until pg_isready -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER"; dosleep 2done# Generate SECRET_KEY_BASE if not providedif [ -z "$SECRET_KEY_BASE" ]; thenecho "Generating SECRET_KEY_BASE..."export SECRET_KEY_BASE=$(bundle exec rake secret)fi# Run database migrationsecho "Running database migrations..."bundle exec rake db:migrate || true# Compile assets if neededecho "Checking assets..."bundle exec rake canvas:compile_assets || true# Clear cacheecho "Clearing cache..."bundle exec rake cache:clear || true# Start Canvas with Pumaecho "Starting Canvas LMS..."exec bundle exec rails server -b 0.0.0.0 -p 3000 -e productionMake it executable:
Terminal window chmod +x entrypoint.shCreate .gitignore File
Create a
.gitignorefile to exclude sensitive data from version control:# Environment and secrets.env.env.local.env.*.localSECRET_KEY_BASE# Ruby/Rails_build/.bundle/vendor/bundle/log/tmp/*.log# Nodenode_modules/yarn-error.logdist/build/# Database*.db*.sqlite3# IDE.vscode/.idea/*.swp*.swo*~.DS_Store# Canvas specificpublic/assets/public/stylesheets/public/javascripts/canvas_uploads/pem/.canvas_encryption_key# Generated filescoverage/doc/.elixir_ls/# OSThumbs.dbCreate docker-compose.yml for Local Testing
Create a
docker-compose.ymlfile for local development and testing (not for Klutch.sh deployment):version: '3.8'services:canvas:build: .container_name: canvas-lms-devports:- "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=productiondepends_on:- canvas-db- canvas-redis- mailhognetworks:- canvas-networkcanvas-db:image: postgres:15-alpinecontainer_name: canvas-dbenvironment:- POSTGRES_USER=canvas- POSTGRES_PASSWORD=canvaspassword- POSTGRES_DB=canvasvolumes:- canvas_db_data:/var/lib/postgresql/datanetworks:- canvas-networkcanvas-redis:image: redis:7-alpinecontainer_name: canvas-redisnetworks:- canvas-networkmailhog:image: mailhog/mailhog:latestcontainer_name: mailhogports:- "1025:1025"- "8025:8025"networks:- canvas-networkvolumes:canvas_db_data:networks:canvas-network:driver: bridgePush 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 .gitignoregit commit -m "Initial Canvas LMS deployment configuration"git push origin mainDeploy on Klutch.sh
- Navigate to klutch.sh/app and log in to your dashboard
- Click Create New App
- Select Docker as the deployment method (detected automatically from your Dockerfile)
- Connect your GitHub repository containing the Canvas LMS deployment files
- Confirm the Dockerfile is detected from your root directory
- Click Deploy to start the deployment process
- Wait for the deployment to complete and your app to become active
Configure Traffic Rules and Persistent Storage
- In your app dashboard, navigate to Traffic settings
- Select HTTP as the traffic type
- Set the internal port to 3000 (Canvas Rails server default)
- Save your traffic configuration
- Navigate to Volumes settings
- Click Add Volume
- Enter mount path:
/app/public/assets - Set volume size to 100GB (for storing course materials and user uploads)
- Click Attach to create and mount the persistent volume
- 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
- Navigate to
http://example-app.klutch.shin your browser - You’ll see the Canvas login page
- Click Create New Account to create your administrator account
- Enter your details and create your account
- Log in with your new credentials
- Complete the initial setup wizard
Configure Institution Settings
- Log in as administrator
- Navigate to Admin → Settings
- 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
- Review and configure authentication settings
- Set up branding with your institution’s colors and logo
Configure Email (SMTP)
Canvas requires SMTP configuration for sending notifications:
- Navigate to Admin → Email Settings
- 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
- Test the configuration by sending a test email
- Save your SMTP settings
Create Your First Course
- Navigate to Dashboard
- Click Create a New Course
- 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
- Click Create Course
- Access your course and add content
Add Course Content
- In your course, navigate to the Modules section
- Click Add Module to create a course section
- Add items to modules:
- Click Add Item within a module
- Select content type (Assignment, Quiz, Discussion, File, etc.)
- Configure the item settings
- Arrange items by dragging to reorder
- Publish your course when ready
Set Up Gradebook and Rubrics
- Navigate to Grades in your course
- Click Create a new Rubric
- Define rubric criteria:
- Enter criterion name
- Set point values for each rating
- Add detailed descriptions for each rating level
- Save your rubric
- Use the rubric when grading assignments in SpeedGrader
Enroll Students
- Navigate to Admissions or People section
- Click Enroll Users
- Enter student emails one per line or upload a CSV file
- Select the role (Student, TA, Observer)
- Confirm and send enrollment invitations
- Students will receive emails with enrollment links
Create Discussion Forums
- Navigate to Discussions in your course
- Click Create a New Topic
- Enter discussion details:
- Topic Name: Title of the discussion
- Description: Instructions or prompt
- Permissions: Set who can post, reply, etc.
- Configure notification settings
- Publish the discussion
- Students can now participate in discussions
Configure Assignments and Grading
- Navigate to Assignments in your course
- Click Create New Assignment
- 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
- Assign a rubric if applicable
- Publish the assignment
- Students submit work, instructors grade in SpeedGrader
Back Up Your Data
- Use PostgreSQL tools to backup your database:
Terminal window pg_dump canvas > canvas_backup.sql - Store backups securely
- Test restore procedures regularly
- 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 CanvasCANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.sh- Notification sender addressSECRET_KEY_BASE- Secret key for Rails session encryptionDATABASE_HOST- PostgreSQL server hostnameDATABASE_NAME- Canvas database nameDATABASE_USER- Database user accountDATABASE_PASSWORD- Database passwordREDIS_URL- Redis connection URL for cachingSMTP_HOST- Email service SMTP serverRAILS_ENV=production- Rails environment
Production Environment Variables
For production deployments using Nixpacks, configure these environment variables for optimal performance:
# Application CoreRAILS_ENV=productionRAILS_LOG_TO_STDOUT=trueRAILS_LOG_LEVEL=noticeRAILS_MAX_THREADS=5
# Domain and SecurityCANVAS_DOMAIN=example-app.klutch.shCANVAS_API_DOMAIN=example-app.klutch.shCANVAS_HTTP_CONTEXT_HOST=example-app.klutch.shCANVAS_OUTGOING_ADDRESS=noreply@example-app.klutch.shSECRET_KEY_BASE=your-generated-secret-key-base-hereENFORCE_SSL=trueALLOW_INSECURE_COOKIES=false
# Database ConfigurationDATABASE_HOST=localhostDATABASE_PORT=5432DATABASE_NAME=canvasDATABASE_USER=canvasDATABASE_PASSWORD=secure-database-passwordDB_POOL_SIZE=10DB_TIMEOUT=15000
# Redis Cache and JobsREDIS_URL=redis://localhost:6379REDIS_CACHE_STORE=redisREDIS_CACHE_TTL=3600
# Email Configuration (SMTP)SMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_USERNAME=your-email@gmail.comSMTP_PASSWORD=your-app-specific-passwordSMTP_ENABLE_STARTTLS=trueCANVAS_EMAIL_FROM_ADDRESS=noreply@example-app.klutch.shCANVAS_EMAIL_FROM_NAME=Canvas LMS
# Performance and ConcurrencyWEB_CONCURRENCY=2MAX_THREADS=5CANVAS_API_RATE_LIMIT=120CANVAS_SESSION_TIMEOUT=14400
# Features and SettingsDEFAULT_TIMEZONE=America/Los_AngelesLOCALE=enENABLE_ANALYTICS=trueENABLE_ACCOUNT_REPORTS=trueENABLE_DEVELOPER_KEYS=trueCode Examples
Ruby - Canvas Course and Assignment Management
# Canvas LMS Course and Assignment Managementrequire '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 endend
# Usage exampleif __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}"endBash - 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 outputRED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'BLUE='\033[0;34m'NC='\033[0m'
# Check if instance is onlinecheck_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 informationget_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 courseslist_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 usersget_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 assignmentsget_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 submissionsget_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 databasebackup_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 databaserestore_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 gradebookexport_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 menucase "${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" ;;esacShell - 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=3000CANVAS_URL="http://localhost:${CANVAS_PORT}"
# Initialize Canvas applicationinit_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 healthmonitor_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 maintenancemaintain_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 backupbackup_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 logsview_logs() { local lines=${1:-50}
echo "Displaying last $lines lines of Canvas logs..." docker logs --tail $lines $CANVAS_CONTAINER}
# Clear cache and rebuild assetsrebuild_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 functioncase "${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" ;;esacBest 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:
-
Pull Latest Changes: Update your repository to the latest stable branch
Terminal window git pull origin stable -
Test Locally: Build and test locally with docker-compose first
Terminal window docker-compose builddocker-compose up -
Backup Database: Always backup before updating
Terminal window pg_dump canvas > canvas_backup_pre_update.sql -
Commit Changes: Push updated Dockerfile to GitHub
Terminal window git add Dockerfilegit commit -m "Update Canvas LMS to latest stable"git push origin main -
Redeploy: In Klutch.sh dashboard, trigger a manual redeploy
- The new Docker image will be built and deployed
- Database migrations will run automatically
-
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
- Canvas LMS GitHub Repository - Source code and documentation
- Canvas Wiki - Installation and configuration guides
- Canvas API Documentation - REST API reference
- Instructure Community - User community and support forums
- Canvas by Instructure - Commercial offerings and information
- PostgreSQL Documentation - Database documentation
- Ruby on Rails Guides - Framework documentation
- Docker Documentation - Container deployment resources
- FERPA Compliance Guide - Family Educational Rights and Privacy Act
- Canvas Best Practices - Community best practices and guides
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.