This commit is contained in:
2026-05-21 14:37:33 -05:00
parent 649a55eecd
commit 4422fba707
8 changed files with 158 additions and 0 deletions

158
basic_setup/mailadminDns.sh Executable file
View File

@@ -0,0 +1,158 @@
#!/bin/bash
# mailadminDns.sh
# ------------------------------------------------------------------
# Setzt AUSSCHLIESSLICH den DNS-Record fuer den mailadmin-Zugang.
# Faesst NICHTS anderes an (kein SES, SPF, DKIM, MX, keine anderen
# Subdomains). Kann gefahrlos auf bereits migrierten Domains laufen.
#
# Verwendet dieselbe ensure_record-Logik wie cloudflareMigrationDns.sh,
# damit das Verhalten (Create/Update/Skip-bei-identisch) identisch ist.
#
# ------------------------------------------------------------------
# PFLICHT-VARIABLEN:
# DOMAIN_NAME Kundendomain, z.B. innungsapp.com
# CF_API_TOKEN Cloudflare API Token
#
# OPTIONALE VARIABLEN:
# MAILADMIN_HOST Subdomain-Label, Default: "mailadmin"
# -> ergibt mailadmin.<DOMAIN_NAME>
# MAILADMIN_TARGET CNAME-Ziel, Default: "mail.<DOMAIN_NAME>"
# Beispiele:
# mail.innungsapp.com (pro-Domain Modell)
# mailadmin.bayarea-cc.com (zentrales Modell)
# DRY_RUN "true" -> zeigt nur an, aendert nichts
#
# ------------------------------------------------------------------
# BEISPIELE:
#
# # Standard: mailadmin.innungsapp.com -> mail.innungsapp.com
# DOMAIN_NAME=innungsapp.com CF_API_TOKEN=xxx ./mailadminDns.sh
#
# # Zentrales Modell: mailadmin.innungsapp.com -> mailadmin.bayarea-cc.com
# DOMAIN_NAME=innungsapp.com \
# MAILADMIN_TARGET=mailadmin.bayarea-cc.com \
# CF_API_TOKEN=xxx ./mailadminDns.sh
#
# # Erst testen ohne zu aendern
# DOMAIN_NAME=innungsapp.com CF_API_TOKEN=xxx DRY_RUN=true ./mailadminDns.sh
#
# ------------------------------------------------------------------
set -e
# --- KONFIGURATION ---
DRY_RUN=${DRY_RUN:-"false"}
MAILADMIN_HOST=${MAILADMIN_HOST:-"mailadmin"}
MAILADMIN_TARGET=${MAILADMIN_TARGET:-"mail.${DOMAIN_NAME}"}
# --- CHECKS ---
if [ -z "$DOMAIN_NAME" ]; then echo "❌ Fehler: DOMAIN_NAME fehlt."; exit 1; fi
if [ -z "$CF_API_TOKEN" ]; then echo "❌ Fehler: CF_API_TOKEN fehlt."; exit 1; fi
if ! command -v jq &> /dev/null; then echo "❌ Fehler: 'jq' fehlt."; exit 1; fi
if ! command -v curl &> /dev/null; then echo "❌ Fehler: 'curl' fehlt."; exit 1; fi
RECORD_NAME="${MAILADMIN_HOST}.${DOMAIN_NAME}"
echo "============================================================"
echo " 🔧 mailadmin DNS Setup"
echo " 🌐 Domain: $DOMAIN_NAME"
echo " 📍 Record: CNAME $RECORD_NAME$MAILADMIN_TARGET"
[ "$DRY_RUN" = "true" ] && echo " ⚠️ DRY RUN MODE - Keine Änderungen!"
echo "============================================================"
# Schutz: CNAME auf sich selbst macht keinen Sinn
if [ "$RECORD_NAME" == "$MAILADMIN_TARGET" ]; then
echo "❌ Fehler: CNAME-Ziel ist identisch mit dem Record-Namen."
echo " $RECORD_NAME kann nicht auf sich selbst zeigen."
echo " Setze MAILADMIN_TARGET auf einen anderen Host."
exit 1
fi
# 1. ZONE ID HOLEN
echo "🔍 Suche Cloudflare Zone ID..."
ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN_NAME" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" | jq -r '.result[0].id')
if [ "$ZONE_ID" == "null" ] || [ -z "$ZONE_ID" ]; then
echo "❌ Zone nicht gefunden für $DOMAIN_NAME."
exit 1
fi
echo " ✅ Zone ID: $ZONE_ID"
# ------------------------------------------------------------------
# FUNKTION: ensure_record
# Identisch zur Logik in cloudflareMigrationDns.sh, reduziert auf
# die Typen die wir hier brauchen (CNAME).
# ------------------------------------------------------------------
ensure_record() {
local type=$1
local name=$2
local content=$3
local proxied=${4:-false}
echo " ⚙️ Prüfe $type $name..."
local search_res=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=$type&name=$name" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json")
local rec_id=$(echo "$search_res" | jq -r '.result[0].id')
local rec_content=$(echo "$search_res" | jq -r '.result[0].content')
[ -z "$rec_id" ] && rec_id="null"
[ -z "$rec_content" ] && rec_content="null"
local json_data=$(jq -n --arg t "$type" --arg n "$name" --arg c "$content" --argjson p "$proxied" \
'{type: $t, name: $n, content: $c, ttl: 3600, proxied: $p}')
if [ "$rec_id" == "null" ]; then
if [ "$DRY_RUN" = "true" ]; then
echo " [DRY] Würde ERSTELLEN: $type $name$content"
else
local res=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" --data "$json_data")
if [ "$(echo $res | jq -r .success)" == "true" ]; then
echo " ✅ Erstellt: $type $name$content"
else
echo " ❌ Fehler beim Erstellen: $(echo $res | jq -r '.errors[0].message')"
exit 1
fi
fi
else
if [ "$rec_content" == "$content" ]; then
echo " 🆗 Identisch ($rec_content). Überspringe."
else
if [ "$DRY_RUN" = "true" ]; then
echo " [DRY] Würde UPDATEN: '$rec_content' → '$content'"
else
local res=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$rec_id" \
-H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" --data "$json_data")
if [ "$(echo $res | jq -r .success)" == "true" ]; then
echo " ✅ Aktualisiert: '$rec_content' → '$content'"
else
echo " ❌ Fehler beim Updaten: $(echo $res | jq -r '.errors[0].message')"
exit 1
fi
fi
fi
fi
}
# ------------------------------------------------------------------
# Der eigentliche Record
# proxied=false ist hier wichtig: der mailadmin laeuft hinter Caddy
# mit eigenem TLS-Zertifikat. Cloudflare-Proxy davor wuerde die
# Zertifikatskette stoeren bzw. doppeltes TLS-Terminieren.
# ------------------------------------------------------------------
echo ""
echo "--- mailadmin CNAME ---"
ensure_record "CNAME" "$RECORD_NAME" "$MAILADMIN_TARGET" false
echo ""
echo "============================================================"
echo "✅ Fertig."
echo ""
echo " mailadmin erreichbar unter: https://$RECORD_NAME"
echo ""
echo " ⚠️ Wichtig: Caddy muss ein Zertifikat für $RECORD_NAME"
echo " ausstellen. Stelle sicher, dass der Hostname in der"
echo " Caddy-Konfiguration enthalten ist."
echo "============================================================"