diff --git a/basic_setup/awsiam.sh b/basic_setup/legacy/awsiam.sh similarity index 100% rename from basic_setup/awsiam.sh rename to basic_setup/legacy/awsiam.sh diff --git a/basic_setup/cloudflareDns.sh b/basic_setup/legacy/cloudflareDns.sh similarity index 100% rename from basic_setup/cloudflareDns.sh rename to basic_setup/legacy/cloudflareDns.sh diff --git a/basic_setup/email-rule.sh b/basic_setup/legacy/email-rule.sh similarity index 100% rename from basic_setup/email-rule.sh rename to basic_setup/legacy/email-rule.sh diff --git a/basic_setup/requeue_email.sh b/basic_setup/legacy/requeue_email.sh similarity index 100% rename from basic_setup/requeue_email.sh rename to basic_setup/legacy/requeue_email.sh diff --git a/basic_setup/s3-retention.sh b/basic_setup/legacy/s3-retention.sh similarity index 100% rename from basic_setup/s3-retention.sh rename to basic_setup/legacy/s3-retention.sh diff --git a/basic_setup/sync-s3-tags.sh b/basic_setup/legacy/sync-s3-tags.sh similarity index 100% rename from basic_setup/sync-s3-tags.sh rename to basic_setup/legacy/sync-s3-tags.sh diff --git a/basic_setup/test_migration_email.sh b/basic_setup/legacy/test_migration_email.sh similarity index 100% rename from basic_setup/test_migration_email.sh rename to basic_setup/legacy/test_migration_email.sh diff --git a/basic_setup/mailadminDns.sh b/basic_setup/mailadminDns.sh new file mode 100755 index 0000000..e3d93d9 --- /dev/null +++ b/basic_setup/mailadminDns.sh @@ -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. +# MAILADMIN_TARGET CNAME-Ziel, Default: "mail." +# 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 "============================================================" \ No newline at end of file