Deploy Moodle 5.2 LMS — Open Source Learning Platform
Self-hosted Moodle LMS with Postgres — courses, quizzes, grading
Just deployed
/var/moodledata
Just deployed
/var/lib/postgresql/data
Deploy and Host Moodle on Railway
Moodle is the world's most widely used open-source learning management system — the platform behind universities, schools, and corporate training programs worldwide. Create courses, build quizzes and assignments, track grades, run forums, and manage learners at any scale, with unlimited users and no per-seat licensing. This template deploys the current Moodle 5.2 release with a managed PostgreSQL database, pre-wired and persistent.
What This Template Deploys
| Service | Purpose |
|---|---|
| Moodle | The LMS application, course UI, and admin on port 8080 |
| PostgreSQL | Courses, users, grades, quiz data, and all application state |
Both services run on Railway's private network. Two persistent volumes hold Moodle's application files and its working data directory, and a third holds the database — the storage layout Moodle actually requires.
About Hosting Moodle
Moodle has a storage model that trips most container deployments. It needs two separate persistent locations: the application directory at /bitnami/moodle, and a working data directory (moodledata) at /bitnami/moodledata where uploaded files, course content, session data, and caches live. Miss the second one and uploads, course files, and user submissions vanish on redeploy while the site itself appears intact — a subtle, damaging failure. This template mounts both.
The database is the third piece. This template uses a managed PostgreSQL service — Moodle supports Postgres natively as a first-class database backend — rather than the SQLite that would never survive real use. All course and user data lives there.
Moodle is a substantial PHP application. Budget 2 GB of RAM minimum for a small deployment, more as concurrent users climb — an active class hitting a quiz at the same time is a real load spike. First boot takes a few minutes while Bitnami initialises the database and runs the Moodle installer.
Typical cost: ~$15–30/month on Railway depending on RAM and storage. Commercial LMS platforms like Canvas, Blackboard, and TalentLMS charge per active user or per seat, so a cohort of any size makes self-hosting dramatically cheaper — and your learner data stays yours.
How It Compares
| Moodle (self-hosted) | Canvas Cloud | TalentLMS | Google Classroom | |
|---|---|---|---|---|
| Cost model | Flat ~$15–30/mo infra | Per user/institution | Per user tier | Free (Workspace) |
| User limit | Unlimited | Licensed | Per plan | Workspace-bound |
| Data ownership | Full | Vendor | Vendor | |
| Plugins | 2,000+ open | Limited | Limited | Minimal |
| Quiz & grading engine | Full | Full | Full | Basic |
| Self-hostable | Yes | No | No | No |
Google Classroom is free but shallow and tied to Workspace; Canvas and TalentLMS are polished but priced per user. Moodle wins on depth, its enormous plugin ecosystem, and owning your data — the trade is that you run it.
Deploy in Under 5 Minutes
- Click Deploy on Railway — Moodle and PostgreSQL build automatically (first boot takes a few minutes)
- Set
MOODLE_USERNAME,MOODLE_PASSWORD, andMOODLE_EMAILfor the admin account - Confirm both Moodle volumes are mounted —
/bitnami/moodleand/bitnami/moodledata - Open your Railway domain and sign in with the admin credentials you set
- Create your first course, add activities, and enrol users
Configure SMTP under Site administration → Server → Email so account and notification emails send.
Common Use Cases
- School or university LMS — full course management, gradebook, and assessment for institutions of any size
- Corporate training platform — onboarding, compliance courses, and certification tracking with completion reporting
- Online course delivery — sell or share structured courses with quizzes, assignments, and progress tracking
- Tutoring and coaching — a branded learning space for a private practice or education business
- Certification programs — timed quizzes, question banks, and automated certificate issuance on completion
- Blended learning — supplement in-person teaching with forums, resources, and online assessment
Configuration
| Variable | Required | Description |
|---|---|---|
MOODLE_USERNAME | Required | Admin account username, set on first install |
MOODLE_PASSWORD | Required | Admin password — use a strong value |
MOODLE_EMAIL | Required | Admin email address |
MOODLE_DATABASE_TYPE | Pre-set | pgsql |
MOODLE_DATABASE_HOST | Auto-injected | PostgreSQL host via Railway reference variable |
MOODLE_DATABASE_PORT_NUMBER | Auto-injected | PostgreSQL port (5432) |
MOODLE_DATABASE_NAME | Auto-injected | Database name |
MOODLE_DATABASE_USER | Auto-injected | Database user |
MOODLE_DATABASE_PASSWORD | Auto-injected | Database password |
MOODLE_HOST | Required | Your Railway public domain — Moodle builds all links from it |
MOODLE_REVERSEPROXY | Pre-set | true — required so Moodle trusts Railway's proxy for HTTPS |
MOODLE_SSLPROXY | Pre-set | true — tells Moodle it's served over HTTPS |
ALLOW_EMPTY_PASSWORD | Pre-set | no — never allow blank database passwords in production |
Both Moodle volumes are required.
/bitnami/moodleholds the application and/bitnami/moodledataholds uploads, course files, and sessions. Without the second, user-submitted content is lost on redeploy even though the site loads.
Set
MOODLE_REVERSEPROXYandMOODLE_SSLPROXYtotrue. Behind Railway's proxy, Moodle otherwise generates broken links and can loop on login. These flags tell it it's served over HTTPS through a proxy.
Dependencies for Moodle Hosting
- Railway account — expect ~$15–30/month depending on RAM and storage
- Persistent Railway volumes for the app, working data, and database (included)
- SMTP credentials for account, enrolment, and notification emails
- Optional: S3-compatible storage for course files on very large installs
Deployment Dependencies
- Moodle GitHub Repository
- Moodle Documentation
- Bitnami Moodle Image Reference
- Railway Volumes Documentation
Implementation Details
The template runs the Bitnami Moodle 5.2 image on port 8080 against a managed PostgreSQL service, with MOODLE_DATABASE_TYPE set to pgsql and connection values supplied through Railway reference variables. Two volumes back the Moodle service — the application at /bitnami/moodle and the working data directory at /bitnami/moodledata — which is the storage split Bitnami's image expects and the part most deployments miss.
MOODLE_REVERSEPROXY and MOODLE_SSLPROXY are enabled because Moodle sits behind Railway's TLS-terminating proxy. Without them, Moodle sees plain HTTP internally, generates http:// links, and can enter a redirect loop at login. On first boot the Bitnami entrypoint initialises the database and runs the Moodle installer, which is why the initial deploy takes several minutes.
Course and user data lives in PostgreSQL; uploaded files and course content live in the moodledata volume. Both need backing up — a full restore requires the database dump and the moodledata contents together, since one without the other leaves Moodle referencing files it can't find.
Frequently Asked Questions
Why does Moodle need two volumes? Moodle separates its application code from its working data. Uploads, course files, session data, and caches live in a moodledata directory kept outside the app directory for security. Both must persist, so both are mounted.
Which database does this use? PostgreSQL. Moodle supports Postgres, MariaDB, and MySQL as first-class backends; this template uses a managed PostgreSQL service, wired in through Railway reference variables.
My links are broken or login loops — why? Almost always because MOODLE_REVERSEPROXY and MOODLE_SSLPROXY aren't set to true. Behind Railway's HTTPS proxy, Moodle needs them to generate correct secure links.
Is it really unlimited users? Yes. Moodle is open source with no licensing fees or user caps. Your only limits are the compute and storage you provision.
Do uploaded course files survive a redeploy? Yes, provided the moodledata volume is mounted. That's the whole reason the second volume matters — without it, user content is lost while the site keeps loading.
How many users can it handle? A small deployment on 2 GB RAM serves a class or small program comfortably. Concurrent activity — a whole cohort taking a quiz at once — is the real load driver, so scale RAM and CPU with peak concurrency, not total enrolment.
Can I install plugins and themes? Yes. Moodle has 2,000+ plugins and many themes installable from the admin interface, though plugins requiring code changes are more involved on a container platform than on a traditional server.
How do I send email? Configure SMTP under Site administration → Server → Email. Without it, enrolment confirmations, password resets, and notifications won't send.
Why Deploy Moodle on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Moodle on Railway you get a complete learning platform with the storage layout done right — Moodle and PostgreSQL pre-wired over a private network, both required volumes mounted, reverse-proxy flags set for clean HTTPS, and automatic SSL. Unlimited learners, no per-seat licensing, and your courses and student data on infrastructure you own.
Template Content
MOODLE_EMAIL_HOST
Email Host
