Despliegue de Listmonk en un VPS: Gestión de envíos de correo con Docker, PostgreSQL y Caddy
TL;DR
En esta guía detallada, configuraremos paso a paso Listmonk, una potente plataforma de código abierto para envíos de correo electrónico, en su propio servidor VPS. Utilizando Docker para la contenerización, PostgreSQL para la base de datos y Caddy como proxy inverso con HTTPS automático, obtendrá una solución totalmente controlada, escalable y segura para gestionar suscriptores y enviar campañas, evitando la dependencia de servicios de terceros y sus limitaciones.
- Configuración de Listmonk, PostgreSQL y Caddy utilizando Docker Compose para facilitar el despliegue y la gestión.
- Obtención y renovación automática de certificados SSL con Caddy.
- Garantía de seguridad básica del servidor (SSH, firewall, Fail2ban).
- Recomendaciones para elegir la configuración óptima del VPS y estrategias de copia de seguridad.
- Comandos prácticos y archivos de configuración para cada etapa de la instalación.
- Sección detallada sobre la resolución de problemas comunes y respuestas a preguntas frecuentes.
Qué configuramos y por qué
En esta guía nos centraremos en el despliegue de Listmonk, una plataforma moderna, de alto rendimiento y multifuncional para la gestión de envíos de correo electrónico. Listmonk es una excelente alternativa a las soluciones comerciales SaaS, como Mailchimp o SendGrid, ofreciendo control total sobre sus datos y envíos sin una tarifa mensual por el número de suscriptores o correos enviados (solo paga por el servicio SMTP y el VPS).
Qué obtendrá el lector al final:
- Un sistema completamente funcional para crear y enviar campañas de correo electrónico.
- La capacidad de importar y gestionar listas de suscriptores.
- Herramientas para la segmentación de la audiencia y la personalización de correos.
- Análisis detallado de aperturas, clics y bajas.
- Una solución robusta que funciona en contenedores Docker, con una base de datos PostgreSQL y un proxy inverso Caddy que proporciona HTTPS automático.
- Su propio servidor de envíos de correo, que puede escalar y personalizar según sus necesidades únicas, sin preocuparse por las políticas de uso de servicios de terceros.
Qué alternativas existen y por qué autoalojado en un VPS:
Existen numerosas soluciones de marketing por correo electrónico en el mercado. Se pueden dividir en dos categorías principales:
-
Servicios gestionados en la nube (SaaS): Mailchimp, SendGrid, Brevo (Sendinblue), MailerLite, Constant Contact.
- Ventajas: Facilidad de uso, no se requiere experiencia técnica, infraestructura lista.
- Desventajas: Alto costo con el crecimiento de la base de suscriptores, dependencia de la política del servicio (bloqueos de cuentas, restricciones de contenido), falta de control total sobre los datos, imposibilidad de personalización profunda.
-
Soluciones autoalojadas: Listmonk, Mautic, Ghost (con integración de envíos), Postfix/Dovecot (para el servidor de correo).
- Ventajas: Control total sobre los datos y la infraestructura, sin restricciones en el número de suscriptores, flexibilidad en la configuración e integración, costo potencialmente más bajo a largo plazo, mayor privacidad.
- Desventajas: Se requiere experiencia técnica para la instalación y el mantenimiento, la responsabilidad de la seguridad y el funcionamiento recae en usted.
La elección de una solución autoalojada en un VPS, como Listmonk, es ideal para desarrolladores, startups, pequeñas y medianas empresas, así como para cualquiera que valore la independencia, el control y la confidencialidad. Esto permite crear un potente sistema de envíos de correo que se adaptará completamente a sus requisitos y crecerá con su proyecto.
Qué configuración de VPS se necesita para esta tarea
La elección de una configuración de VPS adecuada es crucial para el funcionamiento estable y eficiente de Listmonk. Aunque Listmonk es bastante ligero, PostgreSQL puede ser exigente en cuanto a recursos con grandes volúmenes de datos y alta carga. Caddy y Docker por sí mismos consumen recursos mínimos, pero deben tenerse en cuenta.
Requisitos mínimos:
- CPU: 2 vCPU. Uno para Listmonk, uno para PostgreSQL y el resto del sistema.
- RAM: 4 GB. PostgreSQL prefiere RAM para el almacenamiento en caché, y Listmonk funcionará de manera más cómoda.
- Disco: 50 GB SSD. El SSD acelera significativamente el funcionamiento de la base de datos. Esto será suficiente para el sistema operativo, las imágenes de Docker, los datos de Listmonk y PostgreSQL (para decenas de miles de suscriptores y miles de correos enviados).
- Red: 100 Mbps. Para la mayoría de las tareas, esto es suficiente. Más importante es la estabilidad y la ausencia de límites de tráfico.
Plan de VPS específico para la tarea:
Para un inicio cómodo y el soporte de varios cientos de miles de suscriptores con envíos regulares, se recomienda considerar el siguiente plan de configuración:
- CPU: 2-4 vCPU (por ejemplo, Intel Xeon E5 o AMD EPYC).
- RAM: 4-8 GB DDR4.
- Disco: 80-160 GB NVMe SSD (NVMe es preferible por su velocidad, pero un buen SATA SSD también servirá).
- Red: Puerto de 1 Gbps con tráfico ilimitado o un límite alto (por ejemplo, 1-2 TB/mes).
- Sistema operativo: Ubuntu Server 24.04 LTS (o una versión estable más reciente).
Puede adquirir un VPS con las características indicadas para empezar o considerar opciones más potentes a medida que crezcan sus necesidades.
Cuándo se necesita un dedicado, no un VPS:
Debe considerar un servidor dedicado si tiene:
- Millones de suscriptores: PostgreSQL requerirá significativamente más recursos de CPU y RAM, así como discos de alta velocidad.
- Frecuencia de envíos muy alta: El envío de millones de correos por hora requiere un subsistema de red estable y potente, así como recursos dedicados para el servicio SMTP.
- Requisitos elevados de aislamiento y seguridad: Un servidor dedicado proporciona un aislamiento físico completo de otros usuarios.
- Necesidad de hardware específico: Por ejemplo, para cálculos de GPU o arreglos RAID especiales, lo cual rara vez se requiere para Listmonk, pero puede ser relevante para tareas asociadas.
Para la mayoría de las tareas de Listmonk a nivel de pequeña y mediana empresa, un VPS bien configurado será más que suficiente.
Ubicación: qué influencia tiene
- Latencia: Elija una ubicación cercana a su audiencia principal o a usted mismo (para la gestión). Una baja latencia mejora la velocidad de carga de la interfaz de Listmonk y la velocidad de entrega de los correos al proveedor SMTP.
- Legislación: Si trabaja con datos personales de usuarios de la UE, asegúrese de que el servidor esté en una jurisdicción que cumpla con el GDPR. Lo mismo aplica para otras regiones.
- Disponibilidad del proveedor SMTP: Algunos proveedores SMTP pueden tener regiones preferidas para un mejor rendimiento.
Preparación del servidor
Antes de proceder con la instalación de Listmonk, es necesario realizar una configuración básica de seguridad y actualizar el sistema operativo. Utilizaremos Ubuntu Server 24.04 LTS como la plataforma más común y estable para este tipo de tareas.
1. Conexión al servidor por SSH
Utilice un cliente SSH para conectarse a su VPS. Normalmente, el proveedor le proporcionará la dirección IP y las credenciales iniciales (usuario root y contraseña).
ssh root@SU_DIRECCIÓN_IP
2. Actualización del sistema
Primero, actualice la lista de paquetes y los paquetes instalados a las versiones más recientes.
sudo apt update -y # Обновление списка пакетов
sudo apt upgrade -y # Обновление установленных пакетов
sudo apt autoremove -y # Удаление ненужных зависимостей
3. Creación de un nuevo usuario con permisos sudo
El uso del usuario root para tareas diarias no es seguro. Cree un nuevo usuario y concédale permisos sudo.
adduser listmonkadmin # Создание нового пользователя "listmonkadmin"
usermod -aG sudo listmonkadmin # Добавление пользователя в группу sudo
Ahora, salga de la sesión root e inicie sesión con el nuevo usuario:
exit # Выход из сессии root
ssh listmonkadmin@SU_DIRECCIÓN_IP # Вход под новым пользователем
4. Configuración de claves SSH (recomendado)
Para mejorar la seguridad, se recomienda utilizar claves SSH en lugar de contraseñas. Genere un par de claves en su máquina local (si aún no lo ha hecho):
ssh-keygen -t rsa -b 4096 # На вашей локальной машине
Copie la clave pública al servidor:
ssh-copy-id listmonkadmin@SU_DIRECCIÓN_IP # На вашей локальной машине
Después de esto, puede deshabilitar la autenticación por contraseña en /etc/ssh/sshd_config, estableciendo PasswordAuthentication no y reiniciando el servicio SSH.
5. Configuración del firewall (UFW)
Habilite UFW (Uncomplicated Firewall) y permita solo los puertos necesarios: SSH (22), HTTP (80) y HTTPS (443).
sudo ufw allow OpenSSH # Разрешить SSH
sudo ufw allow http # Разрешить HTTP (для Caddy/Let's Encrypt)
sudo ufw allow https # Разрешить HTTPS
sudo ufw enable # Включить файрвол (подтвердите 'y')
sudo ufw status # Проверить статус файрвола
6. Instalación de Fail2ban
Fail2ban protege contra ataques de fuerza bruta, bloqueando las direcciones IP que intentan adivinar contraseñas de SSH y otros servicios.
sudo apt install fail2ban -y # Установка Fail2ban
sudo systemctl enable fail2ban # Включение автозапуска
sudo systemctl start fail2ban # Запуск службы
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # Создание локальной копии конфига
Edite /etc/fail2ban/jail.local para configurar los parámetros, por ejemplo, establezca bantime = 1h (tiempo de bloqueo) y maxretry = 5 (número de intentos). Asegúrese de que la sección [sshd] esté activa (enabled = true).
7. Instalación de utilidades básicas
Instale las utilidades necesarias que serán útiles durante el proceso de instalación y para la depuración.
sudo apt install curl wget git nano htop -y
Ahora su servidor está listo para la instalación del software principal.
Instalación de software — paso a paso
Para desplegar Listmonk, utilizaremos Docker y Docker Compose. Esto simplifica significativamente la instalación, la gestión de dependencias y garantiza la portabilidad de la solución. Instalaremos Docker Engine, Docker Compose y luego configuraremos los servicios de Listmonk, PostgreSQL y Caddy.
1. Instalación de Docker Engine
Instalaremos Docker desde el repositorio oficial para obtener las versiones más recientes (para 2026, nos centraremos en Docker Engine 26.x y superior).
# Actualización de la lista de paquetes
sudo apt update -y
# Instalación de los paquetes necesarios para trabajar con repositorios HTTPS
sudo apt install ca-certificates curl gnupg lsb-release -y
# Adición de la clave GPG oficial de Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Adición del repositorio de Docker a las fuentes de Apt
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Actualización de la lista de paquetes teniendo en cuenta el nuevo repositorio
sudo apt update -y
# Instalación de Docker Engine, containerd y Docker Compose (cli)
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
# Adición del usuario actual al grupo docker para trabajar sin sudo
sudo usermod -aG docker $USER
# Nota: Para aplicar los cambios de grupo, debe salir y volver a iniciar sesión en la sesión SSH
echo "Para completar la instalación de Docker, por favor, salga de la sesión SSH y vuelva a iniciar sesión."
Salga de la sesión SSH (exit) y vuelva a iniciar sesión para que los cambios del grupo Docker surtan efecto. Después de esto, verifique la instalación de Docker:
docker run hello-world # Verificación de la instalación exitosa de Docker
Si ve el mensaje "Hello from Docker!", significa que Docker está instalado y funcionando correctamente.
2. Instalación de Docker Compose (plugin)
En las versiones modernas de Docker, docker compose ya viene como un plugin de Docker CLI, por lo que no se requiere una instalación separada. Ya hemos instalado docker-compose-plugin en el paso anterior. Verifiquemos su versión:
docker compose version # Verificación de la versión de Docker Compose
La versión esperada para 2026 será algo como Docker Compose v2.25.x o superior.
3. Creación de un directorio para el proyecto Listmonk
Crearemos un directorio donde se almacenarán todos los archivos de configuración y datos de Listmonk.
mkdir ~/listmonk # Creación del directorio del proyecto en la carpeta de inicio del usuario
cd ~/listmonk # Navegación al directorio del proyecto
4. Preparación del archivo docker-compose.yml
Ahora crearemos el archivo principal docker-compose.yml, que describirá todos nuestros servicios: Listmonk, PostgreSQL y Caddy.
nano docker-compose.yml # Apertura del editor de texto para crear el archivo
Pegue el siguiente contenido (versiones de imágenes actuales para 2026):
version: '3.8'
services:
db:
image: postgres:17-alpine # Versión actual de PostgreSQL para 2026, alpine para ligereza
restart: always
environment:
POSTGRES_DB: listmonk # Nombre de la base de datos
POSTGRES_USER: listmonk # Usuario de la base de datos
POSTGRES_PASSWORD: ${DB_PASSWORD} # Contraseña del archivo .env
volumes:
- db_data:/var/lib/postgresql/data # Almacenamiento persistente de datos de la BD
healthcheck:
test: ["CMD-SHELL", "pg_isready -U listmonk -d listmonk"]
interval: 5s
timeout: 5s
retries: 5
listmonk:
image: listmonk/listmonk:2.5.0 # Versión actual de Listmonk para 2026
restart: always
environment:
LM_APP_NAME: "My Listmonk" # Nombre de su aplicación
LM_DATABASE_URL: postgres://listmonk:${DB_PASSWORD}@db:5432/listmonk?sslmode=disable # URL de conexión a la BD
LM_ADMIN_USERNAME: admin # Nombre de usuario del administrador por defecto
LM_ADMIN_PASSWORD: ${ADMIN_PASSWORD} # Contraseña del administrador del .env
LM_SMTP_HOST: ${SMTP_HOST} # Host del servidor SMTP (por ejemplo, smtp.sendgrid.net)
LM_SMTP_PORT: ${SMTP_PORT} # Puerto del servidor SMTP (por ejemplo, 587)
LM_SMTP_USERNAME: ${SMTP_USERNAME} # Nombre de usuario SMTP
LM_SMTP_PASSWORD: ${SMTP_PASSWORD} # Contraseña SMTP
LM_SMTP_AUTH_PROTOCOL: login # Protocolo de autenticación (normalmente login o plain)
LM_SMTP_FROM_EMAIL: "[email protected]" # Email del remitente por defecto
LM_SMTP_FROM_NAME: "Your Company" # Nombre del remitente por defecto
LM_ENABLE_GRAVATAR: "true" # Habilitar Gravatar
LM_DEBUG: "false" # Deshabilitar el modo de depuración en producción
LM_TLS_ENABLE: "true" # Habilitar TLS para SMTP (por defecto)
LM_APP_URL: "https://listmonk.yourdomain.com" # URL pública de su Listmonk
depends_on:
db:
condition: service_healthy # Iniciar Listmonk solo después de que la BD esté lista
volumes:
- listmonk_data:/var/lib/listmonk # Almacenamiento persistente de datos de Listmonk (avatares, adjuntos)
labels:
caddy: "listmonk.yourdomain.com" # Indicamos a Caddy el dominio para Listmonk
caddy.reverse_proxy: "{{upstreams}}" # Proxy de solicitudes a Listmonk
caddy:
image: caddy:2.7.6-alpine # Versión actual de Caddy para 2026, alpine para ligereza
restart: always
ports:
- "80:80" # Puerto HTTP
- "443:443" # Puerto HTTPS
volumes:
- caddy_data:/data # Para almacenar certificados SSL y otros datos de Caddy
- caddy_config:/config # Para almacenar la configuración de Caddy
- ./Caddyfile:/etc/caddy/Caddyfile # Nuestro Caddyfile personalizado
depends_on:
- listmonk # Caddy depende de Listmonk (aunque puede iniciarse antes)
volumes:
db_data:
listmonk_data:
caddy_data:
caddy_config:
IMPORTANTE: Reemplace listmonk.yourdomain.com con su dominio real que planea usar para Listmonk. Asegúrese de que el registro DNS (A o CNAME) para este dominio apunte a la dirección IP de su VPS.
5. Creación del archivo .env para secretos
Por seguridad, almacenaremos las contraseñas y otros datos sensibles en un archivo .env separado, que no se incluirá en el sistema de control de versiones (si lo utiliza).
nano .env # Apertura del editor de texto para crear el archivo
Pegue el siguiente contenido, reemplazando YOUR_DB_PASSWORD, YOUR_ADMIN_PASSWORD, YOUR_SMTP_HOST, etc., con sus propios valores:
DB_PASSWORD=YOUR_DB_PASSWORD_STRONG_AND_UNIQUE
ADMIN_PASSWORD=YOUR_ADMIN_PASSWORD_STRONG_AND_UNIQUE
SMTP_HOST=smtp.your-email-provider.com
SMTP_PORT=587
SMTP_USERNAME=your-smtp-username
SMTP_PASSWORD=YOUR_SMTP_PASSWORD_STRONG_AND_UNIQUE
Guarde el archivo (Ctrl+O, Enter, Ctrl+X).
6. Creación del archivo Caddyfile
Caddy gestiona automáticamente los certificados SSL, lo que simplifica enormemente la configuración de HTTPS. Crearemos un Caddyfile simple para nuestro dominio.
nano Caddyfile # Apertura del editor de texto para crear el archivo
Pegue el siguiente contenido, reemplazando listmonk.yourdomain.com con su dominio real:
listmonk.yourdomain.com {
reverse_proxy listmonk:9000 # Proxy de solicitudes a Listmonk, que escucha en el puerto 9000 dentro de Docker
log {
output stdout
format json
}
}
Guarde el archivo (Ctrl+O, Enter, Ctrl+X).
7. Inicio de los servicios de Docker Compose
Ahora que todos los archivos están listos, podemos iniciar todos los servicios con Docker Compose.
docker compose up -d # Inicio de todos los servicios en segundo plano
Este comando descargará las imágenes Docker necesarias (Listmonk, PostgreSQL, Caddy), creará los contenedores, configurará las redes y los iniciará. El flag -d significa iniciar en modo 'detached' (en segundo plano).
8. Inicialización de la base de datos de Listmonk
Después del primer inicio del contenedor Listmonk, es necesario inicializar su base de datos. Esto solo debe hacerse una vez.
docker compose run --rm listmonk ./listmonk --install # Ejecución del comando de instalación de Listmonk en un nuevo contenedor
Este comando creará tablas en la base de datos PostgreSQL y configurará los datos iniciales para Listmonk. El parámetro --rm garantiza que el contenedor temporal se eliminará después de ejecutar el comando.
Después de una inicialización exitosa, puede verificar el estado de los contenedores en ejecución:
docker compose ps # Verificación del estado de los contenedores
Todos los contenedores (db, listmonk, caddy) deben estar en estado running.
Ahora Listmonk debería ser accesible a través de su dominio (por ejemplo, https://listmonk.yourdomain.com) por HTTPS. Caddy obtendrá y configurará automáticamente un certificado SSL de Let's Encrypt.