Automatizando la instalación de Moodle con Ansible: Una solución mágica para despliegues rápidos

Publicado el

·

Actualizado el

·

Por

Automatizar instalación Moodle con Ansible es una forma práctica de convertir una tarea técnica repetitiva en un proceso reproducible, documentado y menos propenso a errores. Cuando una organización necesita desplegar Moodle en varios servidores, repetir la instalación manual deja de ser eficiente y empieza a convertirse en un riesgo operativo.

Por qué automatizar instalación Moodle con Ansible

Automatizar instalación Moodle con Ansible no consiste únicamente en ahorrar tiempo. También permite reducir diferencias entre servidores, documentar decisiones técnicas y repetir el despliegue con más garantías cuando trabajas con desarrollo, preproducción y producción.

La automatización no es solo una herramienta; es una forma de trabajar. En primer lugar, permite declarar cómo debe quedar el servidor, qué paquetes deben instalarse, qué servicios deben estar activos, qué permisos deben aplicarse y qué configuración necesita Moodle para funcionar correctamente.

En este artículo se muestra cómo preparar un despliegue de Moodle con Ansible sobre Ubuntu, utilizando Apache2, PHP-FPM, MariaDB, Redis y certificados SSL con Let’s Encrypt. La idea es partir de una guía práctica, pero con criterio de producción: seguridad, variables sensibles, estructura del playbook y verificación final.

Si deseas explorar otra alternativa para la instalación de Moodle, puedes consultar mi guía paso a paso sobre cómo instalar Moodle 4.5 con Docker, Apache, PHP-FPM y MySQL.

Además, conviene revisar la documentación oficial de Ansible para entender inventarios, playbooks, módulos e idempotencia antes de llevar esta automatización a producción.

¿Te has encontrado alguna vez instalando Moodle manualmente en múltiples servidores? ¿Y si pudieras automatizar todo el proceso con un playbook versionado, revisable y reutilizable?

Resumen rápido

En esta guía vas a ver cómo automatizar instalación Moodle con Ansible sobre Ubuntu, Apache2, PHP-FPM, MariaDB, Redis y certificados SSL con Let’s Encrypt.

La idea no es solo instalar más rápido, sino conseguir instalaciones repetibles, documentadas y menos propensas a errores cuando trabajas con varios servidores o entornos de cliente.

Arquitectura automatizada para instalar Moodle con Ansible, PHP-FPM, MariaDB y Redis
Automatización de una instalación Moodle mediante Ansible, con servidor web, base de datos, caché y seguridad SSL.

Paso 1: Preparativos para automatizar instalación Moodle con Ansible

Antes de automatizar la instalación de Moodle, conviene preparar correctamente el entorno de control, el acceso SSH y el inventario de servidores. Estos pasos parecen básicos, pero son los que determinan si el despliegue será fluido o si el playbook fallará por problemas de conectividad, permisos o variables mal definidas.

Antes de empezar

Ejecuta estas pruebas primero en un entorno de desarrollo o preproducción. Un playbook de Ansible puede crear usuarios, modificar permisos, reiniciar servicios y cambiar configuración de Apache, PHP o MariaDB.

La automatización reduce intervención manual. Por eso conviene versionar el playbook, revisar variables sensibles y validar cada cambio antes de aplicarlo en producción.

1.1. Instalación de Ansible

Ansible debe estar instalado en tu máquina local o en un servidor de control. Desde ahí se ejecutarán los playbooks contra los servidores donde quieras instalar Moodle.

Bash
# Ubuntu / Debian
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible python3-pymysql

# CentOS / RHEL / Fedora
sudo yum install -y ansible

# macOS con Homebrew
brew install ansible

1.2. Acceso SSH a los servidores objetivo

Ansible utiliza SSH para comunicarse con los servidores remotos. Por eso el primer requisito operativo es poder acceder al servidor sin depender de una sesión manual interactiva.

Genera una clave SSH para el usuario desde el que ejecutarás los despliegues:

Bash
ssh-keygen -t ed25519 -C "moodle-ansible-admin"

Después, copia la clave pública al servidor objetivo. Puedes hacerlo con ssh-copy-id o pegándola manualmente en ~/.ssh/authorized_keys.

Bash
ssh-copy-id usuario@servidor

# Alternativa manual: copiar la clave pública
cat ~/.ssh/id_ed25519.pub

# Pegar el contenido en el servidor remoto
vim ~/.ssh/authorized_keys

Comprueba que puedes conectarte correctamente:

Bash
ssh usuario@servidor

Si puedes entrar sin introducir la contraseña del usuario remoto, o únicamente usando la contraseña de tu clave privada, estás listo para ejecutar Ansible.

1.3. Inventario de Ansible

El inventario de Ansible define qué servidores se gestionan, cómo se conectan y qué variables de conexión se aplican a cada grupo. En instalaciones Moodle es habitual separar entornos de preproducción, producción o nodos web.

INI
[moodle_servers]
moodle-prod ansible_host=192.168.1.10
moodle-pre  ansible_host=192.168.1.11

[moodle_servers:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_python_interpreter=/usr/bin/python3
  • Grupos: los servidores se agrupan bajo [moodle_servers]. Puedes crear otros grupos como [dbservers] o [staging].
  • Variables: las variables de conexión se declaran bajo [moodle_servers:vars], incluyendo usuario SSH, clave privada e intérprete de Python.
Inventario de servidores agrupados por entorno y variables de conexión
Un inventario bien organizado permite separar servidores, entornos y variables de conexión antes de ejecutar el playbook

Paso 2: Arquitectura del sistema a desplegar

El despliegue propuesto instala Moodle sobre una arquitectura clásica, robusta y comprensible: Apache2 como servidor web, PHP-FPM como procesador de PHP, MariaDB como base de datos, Redis como caché y Let’s Encrypt para HTTPS. Además, este enfoque ayuda a automatizar instalación Moodle con Ansible sin perder visibilidad sobre cada servicio implicado.

Esta combinación es adecuada para muchos escenarios: servidores dedicados, VPS, entornos corporativos y plataformas Moodle de tamaño medio. Además, deja abierta la puerta a evoluciones posteriores como balanceo, separación de base de datos, almacenamiento compartido o caché distribuida.

Diagrama de arquitectura LMS con servidor web, base de datos y caché
Arquitectura base para automatizar una instalación Moodle con Ansible.

Lectura arquitectónica

El valor de este despliegue no está solo en instalar Moodle, sino en declarar de forma explícita todos los componentes que necesita la plataforma.

Cuando esa arquitectura queda expresada en un playbook, el conocimiento se convierte en un activo reutilizable del proyecto.

Paso 3: Playbook para automatizar instalación Moodle con Ansible

El playbook es el corazón de Ansible. Es el fichero YAML que describe el estado final que queremos conseguir en el servidor: paquetes instalados, servicios activos, directorios creados, permisos aplicados, repositorio de Moodle clonado, base de datos preparada, Apache configurado y certificado SSL emitido.

Flujo de tareas de un playbook YAML para configurar servicios de servidor
El playbook coordina tareas de sistema, servicios, base de datos, configuración web y seguridad

Cómo leer el playbook

No conviene verlo como un simple script largo, sino como una descripción declarativa del estado deseado del servidor.

Cada tarea acerca la máquina al estado final: paquetes instalados, servicios activos, directorios creados, repositorio clonado, permisos aplicados, base de datos preparada y VirtualHost listo.

Vamos a crear un fichero llamado playbook.yml con el siguiente contenido. Esta versión permite automatizar instalación Moodle con Ansible evitando publicar contraseñas en claro y utilizando variables cifradas mediante ansible-vault.

YAML
---
- name: Instalar Moodle con Apache, PHP-FPM, MariaDB, Redis y SSL
  hosts: moodle_servers
  become: true

  vars_files:
    - group_vars/moodle/vault.yml

  vars:
    moodle_git_repo: "https://github.com/moodle/moodle.git"
    moodle_branch: "MOODLE_405_STABLE"
    moodle_dir: "/var/www/moodle"
    moodle_data_dir: "/var/www/moodledata"
    moodle_url: "https://moodle.miempresa.com"
    moodle_dns: "moodle.miempresa.com"
    db_name: "moodle"
    db_user: "moodleuser"
    db_host: "localhost"
    php_version: "8.3"

  tasks:
    - name: Actualizar caché de paquetes
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Actualizar paquetes instalados
      ansible.builtin.apt:
        upgrade: dist

    - name: Agregar repositorio de Ondrej Sury para PHP
      ansible.builtin.apt_repository:
        repo: "ppa:ondrej/php"
        state: present

    - name: Instalar dependencias del servidor Moodle
      ansible.builtin.apt:
        name:
          - apache2
          - php{{ php_version }}-fpm
          - php{{ php_version }}-cli
          - php{{ php_version }}-mysql
          - php{{ php_version }}-xml
          - php{{ php_version }}-mbstring
          - php{{ php_version }}-curl
          - php{{ php_version }}-zip
          - php{{ php_version }}-gd
          - php{{ php_version }}-intl
          - php{{ php_version }}-soap
          - php{{ php_version }}-bcmath
          - php{{ php_version }}-redis
          - mariadb-server
          - mariadb-client
          - redis
          - git
          - unzip
          - certbot
          - python3-certbot-apache
          - python3-pymysql
        state: present

    - name: Asegurar que PHP-FPM está iniciado y habilitado
      ansible.builtin.systemd:
        name: php{{ php_version }}-fpm
        state: started
        enabled: true

    - name: Crear directorio de datos de Moodle
      ansible.builtin.file:
        path: "{{ moodle_data_dir }}"
        state: directory
        owner: www-data
        group: www-data
        mode: "0770"

    - name: Clonar Moodle desde Git
      ansible.builtin.git:
        repo: "{{ moodle_git_repo }}"
        dest: "{{ moodle_dir }}"
        version: "{{ moodle_branch }}"
        force: true
      notify: Reiniciar PHP-FPM

    - name: Configurar el directorio de Moodle como seguro para Git
      ansible.builtin.command: git config --global --add safe.directory {{ moodle_dir }}
      changed_when: false

    - name: Ajustar permisos del código de Moodle
      ansible.builtin.file:
        path: "{{ moodle_dir }}"
        owner: www-data
        group: www-data
        recurse: true

    - name: Crear base de datos de Moodle
      community.mysql.mysql_db:
        name: "{{ db_name }}"
        state: present
        login_user: root
        login_password: "{{ vault_db_root_password }}"

    - name: Crear usuario de base de datos para Moodle
      community.mysql.mysql_user:
        name: "{{ db_user }}"
        password: "{{ vault_db_password }}"
        priv: "{{ db_name }}.*:ALL"
        host: "localhost"
        state: present
        login_user: root
        login_password: "{{ vault_db_root_password }}"

    - name: Configurar VirtualHost de Apache para Moodle con PHP-FPM
      ansible.builtin.template:
        src: templates/moodle-apache.conf.j2
        dest: /etc/apache2/sites-available/moodle.conf
        owner: root
        group: root
        mode: "0644"
      notify: Reiniciar Apache

    - name: Habilitar módulos necesarios en Apache
      ansible.builtin.shell: |
        a2enmod ssl
        a2enmod rewrite
        a2enmod proxy_fcgi
        a2enmod setenvif
      args:
        executable: /bin/bash
      notify: Reiniciar Apache

    - name: Habilitar VirtualHost de Moodle
      ansible.builtin.shell: |
        a2ensite moodle.conf
        a2dissite 000-default.conf
      args:
        executable: /bin/bash
      notify: Reiniciar Apache

    - name: Generar config.php de Moodle
      ansible.builtin.template:
        src: templates/config.php.j2
        dest: "{{ moodle_dir }}/config.php"
        owner: www-data
        group: www-data
        mode: "0640"
      notify: Reiniciar PHP-FPM

    - name: Ajustar php.ini para Moodle
      ansible.builtin.lineinfile:
        path: "/etc/php/{{ php_version }}/fpm/php.ini"
        regexp: "^{{ item.key }} ="
        line: "{{ item.key }} = {{ item.value }}"
      loop:
        - { key: "max_input_vars", value: "5000" }
        - { key: "upload_max_filesize", value: "128M" }
        - { key: "post_max_size", value: "128M" }
        - { key: "memory_limit", value: "512M" }
      notify: Reiniciar PHP-FPM

    - name: Obtener certificado SSL con Let's Encrypt
      ansible.builtin.command: >
        certbot --apache -d {{ moodle_dns }}
        --non-interactive --agree-tos
        -m {{ vault_certbot_email }}
      args:
        creates: "/etc/letsencrypt/live/{{ moodle_dns }}/fullchain.pem"
      notify: Reiniciar Apache

    - name: Reiniciar servicios auxiliares
      ansible.builtin.systemd:
        name: "{{ item }}"
        state: restarted
        enabled: true
      loop:
        - mariadb
        - redis

  handlers:
    - name: Reiniciar Apache
      ansible.builtin.service:
        name: apache2
        state: restarted

    - name: Reiniciar PHP-FPM
      ansible.builtin.service:
        name: php{{ php_version }}-fpm
        state: restarted

Explicación del playbook

La primera parte define el nombre del playbook, el grupo de servidores sobre el que se ejecutará y el uso de privilegios elevados mediante become: true. También carga un fichero externo de variables cifradas, donde guardaremos contraseñas y correos sensibles.

Después se declaran variables reutilizables: rama de Moodle, rutas de instalación, dominio, datos de base de datos y versión de PHP. Separar estos valores del cuerpo de las tareas hace que el playbook sea más fácil de mantener.

  • Actualización del sistema: refresca caché de paquetes y actualiza paquetes instalados.
  • Instalación de dependencias: instala Apache2, PHP-FPM, extensiones PHP, MariaDB, Redis, Git, Certbot y PyMySQL.
  • Directorios y permisos: crea moodledata y ajusta propietarios para www-data.
  • Repositorio Moodle: clona Moodle desde Git utilizando la rama estable definida.
  • Base de datos: crea base de datos y usuario específico para Moodle.
  • Servidor web: genera el VirtualHost de Apache desde una plantilla.
  • Configuración final: crea config.php, ajusta php.ini y solicita el certificado SSL.

Ojo con la idempotencia

Ansible funciona mejor cuando las tareas pueden ejecutarse varias veces sin romper el estado del sistema. Siempre que sea posible, utiliza módulos declarativos en lugar de comandos shell.

En algunos casos se usa command o shell, pero conviene añadir condiciones como creates, changed_when o validaciones explícitas para evitar cambios innecesarios.

Paso 4: Seguridad al automatizar instalación Moodle con Ansible

Punto crítico de seguridad

Evita publicar contraseñas reales dentro del playbook. En un proyecto real las credenciales deben gestionarse con variables cifradas, variables de entorno, un gestor de secretos o ansible-vault.

Esto afecta especialmente a contraseñas de base de datos, claves privadas SSH, tokens de API y cualquier dato que permita acceder al servidor o a Moodle.

Para crear un fichero de variables cifradas, utiliza ansible-vault:

Bash
mkdir -p group_vars/moodle
ansible-vault create group_vars/moodle/vault.yml

Dentro del fichero cifrado puedes guardar las variables sensibles que usará el playbook:

YAML
vault_db_password: "CAMBIAR_PASSWORD_MOODLE"
vault_db_root_password: "CAMBIAR_PASSWORD_ROOT_MARIADB"
vault_certbot_email: "admin@miempresa.com"
Protección de credenciales mediante almacén de secretos cifrado
Las variables sensibles deben cifrarse y quedar fuera del playbook principal

Cuando ejecutes el playbook, Ansible te pedirá la contraseña del vault con --ask-vault-pass. También puedes integrar un fichero de password o un gestor de secretos si trabajas en un pipeline CI/CD.

Paso 5: Plantillas de configuración de Moodle

Además del playbook principal, conviene separar los ficheros de configuración en plantillas Jinja2. Así podemos generar un VirtualHost de Apache y un config.php de Moodle a partir de variables.

5.1. Plantilla del VirtualHost de Apache

Crea el fichero templates/moodle-apache.conf.j2:

Apache
<VirtualHost *:80>
    ServerName {{ moodle_dns }}
    DocumentRoot {{ moodle_dir }}

    <Directory {{ moodle_dir }}>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php{{ php_version }}-fpm.sock|fcgi://localhost"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/moodle_error.log
    CustomLog ${APACHE_LOG_DIR}/moodle_access.log combined
</VirtualHost>

5.2. Plantilla config.php.j2 de Moodle

Crea el fichero templates/config.php.j2. Esta plantilla genera el fichero de configuración principal de Moodle y utiliza las variables definidas en el playbook y en el vault.

PHP
<?php
unset($CFG);
global $CFG;
$CFG = new stdClass();

$CFG->dbtype    = 'mariadb';
$CFG->dblibrary = 'native';
$CFG->dbhost    = '{{ db_host }}';
$CFG->dbname    = '{{ db_name }}';
$CFG->dbuser    = '{{ db_user }}';
$CFG->dbpass    = '{{ vault_db_password }}';
$CFG->prefix    = 'mdl_';
$CFG->dboptions = [
    'dbpersist' => false,
    'dbsocket'  => false,
    'dbport'    => '',
];

$CFG->wwwroot   = '{{ moodle_url }}';
$CFG->dataroot  = '{{ moodle_data_dir }}';
$CFG->admin     = 'admin';

$CFG->directorypermissions = 0770;
$CFG->sslproxy = false;

require_once(__DIR__ . '/lib/setup.php');

Permisos recomendados

El fichero config.php contiene credenciales de base de datos. Por eso el playbook lo genera con permisos restrictivos y propietario www-data.

En producción conviene revisar también permisos de moodledata, configuración de backups, acceso a logs y políticas de rotación.

Paso 6: Ejecutar el playbook

Checklist antes de ejecutar

Confirma que el inventario apunta al servidor correcto, que el usuario SSH tiene permisos, que las variables sensibles están protegidas y que el dominio DNS resuelve hacia la máquina donde vas a instalar Moodle.

También conviene lanzar primero el playbook con --check cuando sea posible y revisar qué cambios aplicará antes de modificar el servidor.

Con el inventario, el playbook, las plantillas y el vault preparados, ya puedes ejecutar Ansible:

Bash
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass

# Modo comprobación, cuando las tareas lo permitan
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass --check

Si el playbook se completa correctamente, el servidor debería quedar con Moodle desplegado, Apache configurado, PHP-FPM funcionando, MariaDB preparada, Redis activo y HTTPS habilitado.

Paso 7: Verificación del sistema

Después de automatizar la instalación, no des por terminado el despliegue sin verificar servicios, configuración y acceso web. Una instalación automatizada debe cerrarse siempre con una comprobación objetiva.

Checklist visual de verificación técnica de servicios web y caché
Verificación técnica de un despliegue Moodle automatizado con Ansible, revisando Apache, PHP-FPM, MariaDB, Redis, SSL, permisos de moodledata y acceso desde navegador.

Puedes usar comandos como estos para revisar el estado del sistema:

Bash
systemctl status apache2
systemctl status php8.3-fpm
systemctl status mariadb
systemctl status redis

apache2ctl -t
php -v
mysql -u moodleuser -p moodle -e "SHOW TABLES;"
curl -I https://moodle.miempresa.com
  • Apache: debe estar activo y sin errores de sintaxis.
  • PHP-FPM: debe estar iniciado y conectado correctamente desde Apache.
  • MariaDB: debe aceptar conexión con el usuario de Moodle.
  • Redis: debe estar disponible si vas a usarlo para caché o sesiones.
  • HTTPS: el dominio debe responder con certificado válido.
  • Moodle: debe cargar en navegador y poder completar el asistente o acceder si ya está configurado.

Conclusión: automatizar instalación Moodle con Ansible en entornos reales

Idea clave

Ansible no sustituye el conocimiento de administración de sistemas. Lo ordena, lo documenta y lo convierte en un proceso repetible.

Para equipos que mantienen varias plataformas Moodle, esta diferencia es enorme: menos improvisación, menos pasos manuales y más control sobre cada cambio aplicado en infraestructura.

Automatizar instalación Moodle con Ansible permite transformar una instalación manual, larga y propensa a errores en un proceso controlado. Además, cada servidor puede configurarse de forma coherente, cada cambio queda documentado y cada despliegue puede revisarse, versionarse y repetirse.

La clave está en no limitarse a “hacer que funcione”. Un buen playbook debe ser legible, seguro, idempotente y fácil de adaptar. Debe separar variables, proteger secretos, usar plantillas y permitir que cualquier persona del equipo entienda qué se está instalando y por qué.

En proyectos Moodle reales, esta aproximación ayuda a reducir incidencias, acelerar despliegues, facilitar auditorías técnicas y mejorar la mantenibilidad de la infraestructura. Y, sobre todo, libera tiempo para trabajar en lo importante: mejorar la plataforma, integrarla con otros sistemas y ofrecer una mejor experiencia de aprendizaje.

¿Ya estás usando Ansible para desplegar Moodle o sigues haciendo instalaciones manuales servidor a servidor? Si tu objetivo es automatizar instalación Moodle con Ansible de forma segura, el primer paso es convertir este playbook en una base versionada y adaptable a tus entornos reales.

Categorías: ,

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *