Moodle is the most widely used open-source learning management system. A small school can start on cPanel with Softaculous, but larger installs run best on a VPS. This guide shows how to install Moodle on a Linux VPS with Nginx and PHP-FPM.
Before you start
- A VPS sized for your users: 2 GB RAM for a few dozen concurrent users, more as you grow. Root access.
- Check the requirements of the Moodle version you install (PHP, MySQL/MariaDB/PostgreSQL versions).
- A domain with DNS pointing to the VPS.
Install PHP and set required options
Install PHP-FPM with: curl, gd, intl, mbstring, mysql (or pgsql), soap, xml, zip, opcache, sodium, redis. Then set in php.ini (both FPM and CLI):
max_input_vars = 5000
memory_limit = 256M
upload_max_filesize = 100M
post_max_size = 100Mmax_input_vars = 5000 is required; the installer refuses to continue without it.
Create the database
mysql -e "CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'moodle'@'localhost' IDENTIFIED BY 'strong-password'; GRANT ALL ON moodle.* TO 'moodle'@'localhost';"Get Moodle and create moodledata
Clone the stable branch you want with Git (easier upgrades):
git clone -b MOODLE_405_STABLE git://git.moodle.org/moodle.git /var/www/moodleReplace the branch name with the current stable branch. Create the data directory outside the web root:
mkdir /var/moodledata && chown www-data:www-data /var/moodledata && chmod 770 /var/moodledataThe code itself should be owned by root or your deploy user and only readable by the web server.
Configure Nginx
server {
server_name lms.example.com;
root /var/www/moodle;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ =404;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.(?!well-known) { deny all; }
location ~ (/vendor/|/node_modules/|composer\.json|/readme|/README|/upgrade\.txt|/db/install\.xml|/fixtures/|/behat/|phpunit\.xml) { deny all; }
}The PATH_INFO lines enable Moodle's "slash arguments", required for many file URLs. Add SSL with Certbot before installing so wwwroot uses https.
Run the installer
cd /var/www/moodle && sudo -u www-data php admin/cli/install.php --wwwroot=https://lms.example.com --dataroot=/var/moodledata --dbtype=mariadb --dbname=moodle --dbuser=moodle --dbpass=strong-password --fullname="My LMS" --shortname=LMS --adminuser=admin --adminpass='Strong-Pass-1' --adminemail=admin@example.com --agree-license --non-interactiveUse --dbtype=mysqli for MySQL or pgsql for PostgreSQL. The installer writes config.php; afterwards make it read-only (chmod 444 config.php). The web installer at your URL is an alternative.
Set up cron
Moodle needs cron every minute for notifications, grading and scheduled tasks:
* * * * * /usr/bin/php /var/www/moodle/admin/cli/cron.php >/dev/null 2>&1Add it to the www-data crontab (crontab -u www-data -e).
Performance
- Enable OPcache with enough memory.
- Use Redis for sessions and the application cache (Site administration → Plugins → Caching).
- Set up outgoing mail via SMTP in Site administration → Server → Email.
- Check Site administration → Notifications and the Environment page for warnings.
Upgrading
Enable maintenance mode, back up the database, code and moodledata, then pull the new branch and run sudo -u www-data php admin/cli/upgrade.php.
Troubleshooting
- max_input_vars must be at least 5000: set it in the PHP-FPM and CLI php.ini.
- Images and files broken: slash arguments are not working; check the
PATH_INFOlines. - Cron has not run for a while warning: the cron entry is missing or runs as the wrong user.
- Uploads limited to 2 MB: raise PHP limits and
client_max_body_size, then the course/site upload limits.
Moodle FAQ
How many users can a VPS handle?
It depends on concurrent activity: quizzes and assignment deadlines create peaks. Start modest and monitor.
Can I install Moodle on cPanel?
Yes, via Softaculous or manually, but cron every minute and moodledata size make a VPS better for busy sites.
Where are uploaded files stored?
In moodledata, which must be backed up together with the database.
