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 upgrade on 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

  1. Cron is your friend — the image already runs Moodle cron every minute; if scheduled tasks back up, check Site administration → Server → Tasks.
  2. PHP OPcache is already active with mod_php — don’t disable it.
  3. Right-size the instance — Moodle is memory-hungry with concurrent users; if htop shows sustained CPU saturation or MariaDB is swapping, step up one size (t3.mediumt3.large on AWS, B2sD2as_v4 on Azure).
  4. 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 admin password 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).