Mailcow Dockerized es una suite de correo que empaqueta Postfix, Dovecot, Rspamd, SOGo, ClamAV y MariaDB en un conjunto de contenedores gestionados con Docker Compose, con un panel web para administrar dominios y buzones. En este tutorial instalarás Mailcow en un servidor Ubuntu 24.04, publicarás los registros DNS necesarios para enviar y recibir correo, crearás tu primer dominio y buzón, y dejarás programadas las copias de seguridad y las actualizaciones.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor dedicado a Mailcow con Ubuntu 24.04 LTS de 64 bits (x86_64 o arm64), por ejemplo un VPS de CubePath. Mailcow no funciona en contenedores OpenVZ ni LXC.
- Al menos 6 GB de RAM más 1 GB de swap (8 GB recomendados para 5 a 10 usuarios), 1 CPU y 20 GB de disco más el espacio para el correo.
- Un usuario no root con privilegios
sudo. - Un dominio propio, en esta guía
your_domain, con acceso a su zona DNS. El servidor usará el nombremail.your_domain. - La IP pública del servidor,
your_server_ip, con posibilidad de configurar su DNS inverso (PTR). - Salida por el puerto TCP 25 abierta. En CubePath, como en la mayoría de proveedores, el puerto 25 de salida está cerrado por defecto y se abre mediante una solicitud al soporte explicando el uso que harás del correo.
ImportanteMailcow necesita en exclusiva los puertos 25, 80, 110, 143, 443, 465, 587, 993, 995 y 4190. No lo instales en un servidor que ya tenga Nginx, Apache o Postfix escuchando en ellos.
Paso 1: Preparar el servidor
Empieza por comprobar que puedes enviar correo hacia fuera. Si el puerto 25 está bloqueado, Mailcow recibirá correo pero no podrá entregarlo:
nc -vz -w 5 gmail-smtp-in.l.google.com 25
Connection to gmail-smtp-in.l.google.com (142.250.27.26) 25 port [tcp/smtp] succeeded!
Si el comando termina con timed out, solicita la apertura del puerto antes de continuar.
Asigna al servidor su nombre completo. Mailcow y los servidores remotos esperan que el nombre del host coincida con el registro PTR:
sudo hostnamectl set-hostname mail.your_domain
Si el servidor tiene menos de 1 GB de swap, crea un fichero de intercambio:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Comprueba el resultado:
hostname -f
free -h
mail.your_domain
total used free shared buff/cache available
Mem: 7.8Gi 412Mi 6.9Gi 1.0Mi 720Mi 7.4Gi
Swap: 1.0Gi 0B 1.0Gi
Paso 2: Instalar Docker y las dependencias
Mailcow requiere Docker 24.0 o superior con el plugin de Compose v2. Instálalos desde el repositorio oficial de Docker, no desde el paquete docker.io ni desde Snap:
sudo apt update
sudo apt install ca-certificates curl git openssl jq gawk
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Añade el repositorio:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Instala Docker Engine y Compose:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verifica las versiones:
docker --version
docker compose version
Docker version 28.4.0, build d8eb465
Docker Compose version v2.39.2
NotaDocker publica los puertos de los contenedores con sus propias reglas de iptables, por lo que las reglas de UFW en la cadena INPUT no los filtran. La documentación de Mailcow desaconseja usar UFW o firewalld en el mismo host; si necesitas restringir el acceso, hazlo en la cadena
DOCKER-USERo en un firewall externo al servidor.
Paso 3: Descargar y configurar Mailcow
Los comandos de Mailcow se ejecutan como root y con la máscara 0022, para que los ficheros generados tengan los permisos que esperan los contenedores. Abre una shell de root:
sudo -i
Clona el repositorio oficial en /opt:
umask 0022
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
Genera la configuración:
./generate_config.sh
El script te pide el nombre del servidor de correo (mail.your_domain, nunca el dominio sin prefijo), la zona horaria (por ejemplo Europe/Madrid) y la rama a seguir. Elige la rama estable master. Al terminar crea el fichero mailcow.conf.
Revisa los valores principales del fichero:
nano mailcow.conf
MAILCOW_HOSTNAME=mail.your_domain
TZ=Europe/Madrid
SKIP_LETS_ENCRYPT=n
SKIP_CLAMD=n
SKIP_SOGO=n
SKIP_LETS_ENCRYPT=n hace que Mailcow obtenga automáticamente un certificado de Let's Encrypt en cuanto el DNS apunte al servidor. Si vas justo de memoria, SKIP_CLAMD=y desactiva el antivirus ClamAV, que es el componente que más RAM consume.
Paso 4: Crear los registros DNS
Antes de arrancar Mailcow, publica en la zona DNS de your_domain los registros básicos. El certificado de Let's Encrypt no se emitirá hasta que mail.your_domain resuelva a la IP del servidor.
| Tipo | Nombre | Valor |
|---|---|---|
| A | mail | your_server_ip |
| MX | @ | 10 mail.your_domain. |
| CNAME | autodiscover | mail.your_domain. |
| CNAME | autoconfig | mail.your_domain. |
| TXT | @ | v=spf1 mx -all |
| TXT | _dmarc | v=DMARC1; p=quarantine; rua=mailto:postmaster@your_domain |
Si el servidor tiene IPv6, añade también un registro AAAA para mail. El registro DKIM lo generará Mailcow en el paso 6.
Configura además el DNS inverso de la IP para que resuelva a mail.your_domain. En CubePath se hace desde el panel: en la página Floating IPs o en la pestaña de red del VPS, edita el campo Reverse DNS de la IP.
Comprueba los registros desde el servidor:
dig +short A mail.your_domain
dig +short MX your_domain
dig +short -x your_server_ip
your_server_ip
10 mail.your_domain.
mail.your_domain.
Paso 5: Arrancar Mailcow
Desde /opt/mailcow-dockerized, y todavía como root, descarga las imágenes y levanta los contenedores. La primera vez tarda varios minutos:
docker compose pull
docker compose up -d
Comprueba que todos los servicios están en marcha:
docker compose ps --format "table {{.Service}}\t{{.Status}}"
SERVICE STATUS
acme-mailcow Up 2 minutes
clamd-mailcow Up 2 minutes (healthy)
dovecot-mailcow Up 2 minutes
mysql-mailcow Up 2 minutes
nginx-mailcow Up 2 minutes
postfix-mailcow Up 2 minutes
rspamd-mailcow Up 2 minutes
sogo-mailcow Up 2 minutes
...
Revisa que el certificado se ha emitido correctamente:
docker compose logs --tail=20 acme-mailcow
Si el DNS del paso anterior ya se ha propagado, el registro termina indicando que el certificado se ha validado; si ves errores de validación, revisa la sección de solución de problemas. Sal de la shell de root con exit.
Paso 6: Configurar el panel, el dominio y el primer buzón
Abre https://mail.your_domain/admin en el navegador e inicia sesión con el usuario admin y la contraseña por defecto moohoo. Lo primero es cambiar esa contraseña desde el apartado de administradores del panel y, si quieres, activar la verificación en dos pasos para la cuenta.
Para dar de alta tu dominio:
- Ve a E-Mail > Configuration y abre la pestaña Domains.
- Pulsa Add domain, escribe
your_domainy guarda. Mailcow genera automáticamente una clave DKIM de 2048 bits para el dominio. - En la lista de dominios, pulsa el botón DNS junto a
your_domain. La página muestra todos los registros que Mailcow espera, con su estado, incluido el TXTdkim._domainkeycon la clave pública.
Copia el registro DKIM a tu zona DNS y comprueba que ya se publica:
dig +short TXT dkim._domainkey.your_domain
"v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
Vuelve a la pestaña Mailboxes, pulsa Add mailbox y crea un buzón, por ejemplo usuario@your_domain, con una contraseña robusta. El usuario puede entrar al webmail SOGo en https://mail.your_domain/SOGo y los clientes de correo se configuran con estos datos:
| Protocolo | Servidor | Puerto | Seguridad |
|---|---|---|---|
| IMAP | mail.your_domain | 993 | SSL/TLS |
| SMTP (envío) | mail.your_domain | 465 | SSL/TLS |
| SMTP (envío) | mail.your_domain | 587 | STARTTLS |
Gracias a los registros autodiscover y autoconfig, Thunderbird, Outlook y la app Mail de Apple detectan estos valores solos a partir de la dirección de correo.
Paso 7: Verificar el envío y la recepción
Comprueba desde tu equipo que el servicio de envío responde con un certificado válido:
openssl s_client -connect mail.your_domain:465 -brief < /dev/null
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN = mail.your_domain
Hash used: SHA256
Signature type: RSA-PSS
Verification: OK
Después envía un correo desde SOGo a una cuenta externa (Gmail, Outlook) y responde a él. En Gmail, la opción Mostrar original del mensaje recibido debe indicar PASS en SPF, DKIM y DMARC. Si un mensaje no llega, revisa los registros de Postfix:
cd /opt/mailcow-dockerized
sudo docker compose logs --tail=100 postfix-mailcow
Rspamd, el filtro antispam de Mailcow, tiene su propia interfaz en https://mail.your_domain/rspamd. Su contraseña se establece desde el panel de administración, en la sección de configuración de acceso a Rspamd UI.
Paso 8: Programar copias de seguridad
Mailcow incluye el script helper-scripts/backup_and_restore.sh, que guarda el correo, la base de datos, la configuración de Rspamd y Postfix, y las claves de cifrado. La variable MAILCOW_BACKUP_LOCATION indica dónde dejar las copias para que el script no pregunte nada y pueda ejecutarse desde cron.
Crea el directorio y lanza una primera copia manual:
sudo mkdir -p /opt/backup
cd /opt/mailcow-dockerized
sudo MAILCOW_BACKUP_LOCATION=/opt/backup ./helper-scripts/backup_and_restore.sh backup all
sudo ls /opt/backup
mailcow-2026-09-25-10-15-02
Programa una copia diaria a las 04:05 que borre las de más de siete días:
sudo nano /etc/cron.d/mailcow-backup
5 4 * * * root cd /opt/mailcow-dockerized && MAILCOW_BACKUP_LOCATION=/opt/backup /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all --delete-days 7
Guardar las copias en el mismo disco no protege frente a la pérdida del servidor: sincroniza /opt/backup con otro equipo o con un almacenamiento de objetos. Para restaurar, ejecuta el mismo script con restore; te pedirá la ruta de la copia y qué componentes recuperar.
Paso 9: Actualizar Mailcow
Mailcow publica actualizaciones con frecuencia, a menudo con parches de seguridad. El script update.sh descarga el código nuevo, actualiza las imágenes y reinicia los contenedores. Primero comprueba si hay versión nueva:
sudo -i
umask 0022
cd /opt/mailcow-dockerized
./update.sh --check
Si hay actualización disponible, aplícala y confirma los cambios cuando el script lo pregunte:
./update.sh
Haz una copia de seguridad antes de cada actualización y comprueba después con docker compose ps que todos los contenedores vuelven a estar en marcha.
Solución de problemas
Un contenedor no arranca porque el puerto ya está en uso. Algún servicio del sistema ocupa un puerto de Mailcow. Localízalo, detenlo y deshabilítalo:
sudo ss -tlnp | grep -E ':(25|80|443|587|993) '
Let's Encrypt no emite el certificado. Casi siempre es DNS: mail.your_domain, autodiscover y autoconfig deben resolver a la IP del servidor y el puerto 80 debe ser accesible desde Internet. Corrige el DNS y reinicia el contenedor ACME con sudo docker compose restart acme-mailcow.
Los correos salientes se quedan en cola. Revisa la cola con sudo docker compose exec postfix-mailcow postqueue -p y los registros de postfix-mailcow. Si ves Connection timed out hacia puertos 25 remotos, la salida por el puerto 25 sigue bloqueada.
Los correos llegan a la carpeta de spam del destinatario. Comprueba en la página DNS del dominio que todos los registros aparecen en verde, que el PTR coincide con mail.your_domain y que la IP no figura en listas negras.
Conclusión
Tienes un servidor de correo completo con Mailcow en Ubuntu 24.04: recibe y envía correo firmado con DKIM, filtra spam con Rspamd, ofrece webmail con SOGo y guarda una copia de seguridad diaria. Como siguientes pasos, endurece la política DMARC a p=reject cuando los informes confirmen que todo tu correo legítimo pasa la autenticación, añade registros MTA-STS y TLS-RPT, y vigila la reputación de tu IP durante las primeras semanas de envío.
