#!/bin/bash # setup-dms-tls.sh # Generiert Dovecot und Postfix SNI-Konfigurationen für Multi-Domain TLS. # Liest die vorhandenen Domains aus den DMS Accounts und erstellt: # - docker-data/dms/config/dovecot-sni.cf (Dovecot SNI pro Domain) # - docker-data/dms/config/postfix-main.cf (Postfix SNI Map + TLS Chain) # # Voraussetzung: # - Caddy hat Wildcard-Certs gezogen (z.B. *.andreasknuth.de) # - Cert-Verzeichnis ist gemountet unter /etc/mail/certs im Container # - Konvention Cert-Pfad: /etc/mail/certs/DOMAIN_NAME/*.DOMAIN_NAME.crt|.key # # Usage: # DMS_CONTAINER=mailserver ./setup-dms-tls.sh # DMS_CONTAINER=mailserver DEFAULT_DOMAIN=email-srvr.com ./setup-dms-tls.sh set -e DMS_CONTAINER=${DMS_CONTAINER:-"mailserver"} CONFIG_DIR=${CONFIG_DIR:-"./docker-data/dms/config"} CERTS_BASE_PATH=${CERTS_BASE_PATH:-"/etc/mail/certs"} # Die Default-Domain für DMS hostname/domainname (bleibt email-srvr.com) DEFAULT_DOMAIN=${DEFAULT_DOMAIN:-"email-srvr.com"} echo "============================================================" echo " 🔐 DMS TLS SNI Setup (Multi-Domain)" echo " Container: $DMS_CONTAINER" echo " Config Dir: $CONFIG_DIR" echo " Certs Base: $CERTS_BASE_PATH" echo " Default Domain: $DEFAULT_DOMAIN" echo "============================================================" # --- Alle Domains aus DMS Accounts lesen --- echo "" echo "📋 Lese Domains aus DMS..." DOMAINS=$(docker exec "$DMS_CONTAINER" setup email list 2>/dev/null \ | grep -oP '(?<=@)[^\s]+' \ | sort -u) if [ -z "$DOMAINS" ]; then echo "❌ Keine Accounts im DMS gefunden!" echo " Bitte zuerst Accounts anlegen: ./manage_mail_user.sh add user@domain.com PW" exit 1 fi echo " Gefundene Domains:" for d in $DOMAINS; do echo " - $d"; done # --- Cert-Verfügbarkeit prüfen --- echo "" echo "🔍 Prüfe Zertifikat-Verfügbarkeit (im Container)..." DOMAINS_WITH_CERTS="" DOMAINS_WITHOUT_CERTS="" for domain in $DOMAINS; do # Caddy speichert Wildcard-Certs als: *.domain.tld/ # Pfad im Container (über den Volume-Mount): /etc/mail/certs/*.domain.tld/ CERT_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.crt" KEY_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.key" # Prüfe ob die Datei im Container existiert if docker exec "$DMS_CONTAINER" test -f "$CERT_PATH" 2>/dev/null; then echo " ✅ $domain → Cert gefunden" DOMAINS_WITH_CERTS="$DOMAINS_WITH_CERTS $domain" else echo " ⚠️ $domain → KEIN Cert unter $CERT_PATH" echo " Caddy-Block '*.${domain}' eintragen und Caddy neu starten!" DOMAINS_WITHOUT_CERTS="$DOMAINS_WITHOUT_CERTS $domain" fi done if [ -n "$DOMAINS_WITHOUT_CERTS" ]; then echo "" echo "⚠️ WARNUNG: Fehlende Certs für:$DOMAINS_WITHOUT_CERTS" echo " Diese Domains werden NICHT in die SNI-Configs eingetragen." echo " Bitte Certs erzeugen und Script erneut ausführen." echo "" fi if [ -z "$DOMAINS_WITH_CERTS" ]; then echo "❌ Kein einziges Zertifikat gefunden! Abbruch." exit 1 fi # ================================================================ # DOVECOT SNI Konfiguration generieren # ================================================================ DOVECOT_CFG="$CONFIG_DIR/dovecot-sni.cf" echo "" echo "📝 Generiere Dovecot SNI Konfiguration: $DOVECOT_CFG" cat > "$DOVECOT_CFG" << 'HEADER' # dovecot-sni.cf - Automatisch generiert von setup-dms-tls.sh # SNI-basierte TLS-Konfiguration für mehrere Domains. # Dovecot wählt das Zertifikat anhand des SNI-Hostnamens des Clients. # Dieses File wird via Volume-Mount in den Container eingebunden. # # Gemounteter Pfad: /tmp/docker-mailserver/dovecot-sni.cf # In DMS docker-compose.yml volumes Sektion: # - ./docker-data/dms/config/dovecot-sni.cf:/tmp/docker-mailserver/dovecot-sni.cf:ro HEADER for domain in $DOMAINS_WITH_CERTS; do CERT_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.crt" KEY_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.key" cat >> "$DOVECOT_CFG" << EOF # Domain: $domain local_name mail.$domain { ssl_cert = <$CERT_PATH ssl_key = <$KEY_PATH } local_name imap.$domain { ssl_cert = <$CERT_PATH ssl_key = <$KEY_PATH } local_name smtp.$domain { ssl_cert = <$CERT_PATH ssl_key = <$KEY_PATH } local_name pop.$domain { ssl_cert = <$CERT_PATH ssl_key = <$KEY_PATH } EOF done echo " ✅ $DOVECOT_CFG erstellt ($(echo $DOMAINS_WITH_CERTS | wc -w) Domains)" # ================================================================ # POSTFIX SNI Konfiguration generieren # ================================================================ POSTFIX_CFG="$CONFIG_DIR/postfix-main.cf" echo "" echo "📝 Generiere Postfix SNI Konfiguration: $POSTFIX_CFG" # Prüfe ob postfix-main.cf schon existiert und sichere sie if [ -f "$POSTFIX_CFG" ]; then cp "$POSTFIX_CFG" "${POSTFIX_CFG}.bak.$(date +%Y%m%d%H%M%S)" echo " ℹ️ Backup erstellt: ${POSTFIX_CFG}.bak.*" fi # TLS Chain Files für Postfix aufbauen # Postfix unterstützt smtpd_tls_chain_files mit mehreren Key/Cert Paaren CHAIN_FILES="" for domain in $DOMAINS_WITH_CERTS; do KEY_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.key" CERT_PATH="$CERTS_BASE_PATH/*.$domain/*.$domain.crt" if [ -z "$CHAIN_FILES" ]; then CHAIN_FILES=" $KEY_PATH, $CERT_PATH" else CHAIN_FILES="$CHAIN_FILES,\n $KEY_PATH, $CERT_PATH" fi done cat > "$POSTFIX_CFG" << POSTFIX_CONF # postfix-main.cf - Automatisch generiert von setup-dms-tls.sh # Postfix SNI-Konfiguration für mehrere Domains. # DMS lädt dieses File automatisch beim Start via /tmp/docker-mailserver/ # ------------------------------------------------------------------ # TLS Chain Files (Key + Cert pro Domain) # Postfix wählt das passende Paar automatisch per SNI # ------------------------------------------------------------------ smtpd_tls_chain_files = $(printf '%b' "$CHAIN_FILES") POSTFIX_CONF echo " ✅ $POSTFIX_CFG erstellt" # ================================================================ # Hinweise für docker-compose.yml # ================================================================ echo "" echo "============================================================" echo "📋 Nächste Schritte:" echo "" echo "1. Volume-Mounts in DMS docker-compose.yml hinzufügen:" echo "" echo " volumes:" echo " # Bestehend (Caddy Certs - gesamtes Verzeichnis):" echo " - /var/lib/docker/volumes/caddy_data/_data/caddy/certificates/" echo " acme-v02.api.letsencrypt.org-directory:/etc/mail/certs:ro" echo "" echo " # NEU - Dovecot SNI:" echo " - ./docker-data/dms/config/dovecot-sni.cf:/tmp/docker-mailserver/dovecot-sni.cf:ro" echo "" echo " # Postfix-main.cf wird von DMS automatisch geladen wenn sie liegt unter:" echo " - ./docker-data/dms/config/postfix-main.cf:/tmp/docker-mailserver/postfix-main.cf:ro" echo "" echo "2. DMS neu starten:" echo " docker compose restart mailserver" echo "" echo "3. TLS testen:" for domain in $DOMAINS_WITH_CERTS; do echo " openssl s_client -connect mail.$domain:993 -servername mail.$domain" done echo "============================================================"