Moodle es la plataforma de aprendizaje (LMS) de código abierto más utilizada en centros educativos y empresas: cursos, tareas, cuestionarios, calificaciones y foros en una aplicación PHP. En este tutorial instalarás Moodle 5.2 en Ubuntu 24.04 con Nginx, PHP-FPM 8.3 y MariaDB, lo descargarás con Git para poder actualizarlo fácilmente, lo publicarás con HTTPS y dejarás configurados el cron y las copias de seguridad.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 vCPU, 4 GB de RAM y 30 GB de disco. El espacio que necesites crecerá con los archivos que suban profesores y alumnos.
- Un usuario no root con privilegios
sudo. - Un dominio o subdominio (en esta guía,
moodle.example.com) con un registro DNS A que apunte a la IP del servidor. Sustituyemoodle.example.compor tu dominio en todos los pasos. - Los puertos 80 y 443 abiertos.
Moodle 5.2 requiere PHP 8.3 y MariaDB 10.11 o posterior (o MySQL 8.4, o PostgreSQL 16). Ubuntu 24.04 incluye exactamente PHP 8.3 y MariaDB 10.11, así que todo sale de los repositorios oficiales de la distribución.
Paso 1: Instalar Nginx, PHP y MariaDB
Instala el servidor web, PHP-FPM con las extensiones que Moodle exige, MariaDB y Git:
sudo apt update
sudo apt install -y nginx mariadb-server git php8.3-fpm php8.3-mysql php8.3-xml php8.3-mbstring php8.3-curl php8.3-zip php8.3-gd php8.3-intl php8.3-soap
Las extensiones sodium, openssl, iconv, ctype, fileinfo y opcache ya vienen incluidas en los paquetes base de PHP en Ubuntu. Comprueba que las principales están cargadas:
php -m | grep -E '^(curl|gd|intl|mbstring|mysqli|sodium|soap|xml|zip)$'
curl
gd
intl
mbstring
mysqli
soap
sodium
xml
zip
Si usas UFW, abre HTTP y HTTPS:
sudo ufw allow 'Nginx Full'
Paso 2: Ajustar PHP para Moodle
Moodle exige que max_input_vars sea al menos 5000, y los formularios de subida necesitan límites mayores que los predeterminados. Edita el php.ini de PHP-FPM:
sudo nano /etc/php/8.3/fpm/php.ini
Busca y ajusta estas directivas (quita el ; inicial de max_input_vars):
max_input_vars = 5000
memory_limit = 256M
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300
Los scripts de línea de comandos de Moodle (instalación, cron, actualizaciones) usan el php.ini de la CLI, que también debe cumplir el requisito de max_input_vars:
sudo nano /etc/php/8.3/cli/php.ini
max_input_vars = 5000
Reinicia PHP-FPM y comprueba el valor:
sudo systemctl restart php8.3-fpm
php -r 'echo ini_get("max_input_vars"), PHP_EOL;'
5000
Paso 3: Crear la base de datos
Ejecuta el script de seguridad de MariaDB para eliminar usuarios anónimos y la base de datos de pruebas. En Ubuntu, root se autentica por socket y puedes mantenerlo así:
sudo mariadb-secure-installation
Abre la consola de MariaDB:
sudo mariadb
Crea la base de datos con el juego de caracteres utf8mb4, que Moodle necesita para emojis y alfabetos completos, y un usuario exclusivo. Sustituye your_strong_password por una contraseña robusta:
CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moodle'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON moodle.* TO 'moodle'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Comprueba el acceso:
mariadb -u moodle -p -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| moodle |
+--------------------+
Paso 4: Descargar Moodle con Git
Clonar la rama estable desde Git es el método que recomienda Moodle para servidores propios, porque las actualizaciones menores se reducen a un git pull. Clona solo la rama MOODLE_502_STABLE:
sudo git clone --branch MOODLE_502_STABLE --depth 1 https://github.com/moodle/moodle.git /var/www/moodle
Desde Moodle 5.1, el código que debe servirse por web está en el subdirectorio public; el resto (incluido config.php y las herramientas de línea de comandos en admin/cli) queda fuera de la raíz web. Compruébalo:
ls /var/www/moodle
CONTRIBUTING.md COPYING.txt Gruntfile.js INSTALL.txt README.md TRADEMARK.txt UPGRADING.md admin composer.json composer.lock config-dist.php index.php lib npm-shrinkwrap.json package.json phpcs.xml.dist phpunit.xml.dist public scripts tsconfig.json
Crea el directorio de datos (moodledata), donde Moodle guarda los archivos subidos, la caché y las sesiones. Debe estar fuera de la raíz web y ser escribible por www-data:
sudo mkdir -p /var/moodledata
sudo chown -R www-data:www-data /var/moodledata
sudo chmod 750 /var/moodledata
El código pertenece a root, así que PHP no puede modificarlo:
sudo chown -R root:root /var/www/moodle
Paso 5: Configurar Nginx
Crea el bloque de servidor:
sudo nano /etc/nginx/sites-available/moodle
server {
listen 80;
listen [::]:80;
server_name moodle.example.com;
root /var/www/moodle/public;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /r.php;
}
# Moodle usa PATH_INFO en URLs como /pluginfile.php/...
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 ~ /\. {
deny all;
}
}
La regla try_files ... /r.php envía al enrutador de Moodle las rutas que no son archivos reales, y el bloque de PHP pasa PATH_INFO, que Moodle usa para servir archivos. Activa el sitio, desactiva el de por defecto y recarga:
sudo ln -s /etc/nginx/sites-available/moodle /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Paso 6: Activar HTTPS con Let's Encrypt
Obtén el certificado antes de instalar Moodle, porque la dirección del sitio (wwwroot) se fija durante la instalación y conviene que sea https:// desde el principio:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d moodle.example.com
Comprueba la renovación automática:
sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/moodle.example.com/fullchain.pem (success)
Paso 7: Instalar Moodle desde la línea de comandos
El instalador de línea de comandos crea config.php y todas las tablas sin los tiempos de espera del navegador. Necesita escribir config.php en /var/www/moodle, así que da permiso de escritura temporal a www-data solo sobre ese directorio (sin -R):
sudo chown www-data /var/www/moodle
Ejecuta el instalador como www-data. Sustituye las contraseñas, el nombre del sitio y el correo por los tuyos; your_admin_password será la contraseña del usuario admin de Moodle:
sudo -u www-data php /var/www/moodle/admin/cli/install.php \
--lang=es \
--wwwroot=https://moodle.example.com \
--dataroot=/var/moodledata \
--dbtype=mariadb \
--dbhost=localhost \
--dbname=moodle \
--dbuser=moodle \
--dbpass='your_strong_password' \
--fullname='Campus virtual' \
--shortname='Campus' \
--adminuser=admin \
--adminpass='your_admin_password' \
[email protected] \
--agree-license \
--non-interactive
La instalación tarda varios minutos: descarga el paquete de idioma español, crea las tablas e instala los plugins. Termina con un mensaje de instalación completada; si falla, el propio instalador indica qué requisito no se cumple.
Devuelve el directorio a root y protege config.php, que contiene la contraseña de la base de datos:
sudo chown root:root /var/www/moodle
sudo chown root:www-data /var/www/moodle/config.php
sudo chmod 640 /var/www/moodle/config.php
Como Nginx ya reenvía las rutas al enrutador, indícaselo a Moodle para que genere URL sin r.php. Edita config.php:
sudo nano /var/www/moodle/config.php
Añade esta línea antes de require_once(__DIR__ . '/lib/setup.php');:
$CFG->routerconfigured = true;
Abre https://moodle.example.com e inicia sesión con admin y la contraseña que elegiste. Ve a Administración del sitio > Servidor > Entorno para comprobar que todos los requisitos aparecen en verde.
Paso 8: Configurar el cron de Moodle
Moodle depende de su cron para enviar notificaciones y correos, procesar tareas en segundo plano, limpiar la caché y ejecutar las copias automáticas de cursos. Debe ejecutarse cada minuto como www-data:
echo '* * * * * www-data /usr/bin/php /var/www/moodle/admin/cli/cron.php > /dev/null 2>&1' | sudo tee /etc/cron.d/moodle
Ejecútalo una vez a mano para verificar que funciona:
sudo -u www-data php /var/www/moodle/admin/cli/cron.php
Server Time: Fri, 25 Sep 2026 11:15:01 +0000
Execute scheduled task: ...
Cron run completed correctly
Al cabo de unos minutos, la página Administración del sitio > Notificaciones deja de mostrar el aviso de que el cron no se ha ejecutado.
Paso 9: Configurar el correo saliente
Sin un servidor SMTP, Moodle intenta enviar correo con la función mail() de PHP, que en la mayoría de servidores no funciona. Ve a Administración del sitio > Servidor > Correo electrónico > Configuración de correo saliente y rellena:
- Servidores SMTP:
smtp.your_provider.com:587. - Seguridad SMTP: TLS.
- Nombre de usuario y contraseña SMTP.
- Dirección de no respuesta: por ejemplo,
[email protected], en un dominio con SPF y DKIM configurados.
En la misma sección está la opción Probar la configuración del correo saliente para enviar un mensaje de prueba.
Paso 10: Programar copias de seguridad
Una copia completa de Moodle requiere la base de datos, el directorio moodledata y config.php. Crea un script:
sudo nano /usr/local/sbin/moodle-backup
#!/usr/bin/env bash
set -euo pipefail
backup_dir="/var/backups/moodle"
stamp="$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
# Modo mantenimiento para que los datos sean coherentes
php /var/www/moodle/admin/cli/maintenance.php --enable
# Reactivar el sitio aunque falle un paso
trap 'php /var/www/moodle/admin/cli/maintenance.php --disable' EXIT
mariadb-dump --single-transaction --default-character-set=utf8mb4 moodle \
| gzip > "$backup_dir/moodle-db-$stamp.sql.gz"
# La caché y los archivos temporales se regeneran solos
tar -czf "$backup_dir/moodle-data-$stamp.tar.gz" \
--exclude='cache' --exclude='localcache' --exclude='temp' --exclude='sessions' \
-C /var moodledata
cp /var/www/moodle/config.php "$backup_dir/config-$stamp.php"
find "$backup_dir" -type f -name 'moodle-*' -mtime +7 -delete
find "$backup_dir" -type f -name 'config-*' -mtime +7 -delete
El script se ejecuta como root, que accede a MariaDB por socket sin contraseña. Hazlo ejecutable, pruébalo y prográmalo para las 3:00, cuando menos uso suele haber:
sudo chmod 750 /usr/local/sbin/moodle-backup
sudo /usr/local/sbin/moodle-backup
sudo ls -lh /var/backups/moodle
echo '0 3 * * * root /usr/local/sbin/moodle-backup' | sudo tee /etc/cron.d/moodle-backup
-rw-r----- 1 root root 5.0K Sep 25 11:30 config-20260925-113000.php
-rw-r--r-- 1 root root 22M Sep 25 11:30 moodle-data-20260925-113000.tar.gz
-rw-r--r-- 1 root root 6.4M Sep 25 11:30 moodle-db-20260925-113000.sql.gz
Copia /var/backups/moodle a otro servidor con regularidad. Las copias de cursos individuales se gestionan aparte, desde Administración del sitio > Cursos > Copia de seguridad.
Paso 11: Actualizar Moodle
Las versiones menores de la rama 5.2 se publican en la misma rama de Git. Para actualizar, haz una copia de seguridad, descarga los cambios y ejecuta el actualizador:
sudo /usr/local/sbin/moodle-backup
cd /var/www/moodle
sudo git pull
sudo -u www-data php admin/cli/upgrade.php --non-interactive
Si el actualizador no tiene nada que hacer, lo indicará y terminará sin cambios. Para una versión mayor (por ejemplo, 5.3), cambia a la rama nueva con git fetch y git checkout siguiendo las notas de actualización oficiales, y revisa antes que tus plugins sean compatibles.
Solución de problemas
El instalador o el entorno indican que falta una extensión de PHP. Instala el paquete php8.3-<extensión> correspondiente y reinicia php8.3-fpm.
Las imágenes o los archivos de los cursos no cargan. Suele faltar PATH_INFO. Revisa que el bloque location ~ [^/]\.php(/|$) tenga fastcgi_split_path_info y fastcgi_param PATH_INFO, y que Certbot lo haya conservado en el bloque HTTPS.
Error al escribir en moodledata. Comprueba que /var/moodledata pertenece a www-data y que el cron se ejecuta como www-data, no como root; si el cron se ejecutó como root, corrige la propiedad con sudo chown -R www-data:www-data /var/moodledata.
Conclusión
Tienes Moodle 5.2 funcionando en Ubuntu 24.04 con Nginx, PHP-FPM y MariaDB, servido por HTTPS, con el cron cada minuto, correo saliente y copias de seguridad diarias. Como siguientes pasos, crea las categorías y los cursos, configura el registro de usuarios o la autenticación con tu proveedor de identidad en Administración del sitio > Plugins > Autenticación, y valora añadir Redis como caché de sesiones cuando crezca el número de alumnos concurrentes.
