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 nombre mail.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.

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

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.

TipoNombreValor
Amailyour_server_ip
MX@10 mail.your_domain.
CNAMEautodiscovermail.your_domain.
CNAMEautoconfigmail.your_domain.
TXT@v=spf1 mx -all
TXT_dmarcv=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:

  1. Ve a E-Mail > Configuration y abre la pestaña Domains.
  2. Pulsa Add domain, escribe your_domain y guarda. Mailcow genera automáticamente una clave DKIM de 2048 bits para el dominio.
  3. 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 TXT dkim._domainkey con 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:

ProtocoloServidorPuertoSeguridad
IMAPmail.your_domain993SSL/TLS
SMTP (envío)mail.your_domain465SSL/TLS
SMTP (envío)mail.your_domain587STARTTLS

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.