#!/usr/bin/env bash # Caddy installieren und Caddyfile aus der Vorlage rendern (wird von setup-lxc.sh gesourced). CADDY_KEY_URL=https://dl.cloudsmith.io/public/caddy/stable/gpg.key CADDY_KEYRING=/usr/share/keyrings/caddy-stable-archive-keyring.gpg CADDY_REPO_LIST=/etc/apt/sources.list.d/caddy-stable.list CADDY_REPO_LINE="deb [signed-by=$CADDY_KEYRING] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" CADDY_CONFIG=/etc/caddy/Caddyfile CADDY_CERT_DIR=/etc/caddy/certs CADDY_CERT_FILE=$CADDY_CERT_DIR/checkbot.crt CADDY_CERT_KEY=$CADDY_CERT_DIR/checkbot.key CADDY_GROUP=caddy CADDYFILE_TEMPLATE=$DEPLOY_DIR/Caddyfile.template CADDY_MANUAL_HINT="Manuell: https://caddyserver.com/docs/install#debian-ubuntu-raspbian ausführen, danach setup-lxc.sh erneut starten." apt_install() { DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "$@" } caddy_candidate() { apt-cache policy caddy 2>/dev/null | awk '/Candidate:/ {print $2}' } install_caddy_official_repo() { local tmp fprs fpr expected apt_install gnupg || return 1 tmp=$(mktemp) || return 1 curl -fsSL --proto '=https' --tlsv1.2 "$CADDY_KEY_URL" -o "$tmp" || { rm -f "$tmp"; return 1; } fprs=$(gpg --batch --show-keys --with-colons "$tmp" 2>/dev/null | awk -F: '$1 == "fpr" {print $10}') if [[ -z $fprs ]]; then rm -f "$tmp"; return 1; fi if [[ -n ${CHECKBOT_CADDY_KEY_FPR:-} ]]; then expected=$(printf '%s' "$CHECKBOT_CADDY_KEY_FPR" | tr -d ' ' | tr '[:lower:]' '[:upper:]') if ! grep -qx "$expected" <<<"$fprs"; then warn "Fingerabdruck des Caddy-Schlüssels stimmt nicht mit CHECKBOT_CADDY_KEY_FPR überein." rm -f "$tmp" return 1 fi else for fpr in $fprs; do log "Caddy-Repo-Schlüssel Fingerabdruck: $fpr (gegen die Caddy-Doku prüfen oder CHECKBOT_CADDY_KEY_FPR setzen)."; done fi gpg --batch --yes --dearmor -o "$CADDY_KEYRING" "$tmp" || { rm -f "$tmp"; return 1; } rm -f "$tmp" chmod 0644 "$CADDY_KEYRING" printf '%s\n' "$CADDY_REPO_LINE" > "$CADDY_REPO_LIST" apt-get update -qq || return 1 apt_install caddy || return 1 } ensure_caddy() { local candidate if command -v caddy >/dev/null 2>&1; then return 0 fi candidate=$(caddy_candidate) if [[ -n $candidate && $candidate != "(none)" ]]; then log "Installiere Caddy aus dem Distributions-Repository." apt_install caddy || die "Installation von Caddy fehlgeschlagen. $CADDY_MANUAL_HINT" return 0 fi log "Caddy ist im Distributions-Repository nicht verfügbar, richte das offizielle Caddy-Repository ein." install_caddy_official_repo || die "Caddy konnte nicht installiert werden. $CADDY_MANUAL_HINT" } install_tls_files() { local src_cert=$1 src_key=$2 install -d -m 0750 -o root -g "$CADDY_GROUP" "$CADDY_CERT_DIR" if [[ $(realpath "$src_cert") != "$(realpath -m "$CADDY_CERT_FILE")" ]]; then install -m 0644 -o root -g root "$src_cert" "$CADDY_CERT_FILE" fi if [[ $(realpath "$src_key") != "$(realpath -m "$CADDY_CERT_KEY")" ]]; then install -m 0640 -o root -g "$CADDY_GROUP" "$src_key" "$CADDY_CERT_KEY" fi } render_caddyfile() { local fqdn=$1 tls_mode=$2 monitor_ips=$3 upstream=$4 content tls_directive case $tls_mode in internal) tls_directive="tls internal" ;; files) tls_directive="tls $CADDY_CERT_FILE $CADDY_CERT_KEY" ;; *) die "Unbekannter TLS-Modus: $tls_mode" ;; esac content=$(cat "$CADDYFILE_TEMPLATE") content=${content//@@FQDN@@/$fqdn} content=${content//@@TLS_DIRECTIVE@@/$tls_directive} content=${content//@@HEALTH_IPS@@/$monitor_ips} content=${content//@@UPSTREAM@@/$upstream} if grep -q '@@' <<<"$content"; then die "Caddyfile-Vorlage enthält nicht ersetzte Platzhalter." fi printf '%s\n' "$content" } apply_caddyfile() { local rendered=$1 tmp backup="" tmp=$(mktemp) printf '%s' "$rendered" > "$tmp" if [[ -f $CADDY_CONFIG ]] && cmp -s "$tmp" "$CADDY_CONFIG"; then rm -f "$tmp" log "Caddyfile unverändert." else if [[ -f $CADDY_CONFIG ]]; then backup=$CADDY_CONFIG.bak cp -p "$CADDY_CONFIG" "$backup" fi install -m 0644 -o root -g root "$tmp" "$CADDY_CONFIG" rm -f "$tmp" fi systemctl enable caddy >/dev/null 2>&1 || true if ! systemctl reload-or-restart caddy; then if [[ -n $backup ]]; then cp -p "$backup" "$CADDY_CONFIG" fi die "Caddy konnte die neue Konfiguration nicht laden (alte Datei wiederhergestellt). journalctl -u caddy -n 50 --no-pager" fi }