add base-images: mail-stack

This commit is contained in:
Haitao Pan 2025-12-03 13:24:40 +08:00
parent 14d5ec7253
commit 35f9ffd512
10 changed files with 194 additions and 0 deletions

View File

@ -0,0 +1,39 @@
# Mail Stack Chasquid + Dovecot + Certbot (Split Containers)
架构图
```
INBOUND EMAIL
↓ 25 (SMTP)
+-----------+
INTERNET →→→→→ | chasquid | →→→ outbound relay (optional)
+-----------+
↑ 587 (STARTTLS) | 465 (TLS)
| |
CLIENTS -----------------+
\----→ dovecot →→ IMAP 993 / POP SSL 995
chasquid → dovecot-auth → 用户认证
```
# Mail Stack: Chasquid + Dovecot + Certbot
This stack provides:
- SMTP (25)
- Submission (587)
- SMTPS (465)
- IMAPS (993)
Certbot (TLS) and nginx (ACME validation) use **official images**.
Certbot (TLS) and nginx (ACME validation) use **official images**.
## Start
docker compose up -d
## Initialize user:
docker exec chasquid chasquid-util domain-add svc.plus
docker exec chasquid chasquid-util user-add admin@svc.plus

View File

@ -0,0 +1,14 @@
FROM alpine:3.20
RUN apk add --no-cache chasquid bash ca-certificates tzdata openssl shadow
WORKDIR /chasquid
COPY config/ /etc/chasquid-tmpl/
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 25 465 587
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,11 @@
hostname = "{{MAIL_HOSTNAME}}"
submission_address = ":587"
smtps_address = ":465"
dovecot_auth = true
tls {
cert_file = "/etc/chasquid/certs/fullchain.pem"
key_file = "/etc/chasquid/certs/privkey.pem"
}

View File

@ -0,0 +1,22 @@
#!/bin/bash
set -e
MAIL_HOSTNAME=${MAIL_HOSTNAME:-smtp.svc.plus}
CERT_DIR="/etc/letsencrypt/live/$MAIL_HOSTNAME"
CERT_DST="/etc/chasquid/certs"
mkdir -p $CERT_DST
while [[ ! -f "$CERT_DIR/fullchain.pem" ]]; do
echo "[chasquid] Waiting for TLS cert..."
sleep 3
done
ln -sf $CERT_DIR/fullchain.pem $CERT_DST/fullchain.pem
ln -sf $CERT_DIR/privkey.pem $CERT_DST/privkey.pem
chmod 640 $CERT_DST/* || true
envsubst < /etc/chasquid-tmpl/chasquid.conf.tmpl > /etc/chasquid/chasquid.conf
echo "[chasquid] Starting..."
exec chasquid

View File

@ -0,0 +1,50 @@
version: "3.9"
services:
nginx:
image: nginx:alpine
volumes:
- ./certbot/www:/var/www/certbot
- letsencrypt:/etc/letsencrypt
- ./nginx-default.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
restart: unless-stopped
certbot:
image: certbot/certbot:latest
command: certonly --webroot -w /var/www/certbot \
-d smtp.svc.plus \
--non-interactive --agree-tos \
-m admin@svc.plus
volumes:
- ./certbot/www:/var/www/certbot
- letsencrypt:/etc/letsencrypt
depends_on:
- nginx
chasquid:
build: ./chasquid
environment:
MAIL_HOSTNAME: smtp.svc.plus
volumes:
- letsencrypt:/etc/letsencrypt
ports:
- "25:25"
- "465:465"
- "587:587"
restart: unless-stopped
dovecot:
build: ./dovecot
environment:
MAIL_HOSTNAME: smtp.svc.plus
volumes:
- letsencrypt:/etc/letsencrypt
ports:
- "993:993"
restart: unless-stopped
volumes:
letsencrypt:

View File

@ -0,0 +1,16 @@
FROM alpine:3.20
RUN apk add --no-cache \
dovecot dovecot-lmtpd dovecot-pigeonhole-plugin \
bash ca-certificates tzdata openssl
WORKDIR /dovecot
COPY config/ /etc/dovecot-tmpl/
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 993
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,3 @@
protocol imap {
mail_plugins = $mail_plugins
}

View File

@ -0,0 +1,8 @@
protocols = imap pop3
ssl = required
ssl_cert = </etc/letsencrypt/live/{{MAIL_HOSTNAME}}/fullchain.pem
ssl_key = </etc/letsencrypt/live/{{MAIL_HOSTNAME}}/privkey.pem
auth_mechanisms = plain login
disable_plaintext_auth = yes

View File

@ -0,0 +1,14 @@
service auth {
unix_listener auth-userdb {
mode = 0660
user = chasquid
group = chasquid
}
}
service imap-login {
inet_listener imaps {
port = 993
ssl = yes
}
}

View File

@ -0,0 +1,17 @@
#!/bin/bash
set -e
MAIL_HOSTNAME=${MAIL_HOSTNAME:-smtp.svc.plus}
CERT_DIR="/etc/letsencrypt/live/$MAIL_HOSTNAME"
while [[ ! -f "$CERT_DIR/fullchain.pem" ]]; do
echo "[dovecot] Waiting for TLS cert..."
sleep 3
done
envsubst < /etc/dovecot-tmpl/dovecot.conf.tmpl > /etc/dovecot/dovecot.conf
envsubst < /etc/dovecot-tmpl/local.conf.tmpl > /etc/dovecot/local.conf
envsubst < /etc/dovecot-tmpl/10-master.conf.tmpl > /etc/dovecot/conf.d/10-master.conf
echo "[dovecot] Starting..."
exec dovecot -F