A Moodle upgrade is a database migration wearing a friendly web form. Behind the Upgrade button, hundreds of plugins run schema changes against tables with millions of rows, and a single incompatible plugin stops the whole thing halfway. The only safe way to find out what will happen is to do it somewhere that is not production. This post follows a Moodle administrator doing exactly that on MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic.
The administrator runs the Moodle package for a vocational school we will call Marlowe Institute: 8,000 students, twelve third-party plugins, a custom theme and a SAML plugin the whole login flow depends on. The task is the yearly jump to the next Moodle major version during the two-week summer break.
Why a permanent test server does not solve this
Marlowe used to keep a test Moodle. It had last been refreshed in March, so it lacked the two plugins installed since, ran a different PHP patch version and had a database a tenth the size of production's. Upgrades that passed on it took three times longer on production and once failed on a plugin the test server did not have. A test environment is only useful if it is a copy of production as of now, which is exactly what the platform's Clone Environment operation produces: a full copy of every container, the PHP layer with its code and plugins, the MariaDB node with its data, the Redis node and the shared storage with moodledata, in a few minutes, with its own URL.
Step one: clone and neutralise
The administrator clones production to moodle-upgrade-test and lowers the clone's cloudlet limits, since one tester does not need exam-week headroom. Then she makes the clone safe: in the clone's config.php she sets $CFG->noemailever = true so no student receives a notification from a test, and she changes $CFG->wwwroot to the clone's URL, which Moodle requires. The clone is placed in a separate environment group with network isolation so nothing in it can reach production's database over the internal network.
Step two: check every plugin before touching Moodle
Moodle's own plugin check page lists each installed plugin and whether a version compatible with the target Moodle release exists. Before any upgrade, the administrator works through the list on the clone. Ten plugins have compatible releases; one has a release candidate; the custom timetable plugin is the school's own and needs a developer's afternoon. She updates all twelve on the clone first, from the plugin admin page or by copying new versions into the plugin directories, and only then upgrades Moodle itself.
| Plugin | Compatible release for target Moodle | Action on clone | Outcome |
|---|---|---|---|
| auth_saml2 | Yes | Update, test login | Login works |
| mod_attendance, mod_hvp, block_xp and 7 others | Yes | Update | Fine |
| local_timetable (custom) | No, school's own | Developer patches for API changes | Two deprecations fixed |
| theme_marlowe (custom) | Based on Boost | Rebuild against new Boost | Three template overrides updated |
Step three: the upgrade itself, timed
With plugins ready, the administrator enables maintenance mode on the clone and runs the upgrade from the platform's Web SSH console rather than the browser, because the CLI does not time out and prints every step:
php admin/cli/maintenance.php --enable
php admin/cli/upgrade.php --non-interactive
php admin/cli/purge_caches.php
php admin/cli/maintenance.php --disable
Before running it she redeploys the clone's PHP container to the PHP version the new Moodle requires, a platform operation that keeps the deployed files, and confirms the required extensions. The upgrade on the clone takes 14 minutes against production-sized data; the largest part is the grade history and log tables. That number goes straight into the production plan: a 30-minute maintenance window, announced to students, with the actual upgrade expected to take a quarter of it.
Step four: test like a student, then like a teacher
The clone is now the new Moodle with real courses. The administrator logs in through SAML as a test student, opens a course, attempts a quiz, submits an assignment file (which lands on the clone's own moodledata, not production's), and checks the theme on a phone. Then as a teacher: grade the submission, run a report, edit a course page. Two teachers are invited to try their own courses on the clone for a day. Everything found is fixed on the clone and noted for production. The clone runs for four days in total and, being small, costs a couple of dollars.
Step five: production, with the rollback already made
On the day, the sequence on production is the one rehearsed, with two additions at the start. First, an on-demand backup through the Database Backup/Restore add-on. Second, a fresh clone of production, taken immediately before maintenance mode. That clone is the rollback: if the upgrade fails, the administrator can point the domain at the clone, which is production as it was five minutes ago, in the time it takes to change a DNS record or swap the environments' domains. Then: plugins updated, PHP container redeployed, maintenance on, CLI upgrade (11 minutes on production; the clone had been slightly under-provisioned), caches purged, maintenance off, a smoke test, and the announcement that Moodle is back.
The rollback clone is kept for a week and then deleted. It was not needed, which is the point of having it.
Frequently Asked Questions
Can I upgrade Moodle through the web installer instead of the CLI?
Yes, but the CLI is more reliable for large sites: the web upgrade can hit PHP or proxy timeouts on long steps, and the CLI prints progress and errors plainly. Use the web interface for the plugin check and for small sites; use admin/cli/upgrade.php for anything with real data.
How do I roll back if the upgrade fails halfway on production?
Restore the pre-upgrade backup into the database and redeploy the previous code, or, faster, switch the domain to the pre-upgrade clone you took minutes before. The platform can swap domains between two environments, so the clone becomes production and the failed upgrade becomes the thing you debug at leisure.
Should I upgrade plugins before or after Moodle?
Before, on the clone, to versions compatible with the target release; Moodle's plugin check tells you which. Upgrading Moodle first with old plugins installed can stop the upgrade on an incompatible one. If a plugin has no compatible release, uninstall it or accept that Moodle will disable it.
Rehearse the upgrade on this morning's data
Run Moodle on MassiveGRID PaaS and clone production in minutes before every upgrade or plugin install. The clone costs cents an hour and doubles as your rollback. Free 14-day trial, no credit card.
Moodle on MassiveGRID PaaS