A collection of practical advice for running the CloudSOE Moodle image in production, on either cloud.
Back up the three things that matter
A Moodle site is its database, its data directory and its config.php. A simple nightly backup:
sudo mysqldump moodle | gzip > /home/$(whoami)/moodle-db-$(date +%F).sql.gz
sudo tar czf /home/$(whoami)/moodledata-$(date +%F).tar.gz -C / var/moodledata
sudo cp /var/www/moodle/config.php /home/$(whoami)/config.php.bak
Ship those files off the instance (S3, Azure Blob, anywhere). Cloud-level snapshots are a good complement, but application-level dumps restore faster and across instance types.
Keep things updated
- Moodle minor updates: use Site administration → Notifications to see when a new release is available, and follow Moodle’s standard upgrade procedure (put the site into maintenance mode first).
- OS security updates come from Debian’s repositories:
sudo apt update && sudo apt upgradeon your own schedule. PHP 8.4 comes from the Sury repository, which is already configured in the image. - New CloudSOE image versions are published to the marketplaces — for major moves, launch a fresh instance and restore your backup rather than upgrading in place.
Performance quick wins
- Cron is your friend — the image already runs Moodle cron every minute; if scheduled tasks back up, check Site administration → Server → Tasks.
- PHP OPcache is already active with mod_php — don’t disable it.
- Right-size the instance — Moodle is memory-hungry with concurrent users; if
htopshows sustained CPU saturation or MariaDB is swapping, step up one size (t3.medium→t3.largeon AWS,B2s→D2as_v4on Azure). - Watch
/var/moodledata— course backups and uploaded files accumulate here; grow the disk before it fills.
Security hardening
The image already disables password SSH, generates all credentials per instance, redirects HTTP to HTTPS and keeps config.php out of the web root. On top of that:
- Change the generated
adminpassword after your first login (profile → Preferences → Change password). - Keep phpMyAdmin behind an IP allow-list in your security group / NSG, or remove it entirely.
- Review Site administration → Reports → Security checks — Moodle’s built-in audit catches most misconfigurations.
- Consider Cloudflare or the cloud provider’s WAF/CDN in front of the site.
Troubleshooting first boot
If the site doesn’t respond a few minutes after launch:
systemctl status moodle-firstboot
journalctl -u moodle-firstboot --no-pager
The setup script is safe to re-run: if it failed (for example a transient metadata-service hiccup), it retries automatically on the next boot because its completion marker was never written. A manual retry is just:
sudo systemctl restart moodle-firstboot
Note that the CLI installer runs during first boot, so allow a few minutes before assuming something is wrong.
The MOTD shows the wrong IP
The login banner captures the public IP at first boot. If you later attach a new Elastic IP / public IP, the banner will be stale. Edit /etc/motd to update it — and remember Moodle itself pins its URL in config.php (wwwroot), so update that too, as shown in the configuration guide.
Test HTTPS from outside
On Azure especially, a VM often cannot reach its own public IP from within. Always verify the site from your own machine:
curl -skI https://<public-ip>/
The certificate’s CN should be your public IP (or your domain once you’ve switched to Let’s Encrypt — see the configuration guide).