Deployment guide

Moodle 5.2

Overview

Moodle is an open source learning management system for building courses, enrolling learners and tracking their progress. This SecureAnyCloud image runs Moodle 5.2 on Ubuntu 24.04 LTS, ready to use on a single Azure virtual machine.

What you get:

  • nginx as the application server, with PHP-FPM 8.3 and OPcache enabled
  • PostgreSQL 16 on the same virtual machine for content and grade data, bound to the loopback interface only
  • Moodle scheduled tasks that run every minute through a systemd timer, so course backups, message delivery, badge issuing and other lifecycle jobs run without manual intervention
  • Moodle administrator and PostgreSQL credentials generated on the first boot of every deployed virtual machine, so two virtual machines launched from the same gallery image never share passwords
  • Credentials written to /root/moodle-credentials.txt with mode 0600, so only the root user can read them
  • Automatic site URL configuration on first boot (see below)

The virtual machine needs a public IP address, or a private IP address that learners can reach. On first boot, a small service queries the Azure Instance Metadata Service, detects the virtual machine's public IP, and sets $CFG->wwwroot in the Moodle configuration file. If no public IP is attached, the service falls back to the primary private IP address. Deployments behind an Azure Application Gateway or a private VNet therefore still work.

Prerequisites

Before you deploy this image, you need:

  • A Microsoft Azure subscription where you can create resource groups, virtual networks and virtual machines
  • Azure role permissions equivalent to Contributor on the target resource group
  • An SSH public key for the first login to the administrator account
  • A virtual network and subnet in the same region as the Azure Compute Gallery that the image is published into. The associated network security group must allow inbound port 22 from your management network, and inbound ports 80 and 443 from the networks your learners will use
  • The Azure CLI (az version 2.50 or later), installed locally if you plan to deploy from the command line
  • The SecureAnyCloud Moodle 5.2 offer enabled on your tenant in Azure Marketplace
1

Deploy the Virtual Machine from the Azure Portal

Sign in to the Azure Portal at https://portal.azure.com. Search the Marketplace for Moodle 5.2 LMS on Ubuntu 24.04 by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription and resource group and give the virtual machine a name. Choose a region that is in the gallery replication list for this offer, select the image version, and pick a size of Standard_D2s_v3 or larger.

On the Disks tab, choose Standard SSD (locally redundant storage) to balance cost and performance. A small deployment does not need a hot managed disk.

On the Networking tab, select your virtual network and subnet and attach a Standard SKU public IP. Open ports 22 (from your management CIDR only), 80 and 443 on the network security group. You can skip port 443 for the initial deployment if you do not yet have a TLS certificate and plan to use Let's Encrypt in Step 10.

Review and create the virtual machine. First boot takes approximately one minute after the provisioning state becomes Succeeded.

2

Deploy the Virtual Machine from the Azure CLI

The commands below create a resource group, a virtual network with a single subnet, and a network security group. The security group opens port 22 to your management network and ports 80 and 443 to the Internet. They then create a virtual machine from the latest version of the SecureAnyCloud Moodle 5.2 Azure Compute Gallery image.

Replace <your-mgmt-cidr> with the CIDR block of the network you will SSH from, for example 203.0.113.0/24. Replace <sub-id> with your Azure subscription GUID.

LOCATION=eastus RG=moodle-5-2-rg VM_NAME=moodle-lms-01 ADMIN_USER=moodleadmin SSH_KEY=~/.ssh/id_rsa.pub MGMT_CIDR=<your-mgmt-cidr> SUB_ID=<sub-id> IMAGE_ID="sac1647283583153:moodle-5-2-ubuntu-24-04:standard:latest" az group create --name $RG --location $LOCATION az network vnet create \
  --resource-group $RG \
  --name moodle-vnet \
  --address-prefix 10.40.0.0/16 \
  --subnet-name moodle-subnet \
  --subnet-prefix 10.40.1.0/24 az network nsg create --resource-group $RG --name moodle-nsg az network nsg rule create \
  --resource-group $RG --nsg-name moodle-nsg \
  --name AllowSSH --priority 1000 --access Allow \
  --protocol Tcp --direction Inbound \
  --source-address-prefixes $MGMT_CIDR \
  --destination-port-ranges 22 az network nsg rule create \
  --resource-group $RG --nsg-name moodle-nsg \
  --name AllowHTTP --priority 1010 --access Allow \
  --protocol Tcp --direction Inbound \
  --source-address-prefixes '*' \
  --destination-port-ranges 80 az network nsg rule create \
  --resource-group $RG --nsg-name moodle-nsg \
  --name AllowHTTPS --priority 1020 --access Allow \
  --protocol Tcp --direction Inbound \
  --source-address-prefixes '*' \
  --destination-port-ranges 443
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:moodle-5-2-ubuntu-24-04:standard:latest
az vm create \
  --resource-group $RG \
  --name $VM_NAME \
  --image $IMAGE_ID \
  --size Standard_D2s_v3 \
  --admin-username $ADMIN_USER \
  --ssh-key-values $SSH_KEY \
  --vnet-name moodle-vnet \
  --subnet moodle-subnet \
  --nsg moodle-nsg \
  --public-ip-sku Standard \
  --os-disk-size-gb 64

On success, the command prints a JSON document. Note the publicIpAddress value, which you use in Steps 3 and 4.

3

Retrieve Initial Credentials

SSH into the virtual machine with the administrator username you chose and the public IP address from Step 2. The first boot service runs before the SSH daemon becomes ready, so the credentials file is always in place when you first log in.

ssh moodleadmin@<public-ip>
sudo cat /root/moodle-credentials.txt

The plain text file contains the Moodle URL, the admin administrator username (admin), the administrator password (32 characters plus a policy marker), and the PostgreSQL role, database name and password.

Copy these values somewhere secure, such as a password manager or encrypted vault. Do not commit them to source control.

To change the credentials later, use the Moodle web interface (Step 6). For PostgreSQL, run ALTER ROLE moodle WITH PASSWORD '<new>' as the postgres operating system user. Then make a matching edit to $CFG->dbpass in /var/www/moodle/config.php.

4

First Login to the Moodle Web Interface

Open a web browser and go to the Moodle URL from the credentials file, for example http://<public-ip>/. When no session cookie is present, Moodle redirects the front page to the login form.

Enter the admin username (admin) and the administrator password from /root/moodle-credentials.txt, then select Log in. After the first successful sign-in, Moodle records your session and opens the administrator dashboard.

5

Administrator Dashboard

The dashboard at /my/ is the starting point for managing your Moodle site. The top navigation bar gives you Dashboard for a personalised view and Site administration for global settings.

The Course overview block prompts you to create your first course, and the Timeline block shows upcoming activities. Notifications and messages are in the top right. The user menu lets you sign out or open your profile and preferences.

6

Change the Administrator Password

For a production deployment, change the administrator password that was generated on first boot. Select the user menu in the top right of the dashboard (the AU avatar), choose Preferences, then User account > Change password.

Enter the current password from /root/moodle-credentials.txt, pick a new one that satisfies the Moodle password policy, and select Save changes.

You can also change the password from the command line with Moodle's CLI tool:

sudo -u www-data php /var/www/moodle/admin/cli/reset_password.php \
  --username=admin \
  --password='<new-password>' \
  --ignore-password-policy
7

Site Administration

Select Site administration in the top navigation bar, then Plugins, to review the components installed on your site. The Plugins overview page lists the activity modules, authentication plugins, enrolment plugins, blocks, filters, themes and local plugins that ship with Moodle 5.2.

Use the Settings link next to each module to tailor its behaviour. For example, disable BigBlueButton if you do not run a conference server, or enable the LTI plugin if you integrate with a third-party tool provider.

Other frequently used pages under Site administration include:

  • Users > Authentication for manual accounts, email signup, LDAP and SAML2
  • Courses > Course categories for the top-level structure
  • Server > System paths if you need to point Moodle at a custom ImageMagick binary or similar
8

Create Your First Course

Select Site administration > Courses > Manage courses and categories. Choose a category (Moodle ships with a default Category 1), then select Create new course.

Under General, enter a course full name and a short name, which appears in breadcrumbs and headers. Confirm the course category. Select Save and display to create the course and open it, or Save and return to continue administering categories.

From the course page, you can add sections, activities (quizzes, assignments, forums, SCORM packages, H5P, BigBlueButton sessions) and resources (files, pages, URLs, books). Use Enrolled users under the course Participants menu to add teachers and students. To set up self-enrolment, go to Course administration > Enrolment methods.

9

Configure Outbound Email (SMTP)

By default, Moodle sends mail through the local sendmail binary. For reliable delivery on a cloud virtual machine, configure an external SMTP provider such as SendGrid, Mailgun, Amazon SES or Microsoft 365.

Select Site administration > Server > Email > Outgoing mail configuration. Set the SMTP hosts field to smtp.example.com:587, set SMTP security to TLS, and set SMTP authentication type to LOGIN. Enter the SMTP username and password issued by your provider.

Set the No-reply address to an address your provider lets you send from, for example no-reply@example.com. Save the settings. Then select Site administration > Server > Test outgoing mail configuration to send a test message to your own inbox.

10

Enable HTTPS with Let's Encrypt

For any production Moodle deployment, serve the site over HTTPS so that session cookies and authentication tokens cannot be intercepted. The image ships with nginx, which certbot can configure automatically.

These commands assume a DNS A record points your fully qualified domain name (for example moodle.example.com) at the virtual machine's public IP address.

sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx -d moodle.example.com \
  --non-interactive --agree-tos -m you@example.com \
  --redirect

When certbot finishes, edit /var/www/moodle/config.php and change $CFG->wwwroot from http://moodle.example.com to https://moodle.example.com.

Then run sudo -u www-data php /var/www/moodle/admin/cli/purge_caches.php so that Moodle rebuilds its theme cache under the new base URL.

11

Backups and Maintenance

Moodle has two data sources that you must back up together: the PostgreSQL database, and the moodledata directory at /var/moodledata. The moodledata directory holds course files, user files, session data and caches.

sudo -u postgres pg_dump -Fc moodle > /var/backups/moodle-db-$(date +%F).dump
sudo tar --acls --xattrs -czf /var/backups/moodle-data-$(date +%F).tgz -C /var moodledata

Copy both files to Azure Blob Storage, an off-site S3 bucket or another object store of your choice. The Moodle cron timer installed with the image also triggers scheduled course backups if you enable them under Site administration > Courses > Backups > Automated backup setup.

Ubuntu's unattended-upgrades is enabled by default, so security patches for the kernel and packages apply automatically. To install non-security upgrades, run:

sudo apt-get update && sudo apt-get -y upgrade

When Moodle publishes a minor release (for example 5.2.1), you can upgrade the source tree in place:

sudo -u www-data php /var/www/moodle/admin/cli/maintenance.php --enable cd /var/www/moodle
sudo git fetch origin MOODLE_502_STABLE
sudo git pull
sudo -u www-data php /var/www/moodle/admin/cli/upgrade.php --non-interactive sudo -u www-data php /var/www/moodle/admin/cli/maintenance.php --disable
12

Scaling Beyond a Single Virtual Machine

For larger deployments, with hundreds of concurrent users and above, move Moodle off the single virtual machine pattern:

  • Move PostgreSQL to Azure Database for PostgreSQL Flexible Server, and update $CFG->dbhost and $CFG->dbpass in /var/www/moodle/config.php
  • Put the Moodle web tier behind Azure Application Gateway or Azure Front Door, and scale horizontally with an Azure Virtual Machine Scale Set. Keep /var/moodledata on Azure Files shared storage
  • Offload session storage to Azure Cache for Redis through Moodle's session_handler_class setting
  • Push static assets to Azure Blob Storage through the Moodle tool_objectfs plugin

The official Moodle admin documentation at https://docs.moodle.org/ covers each of these under "Performance recommendations" and "Multi site Moodle".

Support

SecureAnyCloud provides 24/7/365 expert technical support for this image. Response is guaranteed within 24 hours, with a one-hour average for critical issues. Contact sales@secureanycloud.com.

For general Moodle administration questions, consult the community forums at https://moodle.org/ and the documentation at https://docs.moodle.org/.

Deploy on Azure

Launch Moodle 5.2 LMS on Ubuntu 24.04 on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure