---
title: "Deploy Moodle | (Just Updated) LMS Whose Cron Actually Runs, Plugins Survive"
description: "Moodle LMS whose cron runs and whose plugins survive every redeploy"
category: "CMS"
url: https://railway.com/deploy/moodle-or-just-updated-lms-whose-cron-ac
---

# Deploy Moodle | (Just Updated) LMS Whose Cron Actually Runs, Plugins Survive

Moodle LMS whose cron runs and whose plugins survive every redeploy

**[Deploy Moodle | (Just Updated) LMS Whose Cron Actually Runs, Plugins Survive on Railway](https://railway.com/template/moodle-or-just-updated-lms-whose-cron-ac)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/moodle-or-just-updated-lms-whose-cron-ac/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** CMS

## Template content

### moodle

- **Image:** ghcr.io/bon5co/moodle-railway:5.2.2
- **Public domain:** Yes

### postgres

- **Image:** postgres:17.10-alpine

## Documentation

# Deploy and Host Moodle on Railway

Moodle is the open-source learning management system used by universities, schools and
corporate training teams: courses, enrolments, quizzes, assignments, grades, forums,
certificates and a plugin directory of thousands of add-ons. This template runs Moodle 5.2.2
with PostgreSQL, and is packaged so the two things every other Moodle listing on Railway gets
wrong actually work — the scheduled task runner, and persistence of anything you install or
upload after the first deploy.

## About Hosting Moodle

Moodle is a PHP application that expects three things a container platform does not give it for
free. It needs its **cron** to run every minute: without it no email is ever sent, forum digests
and course-completion never process, scheduled backups never happen, and the notifications page
warns that the site is broken. It needs a **writable webroot** as well as a writable data
directory, because plugins installed from the admin UI are written into the code tree, not into
`moodledata`. And it needs to be told that TLS is terminated in front of it, or every generated
URL comes out as `http://` and browsers block the assets.

This image runs Moodle, nginx, PHP-FPM 8.3 and the Moodle cron worker under runit in a single
service, mounts one volume over `/var/www` so both the webroot and `moodledata` are durable,
repairs the volume's ownership on boot (Railway mounts volumes as uid 0 while the app runs
unprivileged), honours Railway's injected `$PORT`, derives the site URL and the SSL-proxy
setting from `RAILWAY_PUBLIC_DOMAIN`, and sizes PHP-FPM's worker pool and the opcache from the
container's own cgroup limits rather than a fixed guess. The admin password is generated per
deploy and re-applied on every boot, so a redeploy doubles as a working password reset — useful,
because a fresh Moodle has no mail server to send a reset link through.

## 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 are one step closer to supporting a complete full-stack
application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

## Common Use Cases

- Run a school, university department or training provider's LMS without paying for MoodleCloud.
- Host a private course catalogue for staff onboarding and compliance training, with completion
  tracking and certificates.
- Stand up a disposable Moodle for plugin or theme development, where you install add-ons from
  the admin UI and expect them to still be there after the next deploy.

## Dependencies for Moodle Hosting

- A PostgreSQL database (included in this template as a second service, on its own volume).
- A persistent volume for the application service, mounted at `/var/www`.

### Deployment Dependencies

- Moodle: https://moodle.org
- Moodle docs: https://docs.moodle.org
- Base image: https://github.com/erseco/alpine-moodle
- This wrapper: https://github.com/bon5co/moodle-railway

### Implementation Details

The deploy form asks for nothing. `MOODLE_PASSWORD` is generated per deployment, and the
container refuses to boot if it is empty rather than starting with a guessable account. Sign in
as `admin` with the generated password from the service's variables, then change it in the UI if
you prefer.

Cron runs inside the same container once a minute. Plugins installed through
*Site administration → Plugins* land on the volume and are preserved across image updates.


## Similar templates

- [Libredesk - Complete Setup](https://railway.com/deploy/libredesk-complete-setup) — Complete self-hosted omnichannel customer support desk.
- [Paperless-ngx](https://railway.com/deploy/paperless-ngx-3) — Paperless-ngx — document management with OCR and full-text search
- [Instatic CMS - Postgres](https://railway.com/deploy/instatic-cms-postgres) — Design, build and manage powerful static sites from state-of-the-art CMS

Open this page in a browser: https://railway.com/deploy/moodle-or-just-updated-lms-whose-cron-ac
