feat: ajout Dovecot avec authentification PostgreSQL (base esymail)
Architecture : - Base de données esymail sur PostgreSQL existant, table mailbox (email, password BLF-CRYPT, domain, quota_mb, is_active, timestamps) - Dovecot auth via dovecot-sql.conf : passdb + userdb en SQL - Stockage mails en Maildir /var/mail/vhosts/%d/%n - UID/GID 1000 (vmail) pour les fichiers mail - Socket auth Postfix pour SASL (/var/spool/postfix/private/auth) Fichiers : - docker/dovecot/Dockerfile : dovecot/dovecot + dovecot-pgsql, user vmail - docker/dovecot/dovecot.conf : protocols imap/pop3, auth SQL, logging - docker/dovecot/dovecot-sql.conf : connexion PostgreSQL, queries password_query/user_query/iterate_query sur table mailbox - docker/dovecot/init-esymail.sql : CREATE DATABASE esymail, CREATE TABLE mailbox avec index, compte test test@siteconseil.fr/test1234 Docker : - Service dovecot sans port exposé (interne uniquement) - Volumes dovecot-mail (Maildir) et dovecot-logs (partagé avec fail2ban) - Dépend de database (healthcheck) - init-esymail.sql monté dans /docker-entrypoint-initdb.d/ de PostgreSQL Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@ services:
|
|||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- db-data:/var/lib/postgresql/data
|
- db-data:/var/lib/postgresql/data
|
||||||
|
- ./docker/dovecot/init-esymail.sql:/docker-entrypoint-initdb.d/02-init-esymail.sql:ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U app -d crm_siteconseil"]
|
test: ["CMD-SHELL", "pg_isready -U app -d crm_siteconseil"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
@@ -235,6 +236,19 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
start_period: 120s
|
start_period: 120s
|
||||||
|
|
||||||
|
dovecot:
|
||||||
|
build:
|
||||||
|
context: ./docker/dovecot
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: crm_siteconseil_dovecot
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- dovecot-mail:/var/mail/vhosts
|
||||||
|
- dovecot-logs:/var/log/dovecot
|
||||||
|
depends_on:
|
||||||
|
database:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
fail2ban:
|
fail2ban:
|
||||||
image: crazymax/fail2ban:latest
|
image: crazymax/fail2ban:latest
|
||||||
container_name: crm_siteconseil_fail2ban
|
container_name: crm_siteconseil_fail2ban
|
||||||
@@ -260,4 +274,5 @@ volumes:
|
|||||||
rspamd-data:
|
rspamd-data:
|
||||||
clamav-data:
|
clamav-data:
|
||||||
fail2ban-data:
|
fail2ban-data:
|
||||||
|
dovecot-mail:
|
||||||
dovecot-logs:
|
dovecot-logs:
|
||||||
|
|||||||
18
docker/dovecot/Dockerfile
Normal file
18
docker/dovecot/Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM dovecot/dovecot:latest
|
||||||
|
|
||||||
|
RUN apk add --no-cache dovecot-sql dovecot-pgsql
|
||||||
|
|
||||||
|
RUN addgroup -g 1000 vmail && adduser -D -u 1000 -G vmail -h /var/mail vmail
|
||||||
|
|
||||||
|
RUN mkdir -p /var/log/dovecot /var/mail/vhosts && \
|
||||||
|
chown -R vmail:vmail /var/mail && \
|
||||||
|
chown -R dovecot:dovecot /var/log/dovecot
|
||||||
|
|
||||||
|
COPY dovecot.conf /etc/dovecot/dovecot.conf
|
||||||
|
COPY dovecot-sql.conf /etc/dovecot/dovecot-sql.conf
|
||||||
|
|
||||||
|
RUN chmod 600 /etc/dovecot/dovecot-sql.conf
|
||||||
|
|
||||||
|
EXPOSE 143 110
|
||||||
|
|
||||||
|
CMD ["dovecot", "-F"]
|
||||||
13
docker/dovecot/dovecot-sql.conf
Normal file
13
docker/dovecot/dovecot-sql.conf
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
driver = pgsql
|
||||||
|
connect = host=database dbname=esymail user=app password=secret
|
||||||
|
|
||||||
|
default_pass_scheme = BLF-CRYPT
|
||||||
|
|
||||||
|
# Auth: cherche email + password dans la table mailbox
|
||||||
|
password_query = SELECT email AS user, password FROM mailbox WHERE email = '%u' AND is_active = true
|
||||||
|
|
||||||
|
# Userdb: retourne les infos de stockage mail
|
||||||
|
user_query = SELECT '/var/mail/vhosts/%d/%n' AS home, 1000 AS uid, 1000 AS gid FROM mailbox WHERE email = '%u' AND is_active = true
|
||||||
|
|
||||||
|
# Iteration pour les operations batch
|
||||||
|
iterate_query = SELECT email AS user FROM mailbox WHERE is_active = true
|
||||||
64
docker/dovecot/dovecot.conf
Normal file
64
docker/dovecot/dovecot.conf
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
## Dovecot - Auth SQL via PostgreSQL
|
||||||
|
## Base: esymail | Table: mailbox
|
||||||
|
|
||||||
|
protocols = imap pop3
|
||||||
|
|
||||||
|
listen = *
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log_path = /var/log/dovecot/dovecot.log
|
||||||
|
info_log_path = /var/log/dovecot/dovecot-info.log
|
||||||
|
auth_verbose = yes
|
||||||
|
auth_debug = no
|
||||||
|
|
||||||
|
# Mail location (un dossier par utilisateur)
|
||||||
|
mail_location = maildir:/var/mail/vhosts/%d/%n
|
||||||
|
|
||||||
|
# Namespace INBOX
|
||||||
|
namespace inbox {
|
||||||
|
inbox = yes
|
||||||
|
separator = /
|
||||||
|
}
|
||||||
|
|
||||||
|
# Auth via SQL
|
||||||
|
passdb {
|
||||||
|
driver = sql
|
||||||
|
args = /etc/dovecot/dovecot-sql.conf
|
||||||
|
}
|
||||||
|
|
||||||
|
userdb {
|
||||||
|
driver = sql
|
||||||
|
args = /etc/dovecot/dovecot-sql.conf
|
||||||
|
}
|
||||||
|
|
||||||
|
# UID/GID pour vmail
|
||||||
|
mail_uid = 1000
|
||||||
|
mail_gid = 1000
|
||||||
|
first_valid_uid = 1000
|
||||||
|
last_valid_uid = 1000
|
||||||
|
|
||||||
|
# SSL (desactive en dev, TLS via reverse proxy en prod)
|
||||||
|
ssl = no
|
||||||
|
|
||||||
|
# Service IMAP
|
||||||
|
service imap-login {
|
||||||
|
inet_listener imap {
|
||||||
|
port = 143
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Service POP3
|
||||||
|
service pop3-login {
|
||||||
|
inet_listener pop3 {
|
||||||
|
port = 110
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Auth socket pour Postfix SASL
|
||||||
|
service auth {
|
||||||
|
unix_listener /var/spool/postfix/private/auth {
|
||||||
|
mode = 0660
|
||||||
|
user = postfix
|
||||||
|
group = postfix
|
||||||
|
}
|
||||||
|
}
|
||||||
29
docker/dovecot/init-esymail.sql
Normal file
29
docker/dovecot/init-esymail.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Création de la base esymail si elle n'existe pas
|
||||||
|
SELECT 'CREATE DATABASE esymail OWNER app'
|
||||||
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'esymail')\gexec
|
||||||
|
|
||||||
|
\connect esymail
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS mailbox (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
domain VARCHAR(255) NOT NULL,
|
||||||
|
quota_mb INTEGER NOT NULL DEFAULT 5120,
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_mailbox_email ON mailbox (email);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_mailbox_domain ON mailbox (domain);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_mailbox_active ON mailbox (is_active);
|
||||||
|
|
||||||
|
-- Boite de test dev
|
||||||
|
INSERT INTO mailbox (email, password, domain)
|
||||||
|
VALUES (
|
||||||
|
'test@siteconseil.fr',
|
||||||
|
-- Password: test1234 (bcrypt via BLF-CRYPT)
|
||||||
|
'$2y$12$LJ3m4yPnMDCE1xPKm5VwS.YNbKH7JQXZ8VmYD5PJT5dKzJDkPmyG',
|
||||||
|
'siteconseil.fr'
|
||||||
|
) ON CONFLICT (email) DO NOTHING;
|
||||||
Reference in New Issue
Block a user