How to host and deploy Moodle in 2026: options and traps
MoodleCloud, partner hosting, a VPS, containers or Kubernetes: what each costs you in Moodle 5.x, and the storage, cache, cron and upgrade details that bite.
Short answer: if you can’t install plugins and don’t want to run servers, use MoodleCloud. If you need plugins but not a sysadmin, pay a Moodle Certified Partner. If you have someone who runs Linux servers, a single well-tuned VPS with PostgreSQL, Redis and a real cron covers a lot more sites than people expect. Containers and Kubernetes are worth it when you need several web nodes or many Moodle sites, and not before.
The hosting choice matters less than four details most guides skip: where moodledata lives, how caching and sessions are set up, whether cron actually runs, and who keeps your custom plugins working through upgrades. This post covers the options first, then those details.
What are the real options for hosting Moodle?
| Option | You manage | Plugins | Fits |
|---|---|---|---|
| MoodleCloud | Nothing on the server | Not allowed | Course sellers, small teams with basic needs |
| Certified Partner / managed host | Your content and requirements | Yes, usually reviewed by the host | Schools and companies without in-house ops |
| VPS (LAMP or LEMP) | Everything | Yes | One site, someone on staff who runs Linux |
| Containers / Kubernetes | Everything, plus the platform | Yes, baked into the image | Several web nodes, many sites, an ops team |
MoodleCloud
MoodleCloud is Moodle HQ’s own hosted service. Moodle describes it as “a quick, ready-to-go option with all the core Moodle features you need, but it has some limits”, aimed at “individuals who sell courses, or small organisations”.1 Each plan has a maximum number of users, and the MoodleCloud page is blunt about the other limit: “we don’t allow the installation of plugins”.2
That second line decides it for most organisations. No plugins means no custom plugins, no third-party attendance or certificate plugins beyond what the plan ships with, and no custom integrations. If that is fine for you, MoodleCloud removes every problem in the rest of this post.
Moodle Partners and managed hosting
Moodle’s enterprise hosting runs through its Certified Partner network. Moodle says partner hosting lets you “install plugins, integrate with other systems, and scale to thousands of users”, and that Moodle Workplace is only available through Moodle and its Premium Certified Partners.1 Outside the partner network there are plenty of managed hosts that run Moodle well.
What to ask any managed host before signing:
- Which Moodle version they run today, and how soon after a release they upgrade.
- How you get a custom plugin onto the site, and who tests it.
- Whether you can get a full database dump and a copy of
moodledataon request. If not, you are locked in. - Whether cron runs every minute, and whether they run separate ad hoc task workers.
- Whether you get a staging site.
A plain VPS
One server running Nginx or Apache, PHP-FPM, PostgreSQL or MySQL, and Redis. It is the cheapest option with full control, and the one where every mistake is yours. The MoodleDocs install guide lists 512MB of RAM as the minimum, 1GB as recommended, and “8GB plus is likely on a large production server”.3
The same guide refuses to give a users-to-hardware formula. On “what hardware do I need for 50,000 users”, it says you are “highly unlikely to get a useful answer”, and recommends starting with a small pilot.3 We agree. Usage pattern (a quiz with 400 students starting at 9:00) matters more than the number of accounts.
Keep PHP current. Moodle 5.3 needs PHP 8.3 or 8.4, and running Moodle on an unsupported PHP is a security problem on its own; see outdated PHP and Moodle security and the Moodle 5 requirements table.
Containers
Two things to know before you search Docker Hub.
moodlehq/moodle-docker is not a production setup. Its README says it is “aimed at Moodle developers and testers to easily deploy a testing environment for Moodle”.4 It ships every supported database, Selenium for Behat, and a mail catcher. The base image it uses, moodlehq/moodle-php-apache, is described as “configured for Moodle development”.5 Use both for development and plugin testing. Build your own production image.
The Bitnami Moodle image and Helm chart are no longer a free, maintained option. In July 2025 Bitnami announced that from 28 August 2025 it would stop publishing new images and charts to Docker Hub, move existing images to a bitnamilegacy repository that “will receive no further updates or support”, and put production images behind its paid Bitnami Secure Images offering.6 The free images that remain are “intended for development and are only available on the ‘latest’ tag”. On 31 October 2026, bitnamilegacy/moodle exists with tags last updated in August 2025, and the Moodle chart on the main branch of bitnami/charts still pins Moodle 5.0.2.7 Moodle 5.0 lost security support on 5 October 2026.8 If you deployed with the Bitnami chart, you are running an unpatched Moodle unless you pay or build your own image.
A sane production image is boring: an official PHP-FPM base, the PHP extensions Moodle needs, Moodle code plus every plugin copied in at build time, and nothing writable inside the code directory.
Kubernetes and autoscaling
Kubernetes does not change what Moodle needs. It makes the cluster rules in the MoodleDocs Server cluster page non-negotiable:9
$CFG->datarootmust be shared by all nodes, with locking support (NFS is the example given). This holds even if you use an alternative file system for file content.$CFG->tempdirand$CFG->backuptempdirmust be shared too.$CFG->localcachedirshould be local, fast disk on each node.- Sessions go in one shared store, such as Redis.
- The code directory should be read-only to the web server, so nobody installs a plugin on one pod and not the others.
That last rule means plugin installs and upgrades happen in your image build and deploy pipeline, never through the admin UI. Autoscaling web pods works well once that is true. The database does not autoscale. Moodle supports read replicas, and the performance page says that on very large systems “as much as 80-90% of the DB load can be moved away from the primary”.10
Rules of thumb by size
MoodleDocs does not publish a sizing table, so this is not one. These are our rules of thumb, and a pilot with your own usage beats all of them.
| Site | Rule of thumb |
|---|---|
| Under ~500 active users, no custom plugins | MoodleCloud, or a small managed plan |
| Under ~500 users, needs plugins | One VPS or a partner. Redis and CLI cron from day one |
| A few thousand users | One strong VPS or separate web and database servers. Redis for cache and sessions. Dedicated ad hoc task workers |
| Tens of thousands, or heavy exam peaks | Several web nodes behind a load balancer, shared storage or object storage, managed PostgreSQL or MySQL with a replica, a partner or an ops team |
Where should moodledata live: NFS or object storage?
On one server, moodledata is a local directory outside the web root. On several servers it has to be shared, and that is where performance usually goes wrong. MoodleDocs warns that slow network storage like NFS can cause performance problems with Moodle’s default file-based caches, and points to Redis or Memcached.3
The common fix for large file stores is tool_objectfs, a plugin from Catalyst IT that moves file content to S3, Azure Blob, Google Cloud Storage, DigitalOcean Spaces or OpenStack Swift.11 Two caveats:
- It moves file content, not the whole data root. You still need a shared
datarootfor a cluster.9 - It is a third-party plugin. Its default branch declares support for Moodle 4.4 and 4.5 in
version.php. Check for a release tested on your Moodle 5.x version before you depend on it, and remember that on 5.1+ it lives underpublic/admin/tool/objectfs.
How should caching and sessions be set up?
Moodle’s caching layer (MUC) defaults to files in moodledata. The performance page calls that “rather slow overall” and says Redis is “highly recommended” for large and load-balanced sites.10 Practical setup:
- Map the Application and Session caches to a Redis store. Leave the request cache alone; the Redis store page says Redis “isn’t fully compatible” with it.12
- Store user sessions in Redis too. The session docs say database sessions are “not recommended for large sites”.13
- Use a non-empty prefix, the same prefix on every node, and different prefixes for cache and sessions.12 Use the igbinary serializer if available.
- Give Redis enough memory if it shares a box with the database.
Why do cron and ad hoc tasks matter so much?
Because half of Moodle runs there: forum emails, grade recalculation, course backups, completion, search indexing, and since 5.3 asynchronous course deletion. MoodleDocs recommends running cron every minute, from the command line, not over HTTP.1410
On busier sites, add dedicated ad hoc task workers with admin/cli/adhoc_task.php --execute --keep-alive=59, which waits for new tasks instead of exiting. By default only 3 scheduled and 3 ad hoc tasks run at once, so raise those limits when you add workers. Task locking means cron can safely run from several web nodes.14
If a teacher says “the emails come hours late” or “the backup never finished”, look at cron first.
What OPcache settings does Moodle need?
The MoodleDocs OPcache page says the extension is “strongly recommended”. Size opcache.memory_consumption so it never fills (Moodle 5.0’s PHP alone is about 153MB before plugins and language packs), and for Moodle 5.0 it suggests opcache.max_accelerated_files of 18000. Turn on opcache.enable_cli so CLI cron benefits too.15
PostgreSQL or MySQL/MariaDB?
Moodle supports PostgreSQL, MySQL, MariaDB and SQL Server,16 and the MoodleDocs database page does not name a favourite.17 Our opinion: pick PostgreSQL for a new site, mainly because its behaviour on large tables and upgrades is predictable. If your team already runs MySQL or MariaDB well, stay; switching databases is a migration project, not a setting. Whatever you pick, check the floor: Moodle 5.3 needs PostgreSQL 17, MySQL 8.4 or MariaDB 11.4, and the minimum has risen every release.16
What does the /public web root in Moodle 5.1 change?
From Moodle 5.1, web-accessible files live in a public folder, and the release notes say: “Your web server now needs to be configured so that its document root points to this /public directory”. Sites that upgrade without changing it can stop loading.18 Config and other sensitive files now sit outside the web root, which is a real security gain.
Separately, 5.1 added a routing engine. It needs a fallback rule, FallbackResource /r.php on Apache or try_files $uri /r.php$is_args$args; on Nginx. The current MoodleDocs page says a working router is not yet strictly required for a basic install, but Moodle HQ plans to make it mandatory, and 5.2 added warnings when it is missing.19 Set it up now.
Also check: deploy scripts that copy plugins into old paths, backup scripts with hard-coded paths, and git-based installs, where existing plugins must be moved by hand into public/.20 For why Moodle’s layout looks like this at all, see our history of Moodle’s architecture.
How should upgrades and backups work?
The upgrade guide says to back up three things: the code, moodledata and the database, and to test the upgrade on a copy of production first.20 Put the site in maintenance mode, wait for cron to finish, and run the upgrade from the CLI. The site backup page adds --single-transaction for MySQL and MariaDB dumps.21
Our rules:
- Course backups are not a site backup. Restoring 300
.mbzfiles is not a disaster recovery plan. - Test a restore at least once a quarter, onto a fresh server.
- Keep code in git with every plugin pinned, so you can rebuild the exact site.
The upgrade itself is rarely the problem. Custom plugins are. A host can upgrade core Moodle in an afternoon, then stop because three in-house plugins call removed functions or still use Atto. We wrote up what breaks when you upgrade Moodle and how to fix it. If those plugins have no maintainer, that is the work our Moodle developers take on.
Sources
-
Moodle, Moodle hosting solutions. ↑ ↑
-
Moodle, MoodleCloud. ↑
-
MoodleDocs, Installing Moodle (5.3). ↑ ↑ ↑
-
Moodle HQ, moodle-docker README. ↑
-
Moodle HQ, moodle-php-apache README. ↑
-
Bitnami, Upcoming changes to the Bitnami catalog (effective August 28th, 2025). ↑
-
Bitnami, moodle chart, Chart.yaml on main, and Docker Hub, bitnamilegacy/moodle, both checked 31 October 2026. ↑
-
Moodle HQ, Releases and support dates. ↑
-
MoodleDocs, Server cluster. ↑ ↑
-
MoodleDocs, Performance recommendations. ↑ ↑ ↑
-
Catalyst IT, moodle-tool_objectfs, README and
version.phpon the default branch, checked 31 October 2026. ↑ -
MoodleDocs, Redis cache store. ↑ ↑
-
MoodleDocs, Session handling. ↑
-
Moodle HQ, Moodle 5.3 release notes. ↑ ↑
-
Moodle HQ, Moodle 5.1 release notes. ↑
-
MoodleDocs, Configuring the Router. ↑
-
MoodleDocs, Upgrading (5.3). ↑ ↑
-
MoodleDocs, Site backup. ↑
Need a Moodle plugin built or rescued?
Tell the scoping assistant what you need. You get a fixed price and a timeline in a few minutes, and an engineer reviews it within one business day.
Get a fixed quote