Instalación y configuración de un servidor de correo (Postfix + Dovecot + PostfixAdmin + Roundcube) en Debian 13

¿Qué vamos a montar?
En este tutorial vamos a levantar un servidor de correo completo en Debian 13 con dominios y buzones virtuales almacenados en una base de datos MariaDB. Cada pieza cumple un papel:
- Postfix: el servidor SMTP, se encarga de enviar y recibir el correo.
- Dovecot: el servidor IMAP/POP3, permite a los clientes leer los buzones; además valida las contraseñas (SASL) para Postfix y entrega el correo a los buzones vía LMTP.
- PostfixAdmin: un panel web para administrar dominios, buzones y alias sin tocar la base de datos a mano.
- Roundcube: el webmail, para leer y enviar correo desde el navegador.
Trabajaremos con usuarios virtuales: no son cuentas del sistema, sino filas en la base de datos, lo que facilita gestionar muchos buzones. En Debian 13 los paquetes son Postfix 3.10, Dovecot 2.4 (ojo, con una sintaxis de configuración distinta a la 2.3), MariaDB 11.8, PHP 8.4, PostfixAdmin 3.3 y Roundcube 1.6.
Como datos de ejemplo usaremos el dominio de correo midominio.example, el servidor mail.ejemplo.lan (IP 10.10.10.12) y el buzón juan@midominio.example.
Requisitos
- Debian 13 instalado y actualizado, con nombre de host e IP fija.
- Registros DNS MX y A apuntando al servidor (en un entorno de pruebas basta con
/etc/hosts). - Los puertos 25, 587, 465 (SMTP), 143/993 (IMAP) y 80/443 (web) accesibles.
- Privilegios de root.
Instalación de los paquetes
Instalamos toda la pila. Durante la instalación de Postfix elegimos «Sitio de Internet» y como nombre de correo mail.ejemplo.lan:
root@mail:~# apt update
root@mail:~# apt install -y postfix postfix-mysql \
dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql \
mariadb-server \
apache2 libapache2-mod-php php php-mysql php-mbstring php-intl php-gd php-curl php-zip php-xml \
postfixadmin roundcube roundcube-core roundcube-mysql
Dos detalles propios de Debian 13: el módulo LMTP de Dovecot ahora se llama
dovecot-lmtpd(nodovecot-lmtp), y la extensiónphp-imapya no existe en PHP 8.4 (se eliminó del núcleo); no la instalamos porque Roundcube trae su propia implementación de IMAP.
Durante la instalación de postfixadmin y roundcube, el asistente de dbconfig-common nos ofrecerá crear automáticamente su base de datos; aceptamos y definimos las contraseñas cuando lo pida.
Base de datos y usuario virtual del sistema
PostfixAdmin crea su propia base de datos (la llamaremos postfixadmin) con las tablas domain, mailbox y alias. Creamos un usuario de solo lectura para que Postfix y Dovecot consulten esas tablas:
root@mail:~# mysql
CREATE USER 'mailuser'@'127.0.0.1' IDENTIFIED BY 'ClaveFicticiaDB';
GRANT SELECT ON postfixadmin.* TO 'mailuser'@'127.0.0.1';
FLUSH PRIVILEGES;
EXIT;
Creamos también el usuario del sistema vmail (UID/GID 5000), propietario de todos los buzones, y el directorio donde se guardará el correo:
root@mail:~# groupadd -g 5000 vmail
root@mail:~# useradd -g vmail -u 5000 vmail -d /var/mail/vmail -m
root@mail:~# chown -R vmail:vmail /var/mail/vmail
Configuración de PostfixAdmin
Editamos /etc/postfixadmin/config.local.php para fijar el esquema de cifrado de contraseñas (usaremos el de Dovecot, BLF-CRYPT, muy recomendable) y activar la generación de buzones:
<?php
$CONF['configured'] = true;
$CONF['encrypt'] = 'dovecot:BLF-CRYPT';
$CONF['dovecotpw'] = "/usr/bin/doveadm pw";
$CONF['create_mailbox_subdirs_prefix'] = '';
// En un laboratorio con dominios que no resuelven en DNS (como midominio.example)
// desactivamos la comprobación DNS; en producción con un dominio real déjalo en 'YES'.
$CONF['emailcheck_resolve_domain'] = 'NO';
$CONF['default_aliases'] = array (
'abuse' => 'abuse@midominio.example',
'hostmaster' => 'hostmaster@midominio.example',
'postmaster' => 'postmaster@midominio.example',
'webmaster' => 'webmaster@midominio.example',
);
Para que doveadm pw sea accesible por el usuario del servidor web, le damos permiso de lectura al fichero de configuración de Dovecot más adelante. Ahora abrimos en el navegador la página de setup:
http://10.10.10.12/postfixadmin/setup.php
Escribimos una contraseña en el formulario Generate setup_password y pulsamos el botón: la web nos devuelve una línea $CONF['setup_password'] = '$2y$...'; que copiamos y pegamos en config.local.php. Después recargamos la página y ya podremos autenticarnos con esa contraseña para crear el primer administrador. El aviso rojo “connection not secure” es normal al acceder por HTTP en un entorno de pruebas; en producción usaríamos HTTPS.

Iniciamos sesión en http://10.10.10.12/postfixadmin/ con la cuenta de administrador recién creada.

Una vez dentro, PostfixAdmin nos muestra el menú principal con todas las acciones de administración.

Desde Lista de dominios → Nuevo dominio damos de alta nuestro dominio de correo midominio.example.

Y en Buzones de correo → Añadir buzón creamos la cuenta juan@midominio.example con su contraseña.

Configuración de Postfix
Creamos los ficheros de consulta MySQL que Postfix usará para saber qué dominios y buzones son válidos.
/etc/postfix/mysql-virtual-mailbox-domains.cf:
user = mailuser
password = ClaveFicticiaDB
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
/etc/postfix/mysql-virtual-mailbox-maps.cf:
user = mailuser
password = ClaveFicticiaDB
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
/etc/postfix/mysql-virtual-alias-maps.cf:
user = mailuser
password = ClaveFicticiaDB
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
Protegemos estos ficheros porque contienen la contraseña:
root@mail:~# chmod 640 /etc/postfix/mysql-virtual-*.cf
root@mail:~# chgrp postfix /etc/postfix/mysql-virtual-*.cf
Editamos /etc/postfix/main.cf y añadimos (o ajustamos) los parámetros de dominios virtuales, entrega vía LMTP a Dovecot, SASL y TLS:
myhostname = mail.ejemplo.lan
mydestination = localhost
mynetworks = 127.0.0.0/8, 10.10.10.0/24
message_size_limit = 52428800
# Dominios y buzones virtuales (MySQL / PostfixAdmin)
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
# Entrega al buzón mediante Dovecot LMTP
virtual_transport = lmtp:unix:private/dovecot-lmtp
# Autenticación SASL contra Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
# TLS (certificado autofirmado para el laboratorio)
smtpd_tls_cert_file = /etc/ssl/certs/mail.ejemplo.lan.crt
smtpd_tls_key_file = /etc/ssl/private/mail.ejemplo.lan.key
smtpd_tls_security_level = may
smtp_tls_security_level = may
Generamos el certificado autofirmado del ejemplo (en producción usaríamos Let’s Encrypt):
root@mail:~# openssl req -new -x509 -days 3650 -nodes \
-subj "/CN=mail.ejemplo.lan" \
-out /etc/ssl/certs/mail.ejemplo.lan.crt \
-keyout /etc/ssl/private/mail.ejemplo.lan.key
Habilitamos los servicios de envío autenticado submission (587) y submissions (465) en /etc/postfix/master.cf descomentando y dejando estos bloques:
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
Configuración de Dovecot 2.4
Aquí está el mayor cambio respecto a versiones anteriores: Dovecot 2.4 usa una sintaxis nueva para el correo y para la conexión SQL.
En /etc/dovecot/conf.d/10-mail.conf definimos el almacenamiento Maildir y el usuario del sistema:
mail_driver = maildir
mail_path = ~/Maildir
mail_home = /var/mail/vmail/%{user | domain}/%{user | username}
mail_uid = vmail
mail_gid = vmail
first_valid_uid = 5000
last_valid_uid = 5000
namespace inbox {
inbox = yes
}
En /etc/dovecot/conf.d/10-auth.conf habilitamos los mecanismos y el backend SQL:
auth_mechanisms = plain login
auth_allow_cleartext = yes
!include auth-sql.conf.ext
Y reescribimos /etc/dovecot/conf.d/auth-sql.conf.ext con la nueva sintaxis 2.4 (bloque de conexión mysql { }, passdb sql y userdb static):
sql_driver = mysql
mysql 127.0.0.1 {
user = mailuser
password = ClaveFicticiaDB
dbname = postfixadmin
}
passdb sql {
query = SELECT username AS user, password FROM mailbox \
WHERE username = '%{user}' AND active = '1'
}
userdb static {
fields {
uid = vmail
gid = vmail
home = /var/mail/vmail/%{user | domain}/%{user | username}
}
}
En /etc/dovecot/conf.d/10-master.conf publicamos los sockets que Postfix necesita: el de autenticación SASL y el de entrega LMTP, ambos dentro de /var/spool/postfix/private/:
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
Y en /etc/dovecot/conf.d/20-lmtp.conf normalizamos el nombre de usuario a minúsculas. Importante: como nuestros usuarios son la dirección completa (usuario@dominio), usamos %{user | lower} para conservar el dominio; si usáramos %{user | username | lower} se quedaría solo con la parte local y la entrega fallaría:
protocol lmtp {
auth_username_format = %{user | lower}
}
Por último, en /etc/dovecot/conf.d/10-ssl.conf indicamos el mismo certificado que en Postfix. Ojo con Dovecot 2.4: las directivas del certificado se renombraron respecto a la 2.3 (ssl_cert/ssl_key pasan a ser ssl_server_cert_file/ssl_server_key_file, ahora sin el prefijo <):
ssl = yes
ssl_server_cert_file = /etc/ssl/certs/mail.ejemplo.lan.crt
ssl_server_key_file = /etc/ssl/private/mail.ejemplo.lan.key
ssl_min_protocol = TLSv1.2
Reiniciamos ambos servicios y comprobamos la configuración de Dovecot:
root@mail:~# doveconf -n | head
root@mail:~# systemctl restart dovecot postfix
Configuración de Roundcube (webmail)
Roundcube ya quedó instalado y con su base de datos creada por dbconfig. Solo tenemos que apuntarlo a nuestro servidor IMAP/SMTP local editando /etc/roundcube/config.inc.php:
$config['imap_host'] = 'localhost:143';
$config['smtp_host'] = 'tls://localhost:587';
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
$config['product_name'] = 'Correo midominio.example';
// Como el certificado es autofirmado, no verificamos el par en las conexiones locales
$config['imap_conn_options'] = ['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]];
$config['smtp_conn_options'] = ['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]];
Importante con el envío: el prefijo
tls://ensmtp_hostobliga a Roundcube a hacer STARTTLS. Nuestro servicio submission (587) está configurado consmtpd_tls_security_level = encrypt, es decir, no ofrece autenticación hasta que la conexión esté cifrada. Si dejamoslocalhost:587sintls://, Roundcube no negocia TLS, Postfix no anunciaAUTHy al enviar obtendríamos «Error SMTP: Ha fallado la autenticación».
En Debian el paquete deja el Alias /roundcube comentado en /etc/apache2/conf-available/roundcube.conf; lo descomentamos, activamos la configuración y recargamos Apache:
root@mail:~# sed -i 's|#\s*Alias /roundcube|Alias /roundcube|' /etc/apache2/conf-available/roundcube.conf
root@mail:~# a2enconf roundcube
root@mail:~# systemctl reload apache2
Abrimos http://10.10.10.12/roundcube/ e iniciamos sesión con el buzón que creamos, juan@midominio.example.

Ya dentro tenemos la bandeja de entrada del webmail.

Prueba de envío y recepción
Para verificar el circuito completo, redactamos un correo desde Roundcube dirigido a otro buzón del dominio (por ejemplo maria@midominio.example) y lo enviamos.

Si todo está bien conectado, el mensaje sale por el servicio submission de Postfix, se autentica contra Dovecot y se entrega por LMTP en el buzón de destino. Lo confirmamos en la carpeta Enviados.

También podemos seguir el recorrido en los registros:
root@mail:~# journalctl -u postfix -u dovecot -f
Y con esto ya hemos terminado la instalación y configuración de nuestro servidor de correo en Debian 13, con dominios y buzones virtuales administrados cómodamente desde PostfixAdmin y accesibles por webmail con Roundcube.
Categories
Base de datos Implantación de aplicaciones Monitorización Redes Seguridad Servicios Sistemas Virtualización y contenedoresRecent Posts