SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor

Instalar Flarum en un VPS con PHP y MariaDB

Instale Flarum 1.8 en un VPS con PHP, Composer y MariaDB. Expone solo /public con TLS y evita errores de correo y actualizaciones de extensiones.

Instalar Flarum en un VPS con PHP y MariaDB

Instale Flarum en un VPS y tendrá un foro que funciona con PHP y MariaDB, sin Docker, sin Ruby y sin un ejecutor de tareas independiente. Esa es la razón para elegirlo. Instalar Discourse en un VPS implica una pila de Docker con Ruby, PostgreSQL, Redis y un worker en segundo plano, y 2 GB de RAM son el mínimo práctico antes de añadir copias de seguridad o un servicio de correo. Discourse justifica ese consumo en una comunidad activa con miles de publicaciones al día. En un foro de unos cientos de personas, es infraestructura que paga cada mes y nunca utiliza. Flarum encaja en una pila PHP que quizá ya esté ejecutando, por lo que un VPS de 1 GB con nginx y MariaDB puede alojarlo junto a los demás servicios. Si todavía no ha tomado una decisión, la comparación más amplia del software de foros autoalojado cubre el resto de opciones.

Esta guía fija la instalación en Flarum 1.x, actualmente la serie 1.8. En agosto de 2026, Flarum 2.0 todavía es una versión candidata, por lo que 1.8 es la versión que debe ejecutar para un foro del que dependan otras personas. Las extensiones son más importantes aquí que la versión del núcleo, y la mayoría de sus autores todavía no han migrado a 2.0.

Requisitos de Flarum 1.8 en el servidor

Los requisitos documentados de Flarum son PHP 7.3 o posterior, MySQL 5.6+ o MariaDB 10.0.5+, y nginx o Apache con mod_rewrite. Ubuntu 24.04 incluye PHP 8.3 y MariaDB 10.11, por lo que los paquetes de la distribución cumplen ambos requisitos sin usar un repositorio de terceros. Las extensiones de PHP que requiere Flarum son curl, dom, fileinfo, gd, json, mbstring, openssl, pdo_mysql, tokenizer y zip. También necesita acceso al shell, porque Composer no es opcional en este caso: todas las extensiones de Flarum son paquetes de Composer y no hay forma de añadir una sin ejecutar Composer.

Flarum es una aplicación PHP convencional. Si ya ejecuta una pila LAMP en Ubuntu 24.04, la mayor parte de las dos secciones siguientes ya está instalada y puede pasar directamente a la base de datos.

Instale PHP y las extensiones que requiere Flarum

sudo apt update
sudo apt install -y nginx mariadb-server composer
sudo apt install -y php8.3-fpm php8.3-cli php8.3-curl php8.3-gd php8.3-mbstring php8.3-mysql php8.3-xml php8.3-zip
php -m | grep -E 'curl|dom|gd|mbstring|pdo_mysql|zip'
composer --version

Los nombres de los paquetes no coinciden uno por uno con la lista de Flarum. La extensión dom se incluye en php8.3-xml, y fileinfo, json, openssl y tokenizer están compiladas en PHP 8.3 en Ubuntu, por lo que no existe ningún paquete que instalar para ellas. grep debería mostrar seis líneas y composer --version debería indicar una versión 2.x. Conviene corregir ahora cualquier extensión que falte, porque Composer se niega a instalar Flarum sin ella y el error indica cuál es:

  Problem 1
    - flarum/core[v1.8.0, ..., v1.8.17] require ext-gd * -> it is missing from your system.
      Install or enable PHP's gd extension.

Compruebe que PHP de la línea de comandos y el gestor de procesos FastCGI (PHP-FPM) utilicen la misma versión. Composer se ejecuta mediante el binario de la línea de comandos, mientras que el foro se ejecuta mediante FPM, por lo que php -v y sudo php-fpm8.3 -v deben coincidir. Pueden quedar desincronizados en un equipo que haya acumulado varias versiones de PHP desde un repositorio de terceros. En ese caso, una extensión instalada para una versión no será visible para la otra.

Cree la base de datos y un usuario de base de datos dedicado

sudo mariadb-secure-installation
sudo mariadb
CREATE DATABASE flarum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'flarum'@'localhost' IDENTIFIED BY 'use-a-long-random-password';
GRANT ALL PRIVILEGES ON flarum.* TO 'flarum'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Asigne a Flarum su propio usuario de base de datos en lugar de root. La concesión sólo cubre flarum.* y nada más, por lo que un error de inyección SQL en una extensión que no haya escrito usted no puede leer sus otras bases de datos. El juego de caracteres también es importante: utf8mb4 almacena correctamente emojis y scripts no latinos, mientras que el utf8 antiguo de MySQL utiliza una codificación de tres bytes que trunca una publicación en el primer carácter de cuatro bytes. Confirme que el usuario funciona antes de continuar.

mariadb -u flarum -p flarum -e 'SELECT DATABASE();'

Esto debería mostrar flarum. ERROR 1045 (28000): Access denied for user 'flarum'@'localhost' significa que la contraseña no coincide o que el usuario se creó para un host distinto de localhost.

Instalar Flarum en un VPS con Composer, fijado en 1.8

Primero cree un usuario del sistema que sea propietario del código. Ejecutar Composer como root deja archivos propiedad de root en vendor/ y storage/. Después, PHP no puede escribir en su propia caché y el foro responde a todas las solicitudes con un error 500.

sudo useradd --system --home-dir /srv/flarum --shell /bin/bash flarum
sudo install -d -o flarum -g flarum -m 755 /srv/flarum
sudo -iu flarum

El último comando abre un shell como el usuario flarum, en /srv/flarum. Desde aquí hasta el final de la guía, todos los comandos se ejecutan con ese usuario, salvo que comiencen por sudo.

composer create-project flarum/flarum:^1.8.0 .

La restricción ^1.8.0 fija la versión. Acepta versiones de corrección 1.8.x y rechaza 2.0. Esto es lo adecuado mientras 2.0 siga siendo una versión candidata. Composer descarga el esqueleto, resuelve flarum/core y sus dependencias, y deja public/, storage/, vendor/, composer.json y un script de línea de comandos flarum.

En un VPS pequeño, los fallos suelen producirse en este paso, y dos problemas distintos pueden parecer iguales. PHP Fatal error: Allowed memory size of 134217728 bytes exhausted es el propio memory_limit de PHP. Anteponer COMPOSER_MEMORY_LIMIT=-1 al comando elimina ese límite durante una ejecución. Un Killed aislado en su propia línea, sin ningún error de PHP, indica que el kernel ha terminado el proceso por falta de memoria. Puede confirmarlo con dmesg | tail. En ese caso, la máquina realmente se ha quedado sin RAM, así que añada swap. Aumentar el límite de PHP empeora el problema, porque PHP intenta usar todavía más memoria antes de que intervenga el kernel.

Por qué sólo /public debe estar expuesto a la web

La raíz del proyecto contiene config.php con la contraseña de la base de datos en texto plano, vendor/ con todas las dependencias y storage/ con registros y sesiones en caché. Nada de eso debe estar en Internet público. Flarum mantiene todo lo que debe ser accesible por la web en un único subdirectorio, public/, que contiene index.php, una carpeta assets/ y poco más. Configure la raíz del servidor web para que apunte a /srv/flarum/public. Así, el resto del árbol queda inaccesible por HTTP de forma estructural, no mediante una regla que deba recordar.

Si apunta la raíz a /srv/flarum, las consecuencias son reales. Solicitar /config.php no devuelve nada útil, porque PHP ejecuta el archivo y éste sólo devuelve un array. En cambio, /storage/logs/flarum.log entrega a un desconocido los stack traces y los errores de la base de datos, y /composer.lock le muestra la versión exacta de cada paquete que utiliza. Esa lista permite probar vulnerabilidades conocidas.

Dar un pool propio a PHP-FPM

Flarum necesita acceso de escritura a tres rutas: la raíz del proyecto, para que el instalador pueda crear config.php; storage/, para los registros y la caché; y assets/, para los avatares y logotipos cargados. Los archivos pertenecen al usuario flarum, por lo que la solución adecuada es un pool de PHP-FPM que se ejecute como flarum. nginx sigue ejecutándose como www-data y sólo lee.

Escriba /etc/php/8.3/fpm/pool.d/flarum.conf:

[flarum]
user = flarum
group = flarum
listen = /run/php/php8.3-fpm-flarum.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 30s
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 16M
php_admin_value[post_max_size] = 17M
sudo systemctl restart php8.3-fpm
ls -l /run/php/php8.3-fpm-flarum.sock

El socket debe aparecer como srw-rw---- 1 www-data www-data. El proceso maestro se ejecuta como root y crea el socket, por lo que puede asignarle la propiedad a www-data mientras los workers se ejecutan como flarum. Si el socket no existe, sudo journalctl -u php8.3-fpm -n 30 muestra el mensaje FPM rechazó. pm = ondemand inicia los procesos worker sólo cuando llega una petición, por lo que un foro con poca actividad consume muy poca memoria entre visitas.

El bloque server de nginx

Flarum incluye un fragmento de nginx en la raíz del proyecto llamado .nginx.conf. Contiene la regla de reescritura, las cabeceras de caché y la configuración de compresión. Inclúyalo en lugar de copiarlo. Así, una actualización de Flarum que modifique el fragmento se aplicará en el servidor sin que tenga que editar nada.

server {
    listen 80;
    listen [::]:80;
    server_name forum.example.com;

    root /srv/flarum/public;
    index index.php;
    client_max_body_size 16M;

    include /srv/flarum/.nginx.conf;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm-flarum.sock;
    }
}

Guarde ese contenido como /etc/nginx/sites-available/flarum y habilítelo.

sudo ln -s /etc/nginx/sites-available/flarum /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t debe responder en syntax is ok y test is successful. La línea include es la que suele omitirse. Si se omite, aparece un síntoma muy concreto: la página principal carga correctamente y todos los enlaces a las discusiones devuelven un 404 de nginx. Flarum procesa dentro de PHP una URL como /d/1-hello-world. Esa ruta no corresponde a un archivo del disco. Por tanto, sin la regla try_files $uri $uri/ /index.php?$query_string del fragmento, nginx busca un directorio llamado d, no lo encuentra y devuelve un 404 antes de consultar a PHP. Apache obtiene el mismo enrutamiento del archivo .htaccess que ya se encuentra en public/. Esto sólo tiene efecto si el bloque <Directory> correspondiente establece AllowOverride All.

Añada TLS antes de ejecutar el instalador

Configure el certificado ahora, no después. Flarum escribe su URL base en config.php durante la instalación y obtiene esa URL de la dirección que aparece en el navegador. Si instala mediante http://, todas las URL de recursos que Flarum genere después comenzarán por http://. Cuando añada TLS (seguridad de la capa de transporte), el navegador bloqueará esas solicitudes por contenido mixto y el foro se cargará como texto sin estilos y sin JavaScript. Siga primero la configuración de certbot para Let's Encrypt en nginx, confirme que https://forum.example.com sirve una página y después vuelva aquí.

Si ya instaló el sistema mediante HTTP sin cifrar, la reparación requiere una sola línea. Edite /srv/flarum/config.php para que la clave url tenga el valor 'url' => 'https://forum.example.com', y después ejecute php flarum cache:clear como el usuario flarum.

Ejecute el instalador y restrinja config.php

Abra https://forum.example.com en un navegador. El instalador web de Flarum solicita el nombre de la base de datos, el usuario y la contraseña de la base de datos que creó, el título del foro y su cuenta de administrador. Escribe config.php y crea las tablas. Cuando termine, restrinja el archivo que ahora contiene la contraseña de la base de datos.

sudo chmod 640 /srv/flarum/config.php

El archivo sigue siendo legible y modificable por flarum, que es el usuario con el que se ejecuta FPM, y no es legible para ninguna otra cuenta del servidor. Después, compruebe la instalación desde el shell.

php flarum info

Muestra la versión del núcleo, la versión de PHP, las extensiones habilitadas, el controlador de correo y las rutas utilizadas. Es lo primero que debe ejecutar cuando algo no funciona correctamente y lo primero que le pedirá cualquiera que le ayude.

Por qué los correos de registro y restablecimiento de contraseña fallan sin mostrar errores

Esta sección determina si el foro superará su primera semana. Los dos primeros correos que envía un foro nuevo son la confirmación del registro y el restablecimiento de contraseña. Ambos se envían justo cuando una persona desconocida decide si la comunidad es real. Los dos pueden fallar silenciosamente. La persona que nunca recibió el correo no puede informarle, y nada del panel de administración cambia a rojo.

Flarum tiene cuatro controladores de correo, que se configuran en Administration y después en Email: smtp, mail, mailgun y log. Elija smtp y configúrelo para usar un servicio de correo que entregue los mensajes. El controlador mail entrega el mensaje a un binario local de sendmail. Este binario no existe en un Ubuntu VPS recién instalado, por lo que el mensaje no llega a ninguna parte y no se genera ningún error. El controlador log escribe el cuerpo del mensaje en storage/logs/ y no envía nada, porque está pensado para desarrollo.

Guarde la configuración y pulse el botón Enviar correo de prueba en esa misma página. Este botón es el único mecanismo de comprobación disponible, así que úselo antes de invitar a nadie. Si el mensaje no llega, lea el registro.

tail -n 50 /srv/flarum/storage/logs/flarum.log

Una conexión rechazada, un inicio de sesión rechazado y un error de negociación TLS aparecen allí junto con el host y el puerto que se probaron. Una línea que contiene Connection could not be established with host smtp.example.com significa que el puerto está bloqueado o es incorrecto. La causa habitual es que el proveedor bloquee por defecto el puerto saliente 25. El puerto 587 con el campo de cifrado configurado como tls funciona con casi todos los servicios de correo.

Cuando el correo no funciona, una persona que se registra ve el aviso de error genérico de Flarum, Oops! Something went wrong. Please reload the page and try again., porque la solicitud falla al enviar la confirmación. En ambos casos, esa persona no puede acceder y no le informará del problema.

Conseguir que el correo sea aceptado es un problema distinto de conseguir que se envíe. El correo enviado desde la dirección de un VPS sin registros SPF o DKIM publicados para el dominio termina en la carpeta de spam o se descarta sin generar ningún mensaje de rebote. Por eso, el registro muestra un envío correcto, pero el destinatario sigue sin ver el mensaje. Envío fiable de correo desde aplicaciones autoalojadas explica qué registros DNS debe publicar y qué servicios de retransmisión conviene usar.

Las extensiones son paquetes de Composer, por lo que las actualizaciones se realizan con un comando

En Flarum, una extensión es un paquete de Composer. No existe un botón de carga ni un archivo zip que se pueda copiar en una carpeta. Es una decisión de diseño deliberada: las versiones se resuelven entre sí, el conjunto exacto se registra en composer.lock y una extensión que depende de una biblioteca de PHP obtiene esa biblioteca correctamente. La contrapartida es que añadir una extensión requiere tres comandos ejecutados como usuario flarum.

composer require 'fof/upload:*'
php flarum migrate
php flarum cache:clear

Después, habilítela en Administración y, a continuación, Extensiones. Cada comando cumple una función distinta. composer require coloca el código en el disco. php flarum migrate ejecuta las migraciones de base de datos incluidas en la extensión, que es el mecanismo que crea sus propias tablas. php flarum cache:clear vuelve a generar los paquetes compilados de JavaScript y CSS que carga el navegador. Omitir el último comando provoca la confusión habitual: la extensión aparece en la lista, el interruptor está activado y el navegador no cambia en absoluto, aunque se recargue varias veces.

La eliminación de una extensión se realiza en el orden inverso. Desactívela primero en el panel de administración y, después, elimine el paquete. Flarum conserva deliberadamente las tablas de la extensión, de modo que volver a activarla más adelante no provoque pérdida de datos. Si también quiere eliminarlas, revierta sus migraciones antes de quitar el código.

php flarum migrate:reset --extension fof-upload
composer remove fof/upload
php flarum cache:clear

El id de la extensión en ese comando es el nombre del paquete con la barra reemplazada por un guion. Si prefiere hacer clic en lugar de escribir, composer require 'flarum/extension-manager:*' añade una página oficial de administración que integra Composer. Ejecuta las mismas operaciones como el usuario web, necesita la misma memoria y los mismos permisos de escritura, y falla de las mismas formas. Por eso, cuando algo falla, la línea de comandos sigue siendo la opción fiable.

Por qué composer update se niega a actualizar Flarum

Actualizar Flarum y todas sus extensiones requiere un comando de Composer seguido de dos comandos de Flarum. Primero haga una copia de seguridad de la base de datos.

composer update --prefer-dist --no-plugins --no-dev -a --with-all-dependencies
php flarum migrate
php flarum cache:clear

Lea la salida en lugar de dar por hecho que la operación funcionó. El caso importante es cuando Composer se niega a hacer cambios:

Your requirements could not be resolved to an installable set of packages.

Ese mensaje significa que una extensión instalada declara una restricción de flarum/core que excluye la versión a la que intenta actualizar. Composer no incumple la restricción. Por eso mantiene toda la instalación en la versión anterior, en lugar de crear una combinación que el autor de la extensión ha indicado que no funcionará. Busque el paquete responsable.

composer why-not flarum/core 1.8.17

La salida muestra todos los paquetes que bloquean esa versión y la restricción que declara cada uno. A partir de ahí, puede esperar a que el autor publique una versión compatible o eliminar la extensión y prescindir de ella. Este es el coste del modelo de Composer. Conviene entenderlo antes de instalar quince extensiones en un foro del que dependen otras personas. Prefiera extensiones que hayan publicado una versión recientemente y mantenga la lista lo bastante corta como para poder revisarla.

Qué debe incluir la copia de seguridad

Haga una copia de seguridad de la base de datos y del directorio del proyecto. Todo lo demás se puede reconstruir.

mariadb-dump -u flarum -p --single-transaction flarum > flarum-$(date +%F).sql
sudo tar czf flarum-files.tgz -C /srv flarum

En los sistemas antiguos, mariadb-dump se denomina mysqldump; en Ubuntu 24.04 funcionan ambos nombres. La base de datos contiene todas las publicaciones, todos los usuarios y toda la configuración. El directorio del proyecto contiene config.php, composer.json (que es el registro real de las extensiones que ejecuta) y assets/ con los avatares y logotipos cargados. Puede omitir vendor/, porque composer install lo reconstruye a partir de composer.lock, y storage/ se regenera automáticamente. Copie ambos archivos fuera del servidor, porque una copia de seguridad almacenada en el equipo que protege no es una copia de seguridad. La restauración requiere una instalación limpia de Flarum con la misma versión, composer install, volver a colocar los archivos guardados y cargar el archivo SQL.

FAQ

¿Puede Flarum ejecutarse en un VPS de 1 GB?

Sí, para una comunidad pequeña. En condiciones normales, Flarum es PHP-FPM atendiendo solicitudes junto con MariaDB, y con pm = ondemand los workers de PHP sólo existen mientras alguien está leyendo. El punto máximo de consumo se produce durante la instalación: composer create-project resuelve todo el grafo de dependencias en memoria y es el paso con más probabilidades de ser detenido por el asesino de procesos por falta de memoria. Añada un archivo de swap antes de instalar, o ejecute Composer una vez en una máquina más grande y copie después el árbol de archivos.

¿Por qué los enlaces de las discusiones devuelven 404 cuando la página principal funciona?

Al bloque de servidor de nginx le falta include /srv/flarum/.nginx.conf;. Flarum gestiona dentro de PHP las URL como /d/1-hello-world, y esa ruta no corresponde a un archivo del disco. Sin la regla try_files $uri $uri/ /index.php?$query_string del fragmento, nginx busca un directorio llamado d, no lo encuentra y devuelve 404 directamente, sin llamar a PHP. En Apache, el mismo enrutamiento procede de public/.htaccess, que se ignora a menos que el bloque <Directory> establezca AllowOverride All.

¿Por qué el foro perdió todos los estilos después de activar HTTPS?

Flarum almacena su URL base en config.php, obtenida de la dirección que usó al ejecutar el instalador. Si instaló mediante HTTP sin cifrar, Flarum sigue generando URL de recursos http://, y el navegador las bloquea como contenido mixto en una página HTTPS, que queda como texto sin estilos. Edite la clave url en /srv/flarum/config.php para establecer la dirección https:// y ejecute php flarum cache:clear con el usuario propietario de los archivos.

¿Por qué nadie recibe el correo de confirmación del registro?

Compruebe primero el controlador de correo. El controlador mail necesita un binario local de sendmail, que un VPS de Ubuntu recién creado no incluye, y el controlador log escribe en storage/logs/ sin enviar nada. Cambie a smtp, use el puerto 587 con el cifrado establecido en tls porque la mayoría de proveedores bloquean el puerto saliente 25, y pulse Send Test Mail. Si el registro muestra un envío correcto y el correo sigue sin llegar, el problema es la entregabilidad y no la configuración. Publique registros SPF y DKIM para su dominio de envío.

¿Debo instalar Flarum 1.8 o 2.0?

Instale 1.8. En agosto de 2026, Flarum 2.0 es una versión candidata, y, lo que es más importante, muchas extensiones todavía declaran una restricción flarum/core que termina en 1.x. Instalar 2.0 ahora significa ejecutar un foro cuyas extensiones no se pueden actualizar conjuntamente. Ese es exactamente el fallo que composer why-not existe para diagnosticar. Fije la versión con flarum/flarum:^1.8.0 y vuelva a evaluarlo cuando las extensiones de las que depende hayan publicado versiones 2.0.