Tutoriales de VPS
Crear un foro Discourse en un VPS (2026): Docker, HTTPS con dominio, SMTP, copias de seguridad y actualizaciones
Crea un foro comunitario en un VPS Ubuntu con el instalador Docker oficial de Discourse, cubriendo la elección de configuración, dominio y HTTPS automático, envío por SMTP, Cloudflare, copia y restauración, endurecimiento de seguridad, actualizaciones y resolución de problemas comunes.

Discourse es adecuado para crear comunidades de producto, foros de usuarios, sitios de preguntas y respuestas de conocimiento y comunidades de membresía de pago. Incluye categorías, etiquetas, búsqueda de texto completo, niveles de confianza, moderación, notificaciones y PWA móvil, lo que lo hace más completo que ensamblar plugins de foro de WordPress desde cero, pero también exige más en memoria, entregabilidad del correo y mantenimiento diario.
Este artículo utiliza el método de instalación Docker oficialmente compatible de Discourse para completar el dominio, el HTTPS automático, el registro del administrador, SMTP, las copias de seguridad, las actualizaciones y la resolución de problemas comunes en un VPS Ubuntu nuevo. El requisito mínimo oficial actual es 1 núcleo, 1 GB de memoria más Swap y 10 GB de disco; para producción se recomienda empezar con 2 núcleos, 2 GB y 20 GB SSD.
| Escenario | ¿Adecuado? | Explicación |
|---|---|---|
| Comunidades de soporte de producto, foros de usuarios | Adecuado | Categorías, etiquetas, búsqueda, moderación y notificaciones completas |
| Comunidades de alumnos de cursos, intercambio entre miembros | Adecuado | Permite restringir el registro, invitar usuarios e integrar inicio de sesión de terceros |
| Blogs de contenido puro | No prioritario | Los sistemas de publicación como WordPress o Ghost son más directos |
| Solo unas decenas de páginas estáticas de preguntas y respuestas | Posiblemente excesivo | Discourse ejecuta Rails, PostgreSQL, Redis y Sidekiq a la vez |
| Necesidad de modo lista de correo | Adecuado, pero hay que configurar el correo | SMTP, gestión de rebotes y dominio de envío deben ser fiables |
Discourse no es un programa PHP común, y no admite crear un sitio con el panel BaoTa y subir el código fuente para completar la instalación. El soporte oficial es únicamente el despliegue basado en Docker, y se recomienda un VPS Linux de 64 bits dedicado y limpio.
El instalador oficial ajusta automáticamente los Unicorn Workers y los Shared Buffers de PostgreSQL según la CPU y la memoria. La configuración mínima puede usarse para pruebas, pero en operación pública conviene reservar espacio para la base de datos, el procesamiento de imágenes, la búsqueda y las compilaciones de actualización.
| Escala de uso | Configuración recomendada | Situación aplicable |
|---|---|---|
| Pruebas, ensayos de migración | 1 núcleo 1 GB, 2 GB Swap, 20 GB SSD | Solo apto para pocos usuarios y validación a corto plazo |
| Comunidad pública pequeña | 2 núcleos 2-4 GB, 40 GB SSD | Pocos usuarios activos diarios, pocos adjuntos |
| Comunidad mediana | 4 núcleos 8 GB, 80 GB+ NVMe | Más plugins, búsqueda, imágenes y concurrencia |
| Comunidad grande | Web, base de datos y Redis separados | Requiere monitorización, almacenamiento de objetos, CDN y planificación profesional de capacidad |
El disco no debe calcularse solo por el tamaño del programa. Las subidas de usuarios, las copias automáticas, las imágenes Docker, los registros y los archivos temporales durante las actualizaciones crecen continuamente. Si aún no has decidido las especificaciones, puedes empezar por la guía de selección de configuración de VPS.
Prepara lo siguiente:
- Un VPS Ubuntu 24.04 LTS o Debian nuevo;
- Acceso SSH root y una IPv4 pública;
- Un dominio ya apuntado al VPS, por ejemplo
forum.example.com; - Un servicio de correo transaccional disponible, o usar temporalmente el inicio de sesión con Discourse ID;
- Una instantánea del proveedor u otra opción de reversión.
Añade un registro A para el dominio:
forum.example.com A 203.0.113.10
Comprueba la resolución y el uso de puertos:
dig +short forum.example.com A
sudo ss -lntp | grep -E ':(80|443)\b' || true
free -h
df -h
80 y 443 deben estar disponibles. Si en el servidor ya se ejecuta Nginx, Apache, Caddy, BaoTa u otro panel, no ejecutes el instalador directamente; los conflictos de puertos harán fallar la comprobación de conexión y la emisión del certificado HTTPS.
El firewall en la nube solo necesita abrir:
| Puerto | Uso | Recomendación |
|---|---|---|
| 22/TCP | Gestión SSH | Restringirlo a las IP de administración es más seguro |
| 80/TCP | HTTP, validación de certificados | Permitir acceso público |
| 443/TCP | Foro HTTPS | Permitir acceso público |
PostgreSQL y Redis no deben exponerse directamente a Internet.
Un VPS de 1 GB o 2 GB puede agotar la memoria fácilmente al compilar imágenes, actualizar y reconstruir contenedores. El instalador oficial puede crear Swap en máquinas de poca memoria, o puedes configurarlo manualmente de antemano:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/30-discourse-swap.conf
sudo sysctl --system
free -h
Swap solo reduce la probabilidad de OOM repentino; no sustituye la memoria física. Cuando el foro usa Swap con frecuencia o responde notablemente más lento, conviene ampliar la configuración en lugar de seguir aumentando Swap.
El comando de instalación rápida oficial actual de Discourse es:
wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/main/install-discourse | sudo bash
Si prefieres revisar el script antes de ejecutarlo, puedes dividirlo en dos pasos:
curl -fsSL https://raw.githubusercontent.com/discourse/discourse_docker/main/install-discourse -o install-discourse
less install-discourse
sudo bash install-discourse
El instalador comprueba los recursos del sistema, instala Docker y Git, descarga la configuración /var/discourse y entra en un asistente interactivo. El asistente pregunta principalmente por:
- El correo del administrador;
- Un dominio propio o un subdominio gratuito de
discourse.diy; - Si se omite la configuración SMTP;
- DNS, puertos 80/443 y ajustes de Swap.
Tras confirmar, compila el contenedor app, lo que suele tardar varios minutos. No interrumpas SSH solo porque la terminal no muestre nueva salida temporalmente. Puedes abrir otra ventana para observar los recursos:
docker ps
docker stats --no-stream
df -h
Comprueba tras finalizar la instalación:
cd /var/discourse
sudo ./launcher logs app
curl -I https://forum.example.com
Normalmente, el certificado Let's Encrypt se configura automáticamente durante el proceso de instalación, y no es necesario instalar Certbot de nuevo en el host.
Abre https://forum.example.com en el navegador y regístrate con el correo de administrador introducido durante la instalación. Solo la cuenta que coincida con DISCOURSE_DEVELOPER_EMAILS puede obtener privilegios de administrador tras el primer registro.
Tras entrar por primera vez al panel de administración, completa:
- Configurar el nombre del sitio, la descripción, el logo y el idioma predeterminado;
- Decidir si el registro es abierto, por invitación o solo el administrador crea usuarios;
- Crear categorías, normas del foro, política de privacidad y términos del servicio;
- Activar el filtro de palabras sensibles, la cola de moderación y los límites de publicación para usuarios nuevos;
- Crear una cuenta de prueba normal para verificar el registro, la publicación y las notificaciones.
No pruebes solo con la cuenta de administrador. Los permisos de usuario normal, la verificación por correo, la subida de imágenes y los problemas de niveles de confianza suelen aparecer solo al recorrer realmente el flujo de registro.
El nuevo instalador oficial permite omitir SMTP y activar el inicio de sesión con Discourse ID. Así puedes completar primero las pruebas y también usar correo o métodos de inicio de sesión como Google, GitHub o Apple mediante el servicio de identidad unificado.
Sin embargo, las comunidades en producción deberían configurar igualmente correo transaccional dedicado. Sin SMTP, la verificación de registro tradicional, los correos de resumen, las notificaciones de mensajes privados, las respuestas por correo y algunos flujos de recuperación de cuentas quedarán limitados. No instales Postfix temporalmente en el mismo VPS para enviar correo directamente; la entregabilidad, PTR, SPF, DKIM y la gestión de rebotes aumentarán notablemente los costes de mantenimiento.
Los parámetros SMTP habituales son los siguientes:
SMTP 地址:smtp.example.net
SMTP 端口:587
SMTP 用户名:provider-user
SMTP 密码:独立 SMTP Key
发件地址:[email protected]
Para modificar la configuración de instalación, edita:
sudo nano /var/discourse/containers/app.yml
Ejemplo de campos:
env:
DISCOURSE_HOSTNAME: 'forum.example.com'
DISCOURSE_DEVELOPER_EMAILS: '[email protected]'
DISCOURSE_SMTP_ADDRESS: 'smtp.example.net'
DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: 'provider-user'
DISCOURSE_SMTP_PASSWORD: 'replace-with-smtp-key'
DISCOURSE_NOTIFICATION_EMAIL: '[email protected]'
YAML es sensible a la indentación, y cuando la contraseña contiene caracteres como #, :, $ debe ir entre comillas. Reconstruye el contenedor tras modificarlo:
cd /var/discourse
sudo ./launcher rebuild app
Después envía un correo de prueba desde el panel y comprueba SPF, DKIM, DMARC y el webhook de rebotes. El subdominio de envío debe verificarse según los requisitos del proveedor de correo; no des por hecho que los usuarios recibirán el correo solo porque el panel indique "enviado".
Durante la primera instalación se recomienda configurar el registro de Cloudflare como DNS Only, para asegurar que el instalador de Discourse pueda detectar directamente el origen y emitir el certificado. Tras una instalación correcta, activa el proxy y establece el modo SSL/TLS en Full (strict).
No uses el modo Flexible, ya que Cloudflare se conecta al origen por HTTP, lo que provoca fácilmente bucles de redirección y anomalías en las cookies de inicio de sesión. Si aparecen bucles HTTPS, puedes consultar Solución de bucles de redirección HTTPS en VPS.
Tras activar Cloudflare, comprueba:
curl -I http://forum.example.com
curl -I https://forum.example.com
curl -sS https://forum.example.com/srv/status
El inicio de sesión, la publicación, la subida y las notificaciones en tiempo real del foro deben probarse por completo; no basta con que la página de inicio devuelva 200.
Activa las copias automáticas en Admin → Backups y configura la frecuencia y el número de copias a conservar. Las copias deben incluir la base de datos y las subidas de usuarios, pero las copias locales se perderán junto con el VPS, por lo que deben copiarse a almacenamiento externo.
Los datos persistentes predeterminados se encuentran en:
/var/discourse/shared/standalone/
Los archivos de copia habituales se encuentran en:
/var/discourse/shared/standalone/backups/default/
Comprueba las copias recientes:
sudo find /var/discourse/shared/standalone/backups -type f -printf '%TY-%Tm-%Td %TH:%TM %s %p\n' | sort
Se recomienda mantener tres capas a la vez:
- Copias automáticas del panel de Discourse;
- Instantáneas del proveedor del VPS, para revertir rápidamente si falla una actualización;
- Copias externas en S3, almacenamiento de objetos u otro servidor.
Realiza al menos una restauración de prueba. Las copias que solo se crean y nunca se verifican no demuestran que sean utilizables tras una corrupción de la base de datos o un borrado accidental. Para el método completo, consulta la guía de simulacro de copia y restauración en VPS.
Las actualizaciones de versión menor pueden ejecutarse desde el panel en /admin/upgrade. Cuando se trata de imágenes base, plantillas Docker o cambios de versión mayor, reconstruir desde la línea de comandos facilita conservar los registros completos:
cd /var/discourse
sudo ./launcher rebuild app
Antes de actualizar, ejecuta:
free -h
df -h
docker ps
sudo ./launcher logs app
Asegúrate de tener una copia y una instantánea recientes, y luego programa una ventana de mantenimiento. rebuild destruye el contenedor antiguo y reconstruye desde la configuración; los datos persistentes se guardan en /shared, pero errores de configuración, falta de disco o fallos de descarga aún pueden causar caídas.
Tras actualizar, comprueba la página de inicio, el inicio de sesión, la publicación, la búsqueda, la subida de imágenes, el correo y las tareas en segundo plano. No des por terminado el mantenimiento solo porque el estado del contenedor sea Up.
- Usa inicio de sesión SSH con clave y restringe el origen de administración;
- Abre solo 22, 80 y 443, y no expongas PostgreSQL ni Redis;
- Activa la autenticación de dos factores para el administrador y usa una cuenta normal para publicar a diario;
- Limita los enlaces, adjuntos, mensajes privados y frecuencia de publicación de los usuarios nuevos;
- Instala puntualmente las actualizaciones de seguridad de Discourse;
- Instala plugins solo desde repositorios de confianza y registra versiones y propósitos;
- No escribas claves SMTP, secretos OAuth ni claves de almacenamiento de objetos en repositorios públicos;
- Configura copias externas, alertas de disco y monitorización de disponibilidad del sitio.
Discourse incluye limitación de velocidad en la capa de aplicación, pero no sustituye a los firewalls en la nube, las CDN y la monitorización de capacidad. Cuando una comunidad pública sufre un ataque CC, puedes tratarlo con la lista de comprobación de Cloudflare WAF y limitación de velocidad en Nginx.
sudo ss -lntp | grep -E ':(80|443)\b'
docker ps --format 'table {{.Names}}\t{{.Ports}}'
Confirma qué servicio ocupa el puerto antes de decidir migrarlo o detenerlo. No termines directamente procesos de producción que no reconozcas.
dig +short forum.example.com A
curl -4 ifconfig.me
Las dos IP deben coincidir. Comprueba también registros AAAA incorrectos, el proxy de Cloudflare, el firewall en la nube y la caché DNS.
free -h
swapon --show
dmesg -T | grep -i -E 'out of memory|killed process'
Si no hay Swap, configura primero 2 GB de Swap; si el OOM sigue ocurriendo con frecuencia durante la operación a largo plazo, amplía a 2 GB o 4 GB de memoria.
cd /var/discourse
sudo ./launcher logs app
docker ps -a
curl -I http://127.0.0.1
sudo tail -n 100 /var/discourse/shared/standalone/log/rails/production.log
Revisa especialmente DNS, certificados, espacio en disco, arranque de la base de datos, registros de Rails y mapeo de puertos.
Verifica la dirección SMTP, el puerto, el usuario, la clave, el modo TLS y el dominio de envío. Los proveedores de nube pueden bloquear el puerto 25; el correo transaccional suele usar 587 o el puerto indicado por el proveedor. Los cambios en app.yml solo surten efecto tras reconstruir.
Revisa primero el registro completo de compilación para confirmar si el plugin es compatible con la versión actual de Discourse. No borres el directorio persistente solo para que la actualización continúe. Deberías revertir la instantánea o eliminar temporalmente el plugin incompatible de app.yml, y luego reconstruir y verificar los datos.
- El registro A del dominio apunta al VPS actual y 80/443 son accesibles
- Tanto el sitio principal como el panel usan HTTPS válido
- Los usuarios normales pueden registrarse, iniciar sesión, publicar, buscar y subir imágenes
- Los correos de prueba SMTP llegan y SPF, DKIM y DMARC son correctos
- El administrador tiene activada la autenticación de dos factores
- Las copias automáticas están activadas y se copian a almacenamiento externo
- Se ha completado un simulacro de restauración de copia
- Hay instantánea antes de actualizar y se revisan correo y tareas en segundo plano después
- PostgreSQL, Redis y las credenciales de administración no están expuestos a Internet
- Hay alertas de disco, memoria, certificados y disponibilidad del sitio
El verdadero coste de despliegue de Discourse no está en abrir la página de inicio la primera vez, sino en la entregabilidad del correo, la moderación, el crecimiento de los adjuntos, la copia y restauración y las actualizaciones continuas. Las comunidades pequeñas que empiezan con 2 núcleos, 2 GB, correo transaccional dedicado y copias externas suelen ahorrar más tiempo que lidiar repetidamente con OOM, discos llenos y fallos de envío en un VPS de 1 GB.