diff --git a/DMS/setup-dms-tls.sh b/DMS/setup-dms-tls.sh index d6be340..f721c83 100755 --- a/DMS/setup-dms-tls.sh +++ b/DMS/setup-dms-tls.sh @@ -6,6 +6,7 @@ # Liest Domains aus dem laufenden DMS und erstellt: # - docker-data/dms/config/dovecot-sni.cf # - docker-data/dms/config/postfix-main.cf +# - docker-data/dms/config/postfix-sni.map (NEU für Postfix SNI) # # Cert-Konvention (Caddy Wildcard): # Caddy speichert *.domain.tld unter: wildcard_.domain.tld/wildcard_.domain.tld.crt @@ -53,7 +54,6 @@ echo " Gefundene Domains:" for d in $DOMAINS; do echo " - $d"; done # --- Cert-Pfad Hilfsfunktionen --- -# Caddy speichert Wildcard-Certs unter: wildcard_.domain.tld/wildcard_.domain.tld.crt wildcard_cert_path() { echo "$CERTS_BASE_PATH/wildcard_.${1}/wildcard_.${1}.crt" } @@ -76,13 +76,14 @@ for domain in $DOMAINS; do DOMAINS_OK="$DOMAINS_OK $domain" else echo " ⚠️ $domain → KEIN Cert unter $CERT_PATH" - echo " → update-caddy-certs.sh ausführen + caddy reload!" + echo " → update-caddy-certs.sh ausführen + caddy reload!" DOMAINS_MISSING="$DOMAINS_MISSING $domain" fi done # Node-Hostname Cert prüfen (direktes Cert, kein Wildcard) NODE_CERT_PATH="$CERTS_BASE_PATH/$NODE_HOSTNAME/$NODE_HOSTNAME.crt" +NODE_KEY_PATH="$CERTS_BASE_PATH/$NODE_HOSTNAME/$NODE_HOSTNAME.key" if docker exec "$DMS_CONTAINER" test -f "$NODE_CERT_PATH" 2>/dev/null; then echo " ✅ $NODE_HOSTNAME → Cert vorhanden (Node Default)" else @@ -113,13 +114,6 @@ cat > "$DOVECOT_CFG" << 'HEADER' # SNI-basierte Zertifikat-Auswahl für Dovecot (IMAP/POP3). # Dovecot liest dieses File über den Volume-Mount in /tmp/docker-mailserver/ # und wendet es automatisch an. -# -# Caddy Wildcard-Cert Pfad-Schema: -# wildcard_.domain.tld/wildcard_.domain.tld.crt|.key -# -# Volume-Mount in docker-compose.yml: -# - ./docker-data/dms/config/dovecot-sni.cf:/tmp/docker-mailserver/dovecot-sni.cf:ro - HEADER for domain in $DOMAINS_OK; do @@ -149,56 +143,49 @@ EOF done echo " ✅ Dovecot SNI: $(echo $DOMAINS_OK | wc -w) Domain(s)" -echo "" -echo " --- dovecot-sni.cf Inhalt ---" -cat "$DOVECOT_CFG" -echo " --- Ende ---" # ================================================================ -# POSTFIX SNI Konfiguration +# POSTFIX SNI Konfiguration (Neu geschrieben für echte SNI Maps) # ================================================================ POSTFIX_CFG="$CONFIG_DIR/postfix-main.cf" +POSTFIX_MAP="$CONFIG_DIR/postfix-sni.map" echo "" -echo "📝 Generiere: $POSTFIX_CFG" +echo "📝 Generiere: $POSTFIX_CFG und $POSTFIX_MAP" if [ -f "$POSTFIX_CFG" ]; then cp "$POSTFIX_CFG" "${POSTFIX_CFG}.bak.$(date +%Y%m%d%H%M%S)" - echo " ℹ️ Backup: ${POSTFIX_CFG}.bak.*" fi -# smtpd_tls_chain_files: Key + Cert Paar pro Domain -# Postfix wählt automatisch per SNI das passende Paar -CHAIN_LINES="" +# 1. postfix-main.cf erstellen +cat > "$POSTFIX_CFG" << POSTFIX_EOF +# postfix-main.cf - Automatisch generiert von setup-dms-tls.sh +# +# 1. Fallback-Zertifikat (Wird genutzt, wenn kein SNI-Match gefunden wird) +smtpd_tls_chain_files = ${NODE_KEY_PATH}, ${NODE_CERT_PATH} + +# 2. SNI-Mapping aktivieren +# Wir nutzen 'texthash', damit Postfix die Map direkt lesen kann, +# ohne dass 'postmap' ausgeführt werden muss! +tls_server_sni_maps = texthash:/tmp/docker-mailserver/postfix-sni.map +POSTFIX_EOF + +# 2. postfix-sni.map erstellen +echo "# postfix-sni.map - Automatisch generiert (Format: host key_pfad cert_pfad)" > "$POSTFIX_MAP" + for domain in $DOMAINS_OK; do KEY_PATH=$(wildcard_key_path "$domain") CERT_PATH=$(wildcard_cert_path "$domain") - if [ -z "$CHAIN_LINES" ]; then - CHAIN_LINES=" $KEY_PATH, $CERT_PATH" - else - CHAIN_LINES="$CHAIN_LINES,\n $KEY_PATH, $CERT_PATH" - fi + + cat >> "$POSTFIX_MAP" << EOF +mail.${domain} ${KEY_PATH} ${CERT_PATH} +smtp.${domain} ${KEY_PATH} ${CERT_PATH} +imap.${domain} ${KEY_PATH} ${CERT_PATH} +pop.${domain} ${KEY_PATH} ${CERT_PATH} +${domain} ${KEY_PATH} ${CERT_PATH} +EOF done -cat > "$POSTFIX_CFG" << POSTFIX_EOF -# postfix-main.cf - Automatisch generiert von setup-dms-tls.sh -# Postfix SNI-Konfiguration: pro Kundendomain ein Key/Cert-Paar. -# Postfix wählt beim TLS-Handshake das passende Paar per SNI. -# DMS lädt dieses File automatisch beim Start. -# -# Caddy Wildcard-Cert Pfad-Schema: -# wildcard_.domain.tld/wildcard_.domain.tld.crt|.key - -# TLS Chain: Key + Cert Paare (Postfix >= 3.4) -smtpd_tls_chain_files = -$(printf '%b' "$CHAIN_LINES") - -POSTFIX_EOF - -echo " ✅ Postfix SNI: $(echo $DOMAINS_OK | wc -w) Domain(s)" -echo "" -echo " --- postfix-main.cf Inhalt ---" -cat "$POSTFIX_CFG" -echo " --- Ende ---" +echo " ✅ Postfix SNI: $(echo $DOMAINS_OK | wc -w) Domain(s) konfiguriert" # ================================================================ # Zusammenfassung @@ -207,20 +194,14 @@ echo "" echo "============================================================" echo "✅ Konfigurationen generiert." echo "" +echo "🔄 Lade Postfix und Dovecot neu (ohne Downtime)..." +docker exec "$DMS_CONTAINER" postfix reload || echo "⚠️ Postfix Reload fehlgeschlagen" +docker exec "$DMS_CONTAINER" dovecot reload || echo "⚠️ Dovecot Reload fehlgeschlagen" +echo "" echo "📋 Nächste Schritte:" echo "" -echo "1. DMS neu starten:" -echo " docker compose restart mailserver" -echo "" -echo "2. TLS testen (SNI):" +echo "1. TLS testen (SNI):" for domain in $DOMAINS_OK; do echo " openssl s_client -connect mail.$domain:993 -servername mail.$domain 2>/dev/null | grep 'subject\|issuer'" done -echo "" -echo "3. Bei neuen Domains:" -echo " a) Accounts anlegen: ./manage_mail_user.sh add user@newdomain.com PW" -echo " b) Im Caddy-Dir: ./update-caddy-certs.sh && docker exec caddy caddy reload ..." -echo " c) Warten bis Cert generiert (~30s)" -echo " d) Dieses Script erneut ausführen" -echo " e) docker compose restart mailserver" echo "============================================================" \ No newline at end of file diff --git a/DMS/update_dms_config.sh b/DMS/update_dms_config.sh deleted file mode 100644 index 5be8c50..0000000 --- a/DMS/update_dms_config.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# setup-dms-tls.sh -# Generiert SNI-Konfigurationen für Dovecot und Postfix anhand der DMS-Accounts. -# -# Vorbereitung: -# Stelle sicher, dass dieses Skript ausführbar ist: chmod +x setup-dms-tls.sh - -set -e - -DMS_CONTAINER=${DMS_CONTAINER:-"mailserver"} -CONFIG_DIR="./docker-data/dms/config" -NODE_HOSTNAME=${NODE_HOSTNAME:-"node1.email-srvr.com"} - -# Zieldateien im Config-Verzeichnis (werden in den Container gemountet) -DOVECOT_SNI_FILE="$CONFIG_DIR/dovecot-sni.cf" -POSTFIX_MAIN_FILE="$CONFIG_DIR/postfix-main.cf" -POSTFIX_SNI_FILE="$CONFIG_DIR/postfix-sni.map" - -echo "============================================================" -echo " 🔐 DMS SNI-Config Generator (Postfix & Dovecot)" -echo " DMS Container: $DMS_CONTAINER" -echo " Node Hostname: $NODE_HOSTNAME" -echo "============================================================" - -# Sicherstellen, dass das Config-Verzeichnis existiert -mkdir -p "$CONFIG_DIR" - -# --- Domains aus DMS lesen --- -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 DMS-Accounts gefunden." - # Wir erstellen trotzdem leere/Basis-Dateien, damit Postfix nicht abstürzt -fi - -# ========================================== -# 1. Postfix Main Config (postfix-main.cf) -# ========================================== -echo "📝 Erstelle $POSTFIX_MAIN_FILE ..." -cat < "$POSTFIX_MAIN_FILE" -# postfix-main.cf - Automatisch generiert von setup-dms-tls.sh -# -# 1. Fallback-Zertifikat (Wird genutzt, wenn kein SNI-Match gefunden wird) -smtpd_tls_chain_files = /etc/mail/certs/${NODE_HOSTNAME}/${NODE_HOSTNAME}.key, /etc/mail/certs/${NODE_HOSTNAME}/${NODE_HOSTNAME}.crt - -# 2. SNI-Mapping aktivieren -# Wir nutzen 'texthash', damit Postfix die Klartext-Map direkt lesen kann, -# ohne dass 'postmap' im Container ausgeführt werden muss! -tls_server_sni_maps = texthash:/tmp/docker-mailserver/postfix-sni.map -EOF - -# ========================================== -# 2. Dovecot & Postfix SNI Maps initialisieren -# ========================================== -echo "📝 Initialisiere Map-Dateien..." -echo "# dovecot-sni.cf - Automatisch generiert" > "$DOVECOT_SNI_FILE" -echo "# postfix-sni.map - Automatisch generiert (Format: domain key_pfad cert_pfad)" > "$POSTFIX_SNI_FILE" - -# ========================================== -# 3. Schleife über alle Kundendomains -# ========================================== -for domain in $DOMAINS; do - echo " -> Füge SNI-Regeln für $domain hinzu..." - - # Pfade, wie Caddy sie für Wildcards anlegt (wildcard_.domain.tld) - CERT_DIR="wildcard_.${domain}" - CERT_KEY="/etc/mail/certs/${CERT_DIR}/${CERT_DIR}.key" - CERT_CRT="/etc/mail/certs/${CERT_DIR}/${CERT_DIR}.crt" - - # --- Dovecot Block --- - cat <> "$DOVECOT_SNI_FILE" - -# --- $domain --- -local_name mail.${domain} { - ssl_cert = <${CERT_CRT} - ssl_key = <${CERT_KEY} -} -local_name imap.${domain} { - ssl_cert = <${CERT_CRT} - ssl_key = <${CERT_KEY} -} -local_name smtp.${domain} { - ssl_cert = <${CERT_CRT} - ssl_key = <${CERT_KEY} -} -local_name pop.${domain} { - ssl_cert = <${CERT_CRT} - ssl_key = <${CERT_KEY} -} -local_name ${domain} { - ssl_cert = <${CERT_CRT} - ssl_key = <${CERT_KEY} -} -EOF - - # --- Postfix Map Einträge --- - # Bei Postfix SNI Maps müssen Key und Cert in einer Zeile hinter dem Hostnamen stehen - cat <> "$POSTFIX_SNI_FILE" -mail.${domain} ${CERT_KEY} ${CERT_CRT} -smtp.${domain} ${CERT_KEY} ${CERT_CRT} -imap.${domain} ${CERT_KEY} ${CERT_CRT} -pop.${domain} ${CERT_KEY} ${CERT_CRT} -${domain} ${CERT_KEY} ${CERT_CRT} -EOF - -done - -echo "" -echo "✅ Alle Konfigurationsdateien erfolgreich generiert!" - -# ========================================== -# 4. Dienste im Container neu laden -# ========================================== -echo "🔄 Lade Postfix und Dovecot neu (ohne Downtime)..." -docker exec "$DMS_CONTAINER" postfix reload || echo "⚠️ Postfix Reload fehlgeschlagen (Container läuft nicht?)" -docker exec "$DMS_CONTAINER" dovecot reload || echo "⚠️ Dovecot Reload fehlgeschlagen" - -echo "============================================================" -echo "🎉 Fertig!" \ No newline at end of file