Moodle LMS Administration

Moodle Hardening · Production Security Manual

Harden your Moodle LMS platform against cyber attacks. Set strict directory controls on dataroot volumes, deploy advanced HTTP defense headers, enforce Fail2ban login restrictions, and run automated platform security audits.

Pipeline N: Multi-layered Security Boundaries

Edge
Cloudflare WAF
DDoS & Bot Filter
Proxy
Nginx TLS 1.3
HSTS & Custom Headers
Runtime
PHP Hardening
disable_functions
Storage
Isolated Dataroot
Permissions 02770

🛡️ Security Hardening Roadmap

1. Secure the Moodle Dataroot Volume

Why this matters
The dataroot directory stores student files, submissions, and session data. If placed inside Apache's document root, attackers can directly access or run uploaded scripts. Moving this outside of web paths is crucial.
bash · Secure Dataroot Directory
# Move dataroot outside Apache document root
sudo mv /var/www/moodl_ulo2026Demo/moodledata /var/moodledata

# Ensure permissions restrict access to www-data exclusively
sudo chown -R www-data:www-data /var/moodledata
sudo chmod -R 770 /var/moodledata

# Create a blocking .htaccess as a second line of defense
echo "Order deny,allow
Deny from all" | sudo tee /var/moodledata/.htaccess
Potential Issue
Ensure `$CFG->dataroot` in `config.php` matches the new directory path. Moodle will immediately block logins and course uploads if it has mismatched path strings.

2. Enforce Strict Apache Security Headers

How to do it
Protect student profiles and course components from Clickjacking and MIME-sniffing exploits by appending advanced security headers to HTTPS requests inside the Apache virtual host container.
apache · Header Settings
sudo nano /etc/apache2/sites-available/000-default-le-ssl.conf

# Inside the <VirtualHost *:443> block, paste the following rules:
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Content-Security-Policy "upgrade-insecure-requests"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

# Restart Apache to apply the protection headers
sudo systemctl restart apache2

3. Deploy Fail2ban Brute-Force Protection

Why this matters
Moodle's login index path (/login/index.php) is a constant target for brute-force dictionaries. Fail2ban scans access logs and automatically drops requests from active attack IPs at the firewall level.
bash · Configure Fail2ban Jails
# Install Fail2ban package
sudo apt install fail2ban -y

# Create Moodle login parser filter
sudo nano /etc/fail2ban/filter.d/moodle-login.conf
# Add rules:
# [Definition]
# failregex = ^<HOST> - - .*POST /login/index.php.* HTTP/.* 200

# Create the jail parameters config file
sudo nano /etc/fail2ban/jail.d/moodle.local
# Add:
# [moodle-login]
# enabled  = true
# port     = http,https
# filter   = moodle-login
# logpath  = /var/log/apache2/access.log
# maxretry = 5
# bantime  = 3600

sudo systemctl restart fail2ban
Potential Issue
If your Moodle installation is behind a proxy (like Cloudflare or AWS ALB), Apache access logs might display proxy IPs. Ensure you activate mod_remoteip to parse the actual client IP headers correctly.

4. Restrict Codebase Permissions for Production

How to do it
PHP files should be read-only in production. If an attacker uploads a malicious shell via an exploit, they cannot write it to the web directory if the codebase is owned by a deployment user instead of Apache's www-data.
bash · Restrictive Codebase Permissions
# Transfer codebase ownership from www-data to root/deploy user
sudo chown -R root:root /var/www/moodl_ulo2026Demo

# Let www-data only read files
sudo find /var/www/moodl_ulo2026Demo -type d -exec chmod 755 {} \;
sudo find /var/www/moodl_ulo2026Demo -type f -exec chmod 644 {} \;

# Leave write permissions only on caching directories (when not using Redis)
# sudo chown -R www-data:www-data /var/www/moodl_ulo2026Demo/cache

5. Run Automated Platform Security Audits

Why this matters
Weak configuration flags (like allowing open guest logins or displaying PHP warnings) create system exploits. Run Moodle's built-in CLI diagnostic audits to verify your security posture.
bash · CLI Security Auditor
# Run Moodle Security Diagnostic CLI Check
sudo -u www-data php /var/www/moodl_ulo2026Demo/admin/cli/security_checks.php

PHP Hardening

/etc/php/8.1/apache2/php.ini
expose_php = Off
display_errors = Off
log_errors = On
allow_url_fopen = Off
disable_functions = exec,system,shell_exec,passthru

HSTS (Strict-Transport)

Enforce HTTPS globally: Forces browsers to interact strictly over SSL channels.

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Security Actions

  • Check Fail2ban status:
    fail2ban-client status moodle-login
  • Find writable PHP files:
    find /var/www/moodl_ulo2026Demo -name "*.php" -perm /o+w
  • Generate fresh SSL key:
    sudo certbot --apache -d classroom.demodemo.com