VPS-Installer: Caddy Auto-HTTPS (Profil) + IPv4-SMTP-Pref einbauen

- caddy-Service in docker-compose (profiles: caddy) – reverse-proxyt
  webmail/admin mit automatischem Let's-Encrypt; auf dem LXC bleibt er
  aus (dort macht NPM das HTTPS)
- stack/caddy/Caddyfile (Domains via WEBMAIL_FQDN/ADMIN_FQDN aus .env)
- vps-install.sh: ENABLE_CADDY (default 1) -> --profile caddy beim Deploy,
  smtp_address_preference=ipv4 als postfix-main.cf-Override (gegen IPv6-
  'Network unreachable'-Queue-Delays), Output mit https-URLs + A-Records

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 13:35:22 +02:00
parent b5bbc1f9ae
commit f19bcc860c
3 changed files with 70 additions and 5 deletions
+13
View File
@@ -0,0 +1,13 @@
# Reverse-Proxy mit automatischem Let's-Encrypt — nur auf dem VPS aktiv
# (docker compose --profile caddy ...). Die Domains kommen aus der .env.
#
# Voraussetzung: Port 80 + 443 sind offen und WEBMAIL_FQDN / ADMIN_FQDN
# zeigen per A-Record auf diesen Server. Caddy holt/erneuert die Certs selbst.
{$WEBMAIL_FQDN} {
reverse_proxy snappymail:8888
}
{$ADMIN_FQDN} {
reverse_proxy admin-ui:80
}
+27
View File
@@ -112,3 +112,30 @@ services:
volumes: volumes:
- ./docker-data/snappymail/:/var/lib/snappymail/ # echter Datenpfad der djmaze-Image - ./docker-data/snappymail/:/var/lib/snappymail/ # echter Datenpfad der djmaze-Image
- ./snappymail-theme/:/snappymail/themes/:ro # KGVA "Shibui"-Theme - ./snappymail-theme/:/snappymail/themes/:ro # KGVA "Shibui"-Theme
# ----------------------------------------------------------------------------
# caddy Reverse-Proxy mit automatischem Let's-Encrypt (NUR auf dem VPS).
# Aktivieren via Profil: docker compose --profile caddy up -d
# Auf dem LXC bleibt er AUS (dort macht der Nginx Proxy Manager das HTTPS).
# Domains kommen aus der .env (WEBMAIL_FQDN / ADMIN_FQDN); Caddy holt sich
# die Zertifikate selbst (Port 80/443 müssen offen sein).
# ----------------------------------------------------------------------------
caddy:
image: caddy:2-alpine
container_name: dms-caddy
profiles: ["caddy"]
restart: always
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
environment:
- WEBMAIL_FQDN=${WEBMAIL_FQDN}
- ADMIN_FQDN=${ADMIN_FQDN}
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- ./docker-data/caddy/:/data/
depends_on:
- snappymail
- admin-ui
+30 -5
View File
@@ -32,6 +32,7 @@ RSPAMD_PORT="${RSPAMD_PORT:-11334}"
TIMEZONE="${TZ:-Europe/Zurich}" TIMEZONE="${TZ:-Europe/Zurich}"
ENABLE_CLAMAV="${ENABLE_CLAMAV:-0}" ENABLE_CLAMAV="${ENABLE_CLAMAV:-0}"
ENABLE_FAIL2BAN="${ENABLE_FAIL2BAN:-1}" ENABLE_FAIL2BAN="${ENABLE_FAIL2BAN:-1}"
ENABLE_CADDY="${ENABLE_CADDY:-1}" # VPS: Auto-HTTPS-Reverse-Proxy für Webmail/Admin (Port 80/443)
DMS_IMAGE="${DMS_IMAGE:-ghcr.io/docker-mailserver/docker-mailserver:latest}" DMS_IMAGE="${DMS_IMAGE:-ghcr.io/docker-mailserver/docker-mailserver:latest}"
DEPLOY_DIR="${DEPLOY_DIR:-/opt/dms-stack}" DEPLOY_DIR="${DEPLOY_DIR:-/opt/dms-stack}"
REPO_ARCHIVE="${REPO_ARCHIVE:-https://git.kgva.ch/karim/DOCKERMAILSERVER-LXC/archive/main.tar.gz}" REPO_ARCHIVE="${REPO_ARCHIVE:-https://git.kgva.ch/karim/DOCKERMAILSERVER-LXC/archive/main.tar.gz}"
@@ -169,6 +170,12 @@ password = "${RSPAMD_PASSWORD}";
enable_password = "${RSPAMD_PASSWORD}"; enable_password = "${RSPAMD_PASSWORD}";
EOF EOF
# IPv4 für ausgehenden SMTP bevorzugen (viele VPS haben keine saubere IPv6-Route
# -> sonst "Network is unreachable"-Verzögerungen in der Queue). DMS liest postfix-main.cf.
mkdir -p "$DEPLOY_DIR/docker-data/dms/config"
grep -q 'smtp_address_preference' "$DEPLOY_DIR/docker-data/dms/config/postfix-main.cf" 2>/dev/null || \
echo 'smtp_address_preference = ipv4' >> "$DEPLOY_DIR/docker-data/dms/config/postfix-main.cf"
# Self-signed-Cert + erstes Postfach VOR dem Start (sonst bricht DMS ab) # Self-signed-Cert + erstes Postfach VOR dem Start (sonst bricht DMS ab)
msg_info "Erzeuge Self-signed-Zertifikat + erstes Postfach ..." msg_info "Erzeuge Self-signed-Zertifikat + erstes Postfach ..."
mkdir -p "$DEPLOY_DIR/docker-data/certs" "$DEPLOY_DIR/docker-data/dms/config" mkdir -p "$DEPLOY_DIR/docker-data/certs" "$DEPLOY_DIR/docker-data/dms/config"
@@ -186,7 +193,12 @@ grep -q "^${FIRST_EMAIL}|" "$DEPLOY_DIR/docker-data/dms/config/postfix-accounts.
# Stack starten + DKIM + SnappyMail # Stack starten + DKIM + SnappyMail
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
msg_info "Baue & starte Stack (kann ein paar Minuten dauern) ..." msg_info "Baue & starte Stack (kann ein paar Minuten dauern) ..."
( cd "$DEPLOY_DIR" && docker compose up -d --build ) COMPOSE_PROFILES=()
if [[ "$ENABLE_CADDY" == "1" ]]; then
mkdir -p "$DEPLOY_DIR/docker-data/caddy"
COMPOSE_PROFILES=(--profile caddy)
fi
( cd "$DEPLOY_DIR" && docker compose "${COMPOSE_PROFILES[@]}" up -d --build )
msg_info "Warte auf Mailserver ..." msg_info "Warte auf Mailserver ..."
for i in $(seq 1 60); do for i in $(seq 1 60); do
@@ -215,6 +227,16 @@ fi
PUB_IP="$(curl -fsSL https://ipv4.icanhazip.com 2>/dev/null || hostname -I | awk '{print $1}')" PUB_IP="$(curl -fsSL https://ipv4.icanhazip.com 2>/dev/null || hostname -I | awk '{print $1}')"
if [[ "$ENABLE_CADDY" == "1" ]]; then
WEBMAIL_URL="https://${WEBMAIL_FQDN}"
ADMIN_URL="https://${ADMIN_FQDN}"
PROXY_NOTE="Caddy (Auto-HTTPS) aktiv — Webmail/Admin laufen über 443, Zertifikate kommen automatisch (Port 80/443 offen + A-Records nötig)."
else
WEBMAIL_URL="http://${PUB_IP:-<ip>}:${WEBMAIL_PORT}"
ADMIN_URL="http://${PUB_IP:-<ip>}:${ADMIN_PORT}"
PROXY_NOTE="Kein Reverse-Proxy aktiv — Webmail/Admin nur via IP:Port (oder eigenen Proxy davorhängen)."
fi
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Abschluss # Abschluss
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -227,14 +249,17 @@ ${GN}╔════════════════════════
Server-IP .......... ${PUB_IP:-?} Server-IP .......... ${PUB_IP:-?}
Mailserver ......... $MAIL_FQDN Mailserver ......... $MAIL_FQDN
Erstes Postfach .... $FIRST_EMAIL Erstes Postfach .... $FIRST_EMAIL
Webmail ............ http://${PUB_IP:-<ip>}:${WEBMAIL_PORT} Webmail ............ ${WEBMAIL_URL}
Admin-UI ........... http://${PUB_IP:-<ip>}:${ADMIN_PORT} (Supabase-Login) Admin-UI ........... ${ADMIN_URL} (Supabase-Login)
Rspamd-UI .......... http://${PUB_IP:-<ip>}:${RSPAMD_PORT} Rspamd-UI .......... http://${PUB_IP:-<ip>}:${RSPAMD_PORT} (nur via Firewall/Tunnel)
${RD}Rspamd-Passwort:${CL} ${RSPAMD_PASSWORD} ${RD}Rspamd-Passwort:${CL} ${RSPAMD_PASSWORD}
Proxy .............. ${PROXY_NOTE}
Verwaltung ......... cd ${DEPLOY_DIR} · docker compose ps Verwaltung ......... cd ${DEPLOY_DIR} · docker compose ps
${YW}── DNS: Mailhost (einmalig) ──${CL} ${YW}── DNS: Mailhost (einmalig) ──${CL}
A ${MAIL_FQDN}. IN A ${PUB_IP:-<server-ip>} A ${MAIL_FQDN}. IN A ${PUB_IP:-<server-ip>}
A ${WEBMAIL_FQDN}. IN A ${PUB_IP:-<server-ip>} (für Caddy-HTTPS)
A ${ADMIN_FQDN}. IN A ${PUB_IP:-<server-ip>} (für Caddy-HTTPS)
PTR ${PUB_IP:-<server-ip>} -> ${MAIL_FQDN} (in der Hetzner-Console: Server → rDNS) PTR ${PUB_IP:-<server-ip>} -> ${MAIL_FQDN} (in der Hetzner-Console: Server → rDNS)
EOF EOF
for d in $MAIL_DOMAINS; do for d in $MAIL_DOMAINS; do