Self-Hosting Moodle with Docker Compose
What Is Moodle?
Moodle is an open-source learning management system used by over 300 million people worldwide. It handles courses, quizzes, assignments, grading, forums, and SCORM-compliant content — everything you need to run online education or corporate training. Self-hosting Moodle gives you full control over student data, unlimited users with zero per-seat fees, and access to 2,000+ plugins. It replaces cloud LMS platforms like Google Classroom, Canvas, Blackboard, and Thinkific.
Official site · GitHub · Plugin directory
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 4 GB of RAM minimum (2 GB absolute minimum for small deployments)
- 10 GB of free disk space (grows with uploaded content)
- A domain name (recommended for student access)
Docker Compose Configuration
Moodle runs well with the Bitnami image, which bundles PHP, Apache, and automatic cron jobs into a single container. The setup needs MariaDB as the database backend.
Create a docker-compose.yml file:
services:
mariadb:
image: bitnami/mariadb:11.4
container_name: moodle-db
restart: unless-stopped
environment:
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MARIADB_USER=bn_moodle
- MARIADB_DATABASE=bitnami_moodle
- MARIADB_PASSWORD=${DB_PASSWORD}
- MARIADB_CHARACTER_SET=utf8mb4 # Required for emoji and multilingual content
- MARIADB_COLLATE=utf8mb4_unicode_ci
volumes:
- mariadb_data:/bitnami/mariadb
networks:
- moodle
moodle:
image: bitnami/moodle:5.1.3
container_name: moodle
restart: unless-stopped
ports:
- "8080:8080"
- "8443:8443"
environment:
- MOODLE_DATABASE_HOST=mariadb
- MOODLE_DATABASE_PORT_NUMBER=3306
- MOODLE_DATABASE_USER=bn_moodle
- MOODLE_DATABASE_NAME=bitnami_moodle
- MOODLE_DATABASE_PASSWORD=${DB_PASSWORD}
- MOODLE_USERNAME=admin # Change this — your admin login
- MOODLE_PASSWORD=${MOODLE_ADMIN_PASS} # Change this — strong password required
- [email protected] # Change to your email
- MOODLE_SITE_NAME=My Learning Platform
- MOODLE_LANG=en
- MOODLE_REVERSEPROXY=no # Set to "yes" behind a reverse proxy
- MOODLE_SSLPROXY=no # Set to "yes" if proxy terminates SSL
- MOODLE_CRON_MINUTES=1 # Cron runs every minute (Moodle needs this)
volumes:
- moodle_data:/bitnami/moodle
- moodledata:/bitnami/moodledata
depends_on:
- mariadb
networks:
- moodle
networks:
moodle:
volumes:
mariadb_data:
moodle_data:
moodledata:
Create a .env file alongside your compose file:
# Database passwords — change these to strong random values
DB_ROOT_PASSWORD=change_me_root_password_here
DB_PASSWORD=change_me_db_password_here
# Moodle admin password — minimum 8 chars, must include uppercase, lowercase, digit, and special char
MOODLE_ADMIN_PASS=Change_Me_2026!
Start the stack:
docker compose up -d
First startup takes 3-5 minutes while Moodle runs its database installation scripts. Watch the logs:
docker compose logs -f moodle
Wait until you see moodle 08:XX:XX.XX INFO ==> ** Moodle setup finished! ** before accessing the web UI.
Initial Setup
- Open
http://your-server-ip:8080in your browser - Log in with the admin credentials you set in the environment variables (default username:
admin) - Complete the site registration form (or skip it)
- Navigate to Site administration → Notifications to check for any pending updates
- Under Site administration → Plugins → Install plugins, browse and install any plugins you need
First Course Setup
- Go to Site administration → Courses → Add a new course
- Set the course name, short name, and category
- Under the course, add activities: Turn editing on → Add an activity or resource
- Available activity types include assignments, quizzes, forums, wikis, SCORM packages, and lessons
Configuration
SMTP for Email Notifications
Moodle sends enrollment notifications, assignment reminders, forum digests, and password resets via email. Add SMTP variables to the moodle service:
environment:
# ... existing variables ...
- MOODLE_SMTP_HOST=smtp.example.com
- MOODLE_SMTP_PORT_NUMBER=587
- MOODLE_SMTP_USER=your-smtp-user
- MOODLE_SMTP_PASSWORD=your-smtp-password
- MOODLE_SMTP_PROTOCOL=tls
PHP Tuning
For larger deployments (50+ concurrent users), increase PHP memory limits by adding these to the moodle service environment:
- PHP_MEMORY_LIMIT=512M
- PHP_MAX_INPUT_VARS=5000
Reverse Proxy Configuration
Behind Nginx Proxy Manager or Caddy, set these variables:
- MOODLE_REVERSEPROXY=yes
- MOODLE_SSLPROXY=yes
- MOODLE_HOST=https://learn.example.com
The MOODLE_HOST variable sets the $CFG->wwwroot — Moodle uses this for all generated URLs. Get it wrong and every link in the LMS breaks.
Cost Comparison
| Google Classroom | Canvas Cloud | Moodle (Self-Hosted) | |
|---|---|---|---|
| Monthly cost | Free (with Workspace) | $5,000-50,000+/year | $5-20/month (VPS) |
| Per-user fees | Included in Workspace | Per-seat pricing | None |
| Quiz engine | Basic | Good | Excellent (40+ question types) |
| Plugin ecosystem | Limited | Moderate | 2,000+ plugins |
| SCORM support | No | Yes | Yes |
| Data ownership | Google controls | Instructure controls | You control everything |
| Customization | Minimal | Limited | Unlimited |
Backup
Back up these three volumes:
| Volume | Contains | Priority |
|---|---|---|
mariadb_data | Database (courses, users, grades, quiz attempts) | Critical |
moodledata | Uploaded files, cache, temp, backups | Critical |
moodle_data | Application code, config.php, installed plugins | Important |
Database dump:
docker exec moodle-db mariadb-dump -u root -p bitnami_moodle > moodle_backup_$(date +%Y%m%d).sql
Moodle also has built-in course backup: Course → Backup exports a .mbz file containing all course content. Use this for course-level portability between Moodle instances.
For automated backups, see Backup Strategy.
Troubleshooting
Moodle stuck on “Installing database”
Symptom: Container logs show the installation script running for more than 10 minutes.
Fix: This is normal for first startup on slower hardware. The initial database schema creation runs hundreds of SQL statements. Wait up to 15 minutes. If it fails, remove volumes and start fresh:
docker compose down -v
docker compose up -d
“Database connection failed” after restart
Symptom: Moodle can’t connect to MariaDB after a container restart.
Fix: The MariaDB container might not be ready yet. Check that depends_on is set and the database container is healthy:
docker compose ps
docker compose logs mariadb
Cron not running (scheduled tasks failing)
Symptom: Forum digests aren’t sent, calendar events don’t fire, or grades aren’t calculated.
Fix: Verify MOODLE_CRON_MINUTES=1 is set. The Bitnami image runs cron automatically — check with:
docker exec moodle crontab -l
“Maximum upload file size” too small
Symptom: Students can’t upload large assignments.
Fix: Add PHP_UPLOAD_MAX_FILESIZE and PHP_POST_MAX_SIZE environment variables:
- PHP_UPLOAD_MAX_FILESIZE=256M
- PHP_POST_MAX_SIZE=256M
Then change the upload limit in Site administration → Security → Site security settings.
Resource Requirements
- RAM: 1-2 GB idle, 4 GB recommended for 50+ concurrent users
- CPU: 2 cores minimum, 4 cores for quiz-heavy workloads
- Disk: 2 GB for the application, 10-50 GB+ for uploaded content and database
Moodle’s biggest resource consumer is quizzes — each quiz attempt with complex question types (calculated, drag-and-drop) can spike CPU and memory. Budget accordingly if running exams for large classes.
Verdict
Moodle is the most capable self-hosted LMS by a wide margin. The plugin ecosystem, SCORM compliance, and granular permission system make it suitable for everything from a family homeschool setup to corporate training for thousands. The trade-off is complexity — Moodle’s admin interface has hundreds of settings, and initial configuration takes time.
For small teams or simple course delivery, Canvas LMS (self-hosted open-source edition) has a cleaner UI. For selling courses commercially, you’ll want a platform with built-in payments. But for educational institutions, corporate training, or anyone who needs a full-featured LMS with zero per-user costs, Moodle is the clear choice.
FAQ
How does Moodle compare to Google Classroom?
Google Classroom is simpler but limited — basic assignments, no quiz engine, no SCORM, and Google controls your data. Moodle has 40+ question types, 2,000+ plugins, granular permissions, SCORM compliance, and runs on your server with zero per-user fees. Choose Google Classroom for quick informal assignments. Choose Moodle for proper education or training programs. See Replace Google Classroom.
Can Moodle handle hundreds of concurrent users?
Yes, with proper resources. The Bitnami image handles 50-100 concurrent users on a 4 GB RAM / 2 core VPS. For 500+ users, you’ll need 8+ GB RAM, 4+ cores, and should consider a separate database server. Quiz-heavy workloads spike resources — budget for peak exam loads, not average use.
Does Moodle support SCORM courses?
Yes. Moodle natively supports SCORM 1.2 and SCORM 2004 packages. Upload .zip SCORM packages as course activities and Moodle handles the player, tracking, and grade reporting. This is a key advantage over simpler LMS platforms.
How do I install Moodle plugins?
Download .zip plugin files from moodle.org/plugins. In the admin panel: Site administration → Plugins → Install plugins → Upload ZIP file. Or copy the extracted plugin to the correct directory in the moodle_data volume (usually /mod/, /blocks/, or /local/). Run Site administration → Notifications to trigger the install.
Can students access Moodle from mobile devices?
Yes. The Moodle web interface is responsive and works in mobile browsers. There’s also an official Moodle app (iOS and Android) that provides offline access, push notifications, and file uploads. Configure the mobile app in Site administration → Mobile app.
How do I upgrade Moodle?
Update the image tag in docker-compose.yml (e.g., bitnami/moodle:5.1.4) and recreate the container: docker compose up -d. The Bitnami image runs database migrations automatically on startup. Always back up the database and volumes before upgrading — Moodle doesn’t support downgrades.
Related
- Moodle: Slow Performance — Fix
- Chamilo vs Moodle: Which LMS Should You Self-Host?
- Moodle vs Canvas LMS: Which Should You Self-Host?
- Moodle vs Open edX: Which Should You Self-Host?
- Best Self-Hosted Education & LMS Platforms
- Replace Google Classroom
- Docker Compose Basics
- Reverse Proxy Setup
- Backup Strategy
- Linux Basics for Self-Hosting
- Remote Access to Your Home Server
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments