🎓

moodle

18 notes  •  LMS & Business Apps

Configure Email Settings in Moodle

Moodle sends notifications, forum digests, and password resets via email. You can configure it to use your server's built-in PHP mail or an external SMTP relay.

Prerequisites

  • Admin access to the Moodle dashboard
  • SMTP server credentials (if using an external relay)

Steps

Go to Site administration > Server > Email > Outgoing mail configuration.

  • SMTP hosts: Enter your SMTP server (e.g. smtp.gmail.com:587). Leave blank to use PHP's built-in mail function.
  • SMTP security: Choose TLS or SSL as required by your provider.
  • SMTP username / password: Enter the credentials for authentication.
  • No-reply address: Set the From address for Moodle emails.

Verify

Use the Test outgoing mail configuration button at the bottom of the page to send a test email.

Notes

  • Most SMTP servers use port 587 (STARTTLS) or 465 (SSL).
  • For high-volume Moodle sites, consider a transactional email service (SendGrid, SES, Mailgun) to avoid hitting SMTP rate limits.
  • If emails go to spam, configure SPF and DKIM records for your sending domain.

Configure MySQL/MariaDB for Moodle Unicode Support

Moodle requires MySQL or MariaDB to use the utf8mb4 character set to support four-byte Unicode characters (including emoji). Without this, saving emoji or special characters will fail silently.

Steps

nano /etc/my.cnf

Add the following sections:

[client]
default-character-set = utf8mb4

[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip-character-set-client-handshake

[mysql]
default-character-set = utf8mb4
systemctl restart mysqld

Verify

mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set_server';"

The result should show utf8mb4.

Notes

  • For CWP servers, the config file is /etc/my.cnf.d/server.cnf.
  • For MariaDB on CentOS/RHEL, edit /etc/my.cnf.d/mariadb-server.cnf.
  • After restarting MySQL, run the Moodle admin check at Site administration > Server > Environment to confirm the warning is resolved.

Install and Configure Solr for Moodle on CentOS 7

Moodle's global search can be powered by Apache Solr for better full-text search performance. This guide installs the PHP Solr extension and the Solr server on CentOS 7.

Prerequisites

  • CentOS 7 with PHP and PEAR installed
  • Java 8 or later (required by Solr)

Steps

# Install PEAR
wget http://pear.php.net/go-pear.phar
php go-pear.phar

# Install PHP Solr extension
pear install pecl/solr

# Enable the extension
nano /etc/php.d/solr.ini
# Add line:
extension=solr.so

# Install Java
yum install java-1.8.0-openjdk

# Create Solr user and download Solr
adduser solr
cd /opt
wget http://archive.apache.org/dist/lucene/solr/8.11.2/solr-8.11.2.tgz
tar xzf solr-8.11.2.tgz solr-8.11.2/bin/install_solr_service.sh --strip-components=2
bash ./install_solr_service.sh solr-8.11.2.tgz

# Start and enable Solr
systemctl start solr
systemctl enable solr

# Create a Moodle Solr core
sudo -u solr /opt/solr/bin/solr create -c moodle

Verify

curl http://localhost:8983/solr/admin/cores?action=STATUS

Then configure Moodle: Site administration > Plugins > Search > Manage global search — set the search engine to Solr and enter the connection details.

Notes

  • Solr runs on port 8983 by default — open this in the firewall only for localhost access.
  • Restart PHP-FPM after enabling the solr.so extension.

Administer Moodle via the Command Line

Moodle provides CLI scripts in admin/cli/ for performing administrative tasks from the shell — useful for automation, maintenance, and large-scale operations where the web UI would time out.

Prerequisites

  • SSH access to the web server
  • Run commands as the web server process owner (e.g. www-data) to avoid permission issues

Common CLI Commands

# Install or upgrade Moodle
sudo -u www-data php admin/cli/install.php
sudo -u www-data php admin/cli/upgrade.php

# Reset a user's password
sudo -u www-data php admin/cli/reset_password.php

# Purge all caches
sudo -u www-data php admin/cli/purge_caches.php

# Run scheduled tasks immediately
sudo -u www-data php admin/cli/scheduled_task.php --execute=\\core\\task\\send_new_user_passwords_task

# Sync enrollment database plugin
sudo -u www-data php enrol/db/cli/sync.php

# Enable or disable maintenance mode
sudo -u www-data php admin/cli/maintenance.php --enable
sudo -u www-data php admin/cli/maintenance.php --disable

Verify

Most scripts print a success message on completion. Check the Moodle admin interface to confirm the operation took effect.

Notes

  • Always run CLI scripts as the web server user (www-data or apache) to avoid creating files with wrong ownership.
  • Use php admin/cli/scheduled_task.php --list to see all available scheduled tasks.

Install Moodle on Ubuntu with Apache and Let's Encrypt

This guide walks through a full Moodle installation on Ubuntu with Apache, PHP, MySQL, and a Let's Encrypt SSL certificate.

Prerequisites

  • Ubuntu 16.04 or later with root access
  • A domain name pointed to the server

Steps

# Update and upgrade
apt-get update
apt-get upgrade

# Install Apache
apt-get install apache2

# Install certbot for Let's Encrypt (Debian/Ubuntu)
apt-get install -t jessie-backports python-certbot-apache

# Obtain SSL certificate
certbot --authenticator webroot --installer apache

# Install PHP and required extensions
apt install php php-mbstring php-curl php-xml php-zip php-gd \
  php-intl php-json php-mysql php-soap php-xmlrpc

# Install MySQL
apt-get install mysql-server

# Create Moodle database and user
mysql -u root -p <<EOF
CREATE DATABASE moodledb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'moodleuser'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL ON moodledb.* TO 'moodleuser'@'localhost';
FLUSH PRIVILEGES;
EOF

# Download and install Moodle
cd /var/www/html
git clone https://github.com/moodle/moodle.git
cd moodle
git checkout MOODLE_401_STABLE

# Set permissions
chown -R www-data:www-data /var/www/html/moodle
chmod -R 755 /var/www/html/moodle

# Create moodledata directory
mkdir /var/moodledata
chown -R www-data:www-data /var/moodledata
chmod 770 /var/moodledata

Complete the installation by visiting https://yourdomain.com/moodle in a browser and following the web installer.

Verify

After installation, log in as admin and navigate to Site administration > Server > Environment to confirm all checks pass.

Notes

  • Certificates installed by certbot go to /etc/letsencrypt/live/yourdomain.com/.
  • Enable mod_rewrite in Apache: a2enmod rewrite && systemctl restart apache2.

Nginx Configuration for Moodle

This is a working Nginx server block for hosting Moodle with PHP-FPM and Let's Encrypt SSL.

Prerequisites

  • Nginx and PHP-FPM installed
  • Moodle files in /var/www/html/elearning
  • SSL certificate obtained (e.g. via certbot)

Configuration

server {
    root /var/www/html/elearning;
    index index.php;
    server_name elearning.example.com;

    location / {
        try_files $uri $uri/ =404;
    }

    # Allow Let's Encrypt ACME challenges
    location ~ /.well-known/acme-challenge/ {
        allow all;
        default_type "text/plain";
        root /var/www/html/elearning;
    }

    # PHP-FPM handler
    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info  ^(.+\.php)(/.+)$;
        fastcgi_index            index.php;
        fastcgi_pass             unix:/run/php/php7.2-fpm.sock;
        include                  fastcgi_params;
        fastcgi_param            PATH_INFO $fastcgi_path_info;
        fastcgi_param            SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Apply

sudo nginx -t
sudo systemctl reload nginx

Notes

  • Update the fastcgi_pass socket path to match your PHP-FPM version (e.g. php8.1-fpm.sock).
  • Add SSL directives (listen 443 ssl, certificate paths) for HTTPS.

Configure Nginx with PHP-FPM for Moodle

Nginx interfaces with PHP via PHP-FPM for Moodle hosting. A key requirement is configuring PHP-FPM to only execute .php files, and enabling slash-argument support for Moodle's URLs.

Prerequisites

  • Nginx and PHP-FPM installed
  • PHP-FPM pool configured

PHP-FPM Security Setting

Restrict PHP-FPM to only execute .php files:

# On Debian/Ubuntu, edit:
nano /etc/php/8.1/fpm/pool.d/www.conf

# Add or confirm:
security.limit_extensions = .php

Nginx Location Block

Add this slash-arguments compatible block to your Nginx server block:

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

Apply

sudo systemctl reload php8.1-fpm
sudo nginx -t && sudo systemctl reload nginx

Notes

  • The [^/]\.php(/|$) regex prevents execution of PHP inside uploaded files.
  • Moodle requires slash arguments for plugin pages — the regex above handles these correctly.

Fix: Cannot Downgrade mod_quiz Version Error in Moodle

When upgrading or restoring a Moodle installation, you may encounter: Cannot downgrade mod_quiz from 2014080700 to 2014051201. This happens when the version stored in the database is newer than the plugin files on disk.

Steps

# Edit the quiz plugin version file
nano /path/to/moodle/mod/quiz/version.php

# Change $plugin->version to match the version the upgrade script reports
# Example:
$plugin->version = 2014080700;

Save the file and re-run the Moodle upgrade:

sudo -u www-data php admin/cli/upgrade.php

Verify

The upgrade should complete without the version conflict error. Check Site administration > Plugins > Plugins overview to confirm mod_quiz shows the correct version.

Notes

  • Always take a full database and file backup before manually editing version files.
  • If the error persists, try replacing the mod/quiz directory with the correct version matching your Moodle branch.

Install Moodle on Ubuntu with PHP 8.4 and MySQL

A complete Moodle installation on Ubuntu using Apache, PHP 8.4, MySQL, Composer, and a Let's Encrypt certificate via Certbot.

Prerequisites

  • Ubuntu 22.04 or 24.04 with root access
  • A domain name pointed to the server

Steps

# Update and install base packages
apt-get update && apt-get -y upgrade
apt-get install -y git apache2 snapd screen software-properties-common mysql-server

# Enable Apache modules
a2enmod rewrite expires headers cache cache_disk

# Install Certbot via Snap
snap install core
snap install certbot --classic
ln -s /snap/bin/certbot /usr/bin/certbot

# Install PHP 8.4 and extensions
apt install -y zip htop curl libapache2-mod-php php php-mbstring php-bcmath \
  php-curl php-gmp php-tidy php-excimer php-tokenizer php-xmlrpc php-soap \
  php-zip php-gd php-xml php-intl php-json php-mysql php-imagick php-fpm

# Install Composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# Tune PHP settings
sed -i 's/memory_limit = .*/memory_limit = 1024M/' /etc/php/8.4/fpm/php.ini
sed -i 's/upload_max_filesize = .*/upload_max_filesize = 1024M/' /etc/php/8.4/fpm/php.ini
sed -i 's/post_max_size = .*/post_max_size = 1024M/' /etc/php/8.4/fpm/php.ini
sed -i 's/max_execution_time = .*/max_execution_time = 300/' /etc/php/8.4/fpm/php.ini
sed -i 's/^;.*max_input_vars =.*/max_input_vars = 10000/' /etc/php/8.4/fpm/php.ini

# Enable PHP-FPM and restart services
a2enmod proxy_fcgi setenvif
a2enconf php8.4-fpm
systemctl restart php8.4-fpm apache2

# Create Moodle database
mysql -u root -p <<EOF
CREATE DATABASE moodledb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'moodleuser'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL ON moodledb.* TO 'moodleuser'@'localhost';
FLUSH PRIVILEGES;
EOF

# Clone Moodle
cd /var/www/html
git clone https://github.com/moodle/moodle.git --branch MOODLE_404_STABLE --depth 1

# Set permissions
find /var/www/html/moodle -type f -exec chmod 644 {} \;
find /var/www/html/moodle -type d -exec chmod 755 {} \;

# Create data directory
mkdir /var/moodledata
chown -R www-data:www-data /var/moodledata
chmod 770 /var/moodledata

Verify

Visit https://yourdomain.com/moodle and complete the web installer.

Notes

  • Run certbot --apache -d yourdomain.com to obtain and configure the SSL certificate.
  • Enable Apache to follow symlinks and override: set AllowOverride All in apache2.conf.

Fix: Invalid Login — Login Token Error in Moodle

Starting with Moodle 3.1.15 / 3.3.9 / 3.4.6 / 3.5.3 / 3.6.0, a login token is required for all login form submissions. If a custom theme or login form does not include this token, users will see Invalid login, please try again.

Cause

The security feature requires all login forms to submit a token obtained via \core\session\manager::get_login_token(). Custom themes with their own login templates may be missing this field.

Fix: Update Custom Theme Template

For Boost-based themes, update the login template:

# Moodle 3.4+
theme/yourtheme/templates/core/loginform.mustache

# Moodle 3.3 and earlier
theme/yourtheme/templates/core/login.mustache

Add the token field inside the login form:

<input type="hidden" name="logintoken" value="{{logintoken}}">

Fix: Custom HTML Login Forms

If you use a plain HTML login form, generate the token in PHP:

<?php
$token = \core\session\manager::get_login_token();
?>
<input type="hidden" name="logintoken" value="<?php echo $token; ?>">

Disable the Protection (Not Recommended)

# In config.php
$CFG->disablelogintoken = true;

Verify

After updating the template, purge Moodle caches and test login:

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

Notes

  • Disabling the login token removes a CSRF protection measure — only do this temporarily for debugging.
  • Sites with an alternate login URL (Site administration > Security > Site security settings) must also pass the token through the redirect.

Configure MySQL/MariaDB utf8mb4 for Moodle on CWP

On CentOS Web Panel (CWP) servers, the MariaDB config file differs from the standard path. This guide sets the correct utf8mb4 configuration to resolve Moodle's mysql_full_unicode_support warning.

Steps

nano /etc/my.cnf.d/server.cnf

Add or update these sections:

[client]
default-character-set = utf8mb4

[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip-character-set-client-handshake

[mysql]
default-character-set = utf8mb4
systemctl restart mariadb

Verify

mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set_server';"

Should return utf8mb4. Check Moodle's admin environment page to confirm the warning is gone.

Notes

  • On standard CentOS/RHEL installs, the config file may be /etc/my.cnf or /etc/my.cnf.d/mariadb-server.cnf.
  • Existing tables may need to be converted: run the Moodle CLI task php admin/cli/mysql_utf8mb4_conversion.php after changing the server settings.

Fix Moodle Warning: MySQL Full Unicode Support (utf8mb4)

Moodle shows this warning when MySQL or MariaDB is configured to use the utf8 character set instead of utf8mb4. The utf8 encoding does not support four-byte characters such as emoji, causing data loss on insert.

Cause

The server's character-set-server is set to utf8 instead of utf8mb4, or the existing Moodle tables were created with utf8.

Fix Server Configuration

nano /etc/my.cnf

# Add under [mysqld]:
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix

systemctl restart mysql

Convert Existing Tables

sudo -u www-data php admin/cli/mysql_utf8mb4_conversion.php

Verify

Go to Site administration > Server > Environment. The mysql_full_unicode_support row should show a green OK status.

Notes

  • Back up the database before running the conversion script.
  • The conversion may take a long time on large Moodle installations — run in a screen session.
  • Moodle 3.x and later require utf8mb4 for full emoji and multilingual support.

Fix CSS for Moodle Grader Report Sticky Footer

In some Moodle versions, the Boost theme's sticky footer causes the grader report's Overall average row to be positioned incorrectly. This fix comments out the offending CSS rule.

Fix Option 1: Edit moodle.css

nano theme/boost/style/moodle.css

Find and comment out this rule:

.path-grade-report-grader.hasstickyfooter .gradeparent tr.lastrow {
    /*bottom: calc(max(96px, 0.9375rem * 3) - 1px);*/
}

Fix Option 2: Edit the SCSS Source

nano theme/boost/scss/moodle/grade.scss

Find the hasstickyfooter block and comment out the bottom line:

&.hasstickyfooter {
    .gradeparent {
        tr.lastrow {
            // bottom: calc(#{$stickyfooter-height} - 1px);
        }
    }
}

Apply

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

Notes

  • If you are using a child theme, override the rule in your child theme's CSS rather than editing core Boost files — core changes will be overwritten on upgrade.
  • This issue is tracked in the Moodle tracker; check if your version has an official fix available.

Use Moosh for Moodle Course Backups

Moosh is a command-line tool for Moodle administration. It can trigger course backups, manage users, and perform other tasks directly from the shell — useful for scripting and automation.

Install Moosh

sudo apt-get install software-properties-common
sudo apt-add-repository ppa:zabuch/ppa
sudo apt-get update
sudo apt-get install moosh

Back Up a Single Course

# Run from the Moodle root directory
cd /var/www/html/moodle
sudo -u www-data moosh course-backup 42

Where 42 is the Moodle course ID. Backups are stored in the default backup directory.

Back Up All Courses

sudo -u www-data moosh course-backup -a

Verify

ls /var/moodledata/backup/

The backup .mbz files should be listed.

Notes

  • Always run moosh as the web server user (www-data or apache) to avoid permission issues.
  • Use moosh --help to see all available commands.
  • Schedule automatic backups with a cron job: 0 2 * * * www-data cd /var/www/html/moodle && moosh course-backup -a.

Configure Moodle .htaccess Security Rules

This .htaccess file configures Apache security rules for Moodle, blocking access to sensitive directories and files such as .git, vendor, Composer files, and test files.

Configuration

# Ensure mod_rewrite is enabled
RewriteEngine On

# Block hidden files (.git, .env, etc.)
RewriteRule ^(\.git|\.github|\.env|\.stylelintrc) - [R=404,L]

# Block vendor and node_modules
RewriteRule ^(vendor|node_modules)/ - [R=404,L]

# Block Composer and environment files
RewriteRule ^(composer\.json|composer\.lock|admin/environment\.xml)$ - [R=404,L]

# Block README and license files
RewriteRule ^(README|readme|license)\.(txt|md|xml)$ - [R=404,L]

# Block Behat test files and PHPUnit configs
RewriteRule ^(behat\.yml|\.phpunit\.xml)$ - [R=404,L]

Apply

# Place in the Moodle root directory
cp moodle.htaccess /var/www/html/moodle/.htaccess

# Ensure AllowOverride is enabled in Apache config
# In /etc/apache2/apache2.conf:
# AllowOverride All
sudo systemctl reload apache2

Notes

  • These rules require mod_rewrite to be enabled: a2enmod rewrite.
  • Moodle ships a default .htaccess in the root — this can be used as a starting point.
  • If using Nginx, these rules must be translated to Nginx location blocks instead.

Configure Moodle .htaccess Security Rules

This .htaccess file configures Apache security rules for Moodle, blocking access to sensitive directories and files such as .git, vendor, Composer files, and test files.

Configuration

# Ensure mod_rewrite is enabled
RewriteEngine On

# Block hidden files (.git, .env, etc.)
RewriteRule ^(\.git|\.github|\.env|\.stylelintrc) - [R=404,L]

# Block vendor and node_modules
RewriteRule ^(vendor|node_modules)/ - [R=404,L]

# Block Composer and environment files
RewriteRule ^(composer\.json|composer\.lock|admin/environment\.xml)$ - [R=404,L]

# Block README and license files
RewriteRule ^(README|readme|license)\.(txt|md|xml)$ - [R=404,L]

# Block Behat test files and PHPUnit configs
RewriteRule ^(behat\.yml|\.phpunit\.xml)$ - [R=404,L]

Apply

# Place in the Moodle root directory
cp moodle.htaccess /var/www/html/moodle/.htaccess

# Ensure AllowOverride is enabled in Apache config
# In /etc/apache2/apache2.conf:
# AllowOverride All
sudo systemctl reload apache2

Notes

  • These rules require mod_rewrite to be enabled: a2enmod rewrite.
  • Moodle ships a default .htaccess in the root — this can be used as a starting point.
  • If using Nginx, these rules must be translated to Nginx location blocks instead.

Reset Moodle Admin Password via CLI

If you are locked out of the Moodle admin account, you can reset the password directly from the command line using a built-in CLI script.

Find the Admin User ID

mysql -u moodleuser -p moodledb

-- Find the site admin IDs
SELECT value FROM mdl_config WHERE name = 'siteadmins';

-- Look up the username for that ID
SELECT id, username, email FROM mdl_user WHERE id = <admin_id>;

Reset the Password

# Run from the Moodle root directory
cd /var/www/html/moodle
sudo -u www-data /usr/bin/php admin/cli/reset_password.php

The script will prompt you to enter a username and new password.

Verify

Log in to the Moodle admin panel at https://yourdomain.com/moodle/login/index.php with the new password.

Notes

  • If you have multiple PHP versions, specify the correct binary: /usr/bin/php8.1 admin/cli/reset_password.php.
  • Moodle enforces password complexity rules — the new password must meet the site's policy.

Install Moodle 5 on Ubuntu with MySQL 8

Moodle 5 requires MySQL 8.0+ or MariaDB 10.6+. This guide covers installing MySQL 8 from the official APT repository and configuring it for Moodle 5.

Prerequisites

  • Ubuntu 22.04 or 24.04
  • Root or sudo access
  • PHP 8.2 or later installed

Install MySQL 8

# Download and install MySQL APT config package
wget https://dev.mysql.com/get/mysql-apt-config_0.8.34-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.34-1_all.deb

# Choose MySQL 8.0 in the interactive prompt, then install
sudo apt-get update
sudo apt-get install mysql-server

# Secure the installation
sudo mysql_secure_installation

Create Moodle Database

mysql -u root -p <<EOF
CREATE DATABASE moodledb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moodleuser'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL ON moodledb.* TO 'moodleuser'@'localhost';
FLUSH PRIVILEGES;
EOF

Download Moodle 5

cd /var/www/html
git clone https://github.com/moodle/moodle.git --branch MOODLE_500_STABLE --depth 1
chown -R www-data:www-data moodle

Verify

Visit https://yourdomain.com/moodle and complete the installer. Check Site administration > Server > Environment to confirm all requirements are met.

Notes

  • MySQL 8.0 changed the default authentication method — if you encounter auth errors, use: ALTER USER 'moodleuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
  • Moodle 5 requires PHP 8.2+. Check with php -v before starting.