Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › Apache

How to Install Moodle on a VPS (Ubuntu, Apache or Nginx)

By Freedom251 Team · · 11 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To install Moodle on a VPS, prepare a supported Linux web stack, create a dedicated database, keep moodledata outside the public web root, run Moodle’s installer, and finish with HTTPS, permissions, cron, backups, and updates. The exact PHP and database versions depend on the Moodle branch you choose.

The current official downloads page identifies Moodle 5.3 as the latest update. Moodle 4.5.15 is listed as a security-supported release, with PHP 8.1 or newer and specific database minimums. Check the requirements for your selected branch before installing packages.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Choose the Moodle release and plan the VPS

Moodle is a PHP application that uses a relational database and a web server. Your VPS must provide all three components, plus enough storage and memory for course files, concurrent users, database queries, scheduled tasks, and backups. There is no universal “minimum VPS size”: a small private course and a busy school have very different workloads.

Check release-specific requirements first

Requirements change between branches. The Moodle 4.5 server-requirements documentation specifies PHP 8.1.0 as the minimum. The security-supported Moodle 4.5.15 listing also specifies MariaDB 10.6.7 or MySQL 8.0, PostgreSQL 13, Microsoft SQL Server 2017, or Oracle 19c as supported database baselines. Moodle’s current downloads page identifies Moodle 5.3 as the latest update, so do not assume that a 4.5 package’s requirements apply to 5.3.

Use the Moodle 4.5 server requirements page when installing 4.5, and consult the corresponding requirements for any other branch. Select one PHP version and use that same version for both the command-line interface and PHP-FPM.

Item Known requirement or guidance Qualification
Moodle 4.5 PHP PHP 8.1.0 minimum Applies to the 4.5 branch; later branches may require newer PHP.
Moodle 4.5.15 databases MariaDB 10.6.7, MySQL 8.0, PostgreSQL 13, SQL Server 2017, or Oracle 19c Versions listed for the security-supported 4.5.15 release.
Latest official download-page update Moodle 5.3 Verify its server requirements before provisioning.
Web server Apache or Nginx Install and configure one, not both.
Data directory moodledata outside the document root Must be writable by the web-server account and inaccessible to browsers.

Prepare access and naming

  • A fresh Ubuntu VPS with sudo or root access.
  • A DNS name such as moodle.example.com, or a temporary IP address for initial testing.
  • A plan for off-site backups of the database, moodledata, and config.php.
  • Enough disk space for uploaded files, the database, temporary backups, and future upgrades. Monitor usage rather than relying on a generic disk figure.

2. Update Ubuntu and apply basic network controls

Connect over SSH as a sudo-capable account. The commands below assume a current Ubuntu Server installation without a desktop environment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Update package indexes and installed packages:
    sudo apt update
    sudo apt -y full-upgrade

    Reboot if the kernel or core libraries were upgraded, then reconnect.

  2. Install common utilities used during the deployment:
    sudo apt install -y ca-certificates curl unzip tar git ufw
  3. Allow SSH and web traffic before enabling the firewall. If your SSH service uses a non-standard port, allow that port instead of OpenSSH:
    sudo ufw allow OpenSSH
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable
    sudo ufw status verbose
  4. Point your DNS A/AAAA record at the VPS. Keep the time-to-live low while testing, then raise it after the address is stable.

Do not expose MariaDB, MySQL, or PostgreSQL directly to the internet unless a documented remote-access design requires it. Moodle and the database can communicate over the VPS’s local socket or loopback interface.

3. Install PHP, extensions, and a database

Install the PHP version required by your branch

Ubuntu package names vary by release and by the PHP version in use. Install the default packages only after confirming that Ubuntu’s default PHP satisfies Moodle’s requirement; otherwise use your organization’s approved repository for the required version.

sudo apt install -y php-fpm php-cli 
  php-curl php-zip php-gd php-xml php-intl php-mbstring 
  php-soap php-bcmath php-exif php-ldap php-mysql php-opcache

Moodle’s Ubuntu installation guidance also lists XML-RPC among the extensions used by its example. On newer PHP releases, an XML-RPC package may be unavailable or supplied differently, so follow the selected branch’s extension list rather than forcing an obsolete package. Confirm both PHP interfaces:

php -v
php -m
systemctl status php*-fpm --no-pager

Check that the command-line PHP version and the FPM service version match. Raise upload and execution limits in the active FPM and web-server configuration when your courses contain large files, then restart PHP-FPM. Moodle’s administration screens will report settings that are too low for your workload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install MariaDB (or use another supported database)

The example below uses MariaDB, which is a straightforward local database choice on Ubuntu. A supported MySQL, PostgreSQL, SQL Server, or Oracle installation is also possible when it meets the release requirements and you adapt the driver and commands.

sudo apt install -y mariadb-server mariadb-client
sudo systemctl enable --now mariadb
sudo mariadb-secure-installation

Use the secure-installation prompts to remove anonymous users, disallow remote root login, remove the test database, and reload privilege tables. Then create a database with UTF-8 support and a separate account for Moodle:

sudo mariadb
CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moodleuser'@'localhost' IDENTIFIED BY 'replace-with-a-long-random-password';
GRANT ALL PRIVILEGES ON moodle.* TO 'moodleuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Store the database password in a password manager. Do not reuse the VPS administrator password, and do not grant the Moodle account global privileges.

4. Select and configure one web server

Apache and Nginx are both valid Moodle choices. Apache has extensive Moodle community documentation and familiar per-directory tooling. Nginx can be efficient for busier sites, but its PHP-FPM and fallback configuration must be written explicitly. Operational familiarity, expected traffic, logging, and your team’s existing tooling matter more than a generic performance claim.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision point Apache Nginx
PHP integration Enable proxy modules and pass PHP files to PHP-FPM. Configure a FastCGI location and the correct PHP-FPM socket.
Rewrite and fallback Use a virtual host and Moodle’s directory rules. Use try_files so non-file requests reach index.php.
Administration Often easier for teams already using Apache modules and virtual hosts. Often preferred by teams standardizing on Nginx configuration and centralized proxying.
Logging Separate access and error logs per virtual host. Separate access and error logs per server block.
Installation rule Install and expose one web server, not both on ports 80 and 443.

Option A: Apache with PHP-FPM

sudo apt install -y apache2 libapache2-mod-fcgid
sudo a2enmod proxy_fcgi setenvif rewrite headers env dir mime
sudo a2enconf php8.1-fpm

Replace php8.1-fpm with the FPM configuration that matches your installed PHP version. Create a virtual host such as /etc/apache2/sites-available/moodle.conf:

<VirtualHost *:80>
    ServerName moodle.example.com
    DocumentRoot /var/www/moodle

    <Directory /var/www/moodle>
        Options FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    <FilesMatch .php$>
        SetHandler 'proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost/'
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/moodle-error.log
    CustomLog ${APACHE_LOG_DIR}/moodle-access.log combined
</VirtualHost>

Change the socket path to the file present under /run/php/. Enable the site and test the syntax:

sudo a2dissite 000-default.conf
sudo a2ensite moodle.conf
sudo apachectl configtest
sudo systemctl reload apache2

Option B: Nginx with PHP-FPM

sudo apt install -y nginx
sudo systemctl enable --now nginx

Create /etc/nginx/sites-available/moodle. The socket name must match your installed FPM version:

server {
    listen 80;
    listen [::]:80;
    server_name moodle.example.com;
    root /var/www/moodle;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ [^/].php(/|$) {
        fastcgi_split_path_info ^(.+?.php)(/.+)$;
        try_files $fastcgi_script_name =404;
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

    location ~ /. {
        deny all;
    }

    access_log /var/log/nginx/moodle-access.log;
    error_log /var/log/nginx/moodle-error.log;
}
sudo ln -s /etc/nginx/sites-available/moodle /etc/nginx/sites-enabled/moodle
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Keep moodledata outside /var/www/moodle; the Nginx rule above is not a substitute for that separation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Download Moodle and place the code safely

Obtain the archive for the branch you selected from Moodle’s official downloads page, or obtain the branch through Moodle’s documented Git distribution. Verify the version and, where available, the archive checksum before unpacking it.

One safe layout is:

  • /var/www/moodle — Moodle application code and the generated config.php.
  • /var/moodledata — uploaded files, caches, sessions, and other data; never a public web directory.
sudo mkdir -p /var/www/moodle /var/moodledata
sudo tar -xzf /tmp/moodle-release.tar.gz --strip-components=1 -C /var/www/moodle
sudo chown -R www-data:www-data /var/www/moodle /var/moodledata
sudo chmod 770 /var/moodledata

The archive filename in the command is an example; use the file you actually downloaded. If your web server runs as a different account, substitute that account for www-data. During installation the web process must be able to create config.php and write to moodledata.

After installation, reduce write access to the code tree. A common production baseline is root ownership with the web-server group able to read, directories at 755, and files at 644:

sudo chown -R root:www-data /var/www/moodle
sudo find /var/www/moodle -type d -exec chmod 755 {} ;
sudo find /var/www/moodle -type f -exec chmod 644 {} ;
sudo chown -R www-data:www-data /var/moodledata
sudo find /var/moodledata -type d -exec chmod 770 {} ;

Do not make the entire web root world-writable. If you use a web-based upgrade workflow, follow Moodle’s documented ownership requirements for that workflow rather than broadly relaxing permissions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Run the Moodle installer

Use the command-line installer

The CLI installer is predictable and works well over SSH. Run it as the web-server account so generated files have appropriate ownership:

sudo -u www-data /usr/bin/php /var/www/moodle/admin/cli/install.php 
  --wwwroot='https://moodle.example.com' 
  --dataroot='/var/moodledata' 
  --dbtype='mariadb' 
  --dbhost='localhost' 
  --dbname='moodle' 
  --dbuser='moodleuser' 
  --dbpass='replace-with-a-long-random-password' 
  --fullname='Example Learning Site' 
  --shortname='Example' 
  --adminuser='admin' 
  --adminpass='replace-with-a-unique-admin-password' 
  --adminemail='[email protected]' 
  --non-interactive 
  --agree-license

Use the final HTTPS URL only after HTTPS will be available, or begin with the temporary HTTP URL and update Moodle’s stored URL during the HTTPS migration. The administrator password should be long, unique, and stored in a password manager.

Use the browser installer instead

  1. Browse to the server name or temporary IP address.
  2. Choose the language and confirm the detected paths.
  3. Set the data directory to /var/moodledata, not a directory under the document root.
  4. Select the database driver, then enter the database name, user, host, and password created earlier.
  5. Review the environment check. Resolve missing extensions, unsupported PHP versions, writable-path errors, and database collation warnings before continuing.
  6. Enter the site name and administrator account, then let Moodle write config.php.

If the installer cannot write config.php, temporarily correct ownership on that file’s parent directory, rerun the installer, and apply the production permissions immediately afterward.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

7. Enable HTTPS and finish hardening

Plain HTTP exposes login credentials and session cookies. Obtain a certificate for the real hostname with Certbot after DNS points to the VPS and the chosen web server answers on port 80.

Apache certificate

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d moodle.example.com

Nginx certificate

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d moodle.example.com

Follow the prompts to redirect HTTP to HTTPS, then test renewal:

sudo certbot renew --dry-run

After changing the site from HTTP to HTTPS, make sure Moodle’s configured $CFG->wwwroot uses the HTTPS URL. If you changed it manually in config.php, clear Moodle caches from the CLI:

sudo -u www-data php /var/www/moodle/admin/cli/purge_caches.php

Review these production controls:

  • Allow only required inbound ports through the VPS firewall.
  • Keep the database bound to local access unless remote administration is explicitly required and protected.
  • Use separate, strong credentials for SSH, the database, and Moodle administrators.
  • Keep Ubuntu, PHP, the web server, the database, and Moodle on supported security branches.
  • Inspect web-server and PHP-FPM logs after each configuration change.
  • Protect backups from the web root and restrict their permissions.

8. Configure Moodle’s cron task

Moodle needs its scheduled task runner for message delivery, enrolment synchronization, cache cleanup, backups, and other background work. Run it at least once per minute as the web-server account. Create /etc/cron.d/moodle:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
* * * * * www-data /usr/bin/php /var/www/moodle/admin/cli/cron.php >/dev/null

Use the absolute PHP path and confirm the command works manually:

sudo -u www-data /usr/bin/php /var/www/moodle/admin/cli/cron.php

In Moodle administration, check the scheduled-task status and investigate tasks that remain overdue. A cron process that runs as root can create files the web process cannot modify, so keep the account consistent.

9. Back up and test recovery

A VPS snapshot alone is not a complete Moodle backup. Preserve three items together:

  1. The database, exported with the database’s native dump tool.
  2. The complete /var/moodledata directory, including uploaded course files.
  3. /var/www/moodle/config.php and your deployment notes, including the Moodle branch and PHP version.

Store encrypted copies off the VPS, retain more than one restore point, and test restoring to a separate staging VPS. A backup that has never been restored is only an assumption. Schedule database dumps during a period of low activity and monitor backup jobs for failures and insufficient disk space.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

10. Common installation failures

Symptom Likely cause Fix
Environment check reports an unsupported PHP version The VPS installed Ubuntu’s default PHP, which is older than the Moodle branch requires. Install a supported PHP version, matching CLI and FPM, then restart FPM and reload the web server.
Blank page or “502 Bad Gateway” PHP-FPM is stopped, or the configured socket path is wrong. Check systemctl status php*-fpm, inspect /run/php/, correct the Apache or Nginx socket, test configuration, and reload.
Installer says moodledata is not writable The directory belongs to the wrong account or has restrictive permissions. Give the web-server account ownership of /var/moodledata and use a private mode such as 770; never move it into the public root.
“Database connection failed” Wrong host, database name, password, driver, or missing PHP database extension. Log in with the Moodle database account from the VPS, verify the database exists, and confirm the matching PHP driver is loaded.
Every URL returns the home page or 404 errors Fallback/rewrite rules are missing or the virtual host points at the wrong directory. For Apache, verify the active virtual host and rewrite handling. For Nginx, verify try_files, root, and the PHP location, then run the server’s config test.
Users are redirected between HTTP and HTTPS Moodle’s configured site URL and the certificate-enabled URL do not match. Set the canonical HTTPS URL in config.php, purge caches, and remove conflicting proxy redirects.
Scheduled tasks remain overdue Cron is absent, runs under the wrong user, or calls a different PHP version. Run the CLI cron command manually, inspect cron logs, and keep the task under the web-server account every minute.
Updates fail after permissions were tightened The deployment account cannot replace read-only Moodle code. Use a controlled maintenance procedure that temporarily grants the required ownership, performs the upgrade, and reapplies 755/644 production permissions.

11. Decide whether self-hosting is appropriate

A VPS gives you control over the operating system, PHP version, database, web server, network location, backups, and maintenance schedule. It also makes you responsible for patching every layer, monitoring disk and memory, renewing certificates, testing restores, and responding to outages.

If you do not want to maintain that stack, a managed Moodle provider or MoodleCloud can remove much of the server administration. Confirm that the service supports your chosen Moodle release, required plugins, data-residency needs, backup/restore workflow, user volume, and upgrade policy. The trade-off is less low-level control and a recurring service cost.

For a self-managed VPS, the installation is complete only when the selected release passes its environment checks, the site is reachable over HTTPS, moodledata is private, cron runs successfully, and a tested backup exists.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

ApacheLinuxMariaDBMoodleNGINXPHPself-hostingUbuntuVPS

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.