Files

116 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
WM_DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=common.sh
source "$WM_DEPLOY_DIR/scripts/common.sh"
wm_load_env
wm_assert_data_mount
if [[ "$(id -u)" -ne 0 ]]; then
wm_die "Dieses Skript muss als root ausgeführt werden."
fi
domain="${WATERMAPS_DOMAIN:-}"
email="${WATERMAPS_ACME_EMAIL:-}"
expected_ipv4="${1:-${WATERMAPS_EXPECTED_IPV4:-}}"
[[ "$domain" =~ ^([A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$ ]] ||
wm_die "Ungültiger WATERMAPS_DOMAIN: $domain"
[[ "$email" == *@*.* && "$email" != "admin@example.com" ]] ||
wm_die "Bitte WATERMAPS_ACME_EMAIL in deploy/.env.production konfigurieren."
[[ "$expected_ipv4" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] ||
wm_die "Erwartete Server-IPv4 fehlt. Als Argument übergeben oder WATERMAPS_EXPECTED_IPV4 setzen."
wm_assert_route_data
wm_wait_for_health watermaps 120
wm_wait_for_health nginx 60
wm_smoke_test_route
mapfile -t resolved_ipv4s < <(dig +short A "$domain" | awk '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/')
[[ "${#resolved_ipv4s[@]}" -gt 0 ]] || wm_die "Für $domain ist noch kein A-Record auflösbar."
for resolved_ipv4 in "${resolved_ipv4s[@]}"; do
[[ "$resolved_ipv4" == "$expected_ipv4" ]] ||
wm_die "$domain zeigt zusätzlich/abweichend auf $resolved_ipv4 statt ausschließlich auf $expected_ipv4."
done
challenge_name="watermaps-preflight-$$"
challenge_dir="$WATERMAPS_DATA_DIR/certbot/www/.well-known/acme-challenge"
challenge_file="$challenge_dir/$challenge_name"
install -d -m 0755 "$challenge_dir"
printf 'watermaps-acme-preflight\n' >"$challenge_file"
trap 'rm -f "$challenge_file"' EXIT
curl --fail --silent --show-error \
--header "Host: $domain" \
"http://127.0.0.1/.well-known/acme-challenge/$challenge_name" \
| grep -qx 'watermaps-acme-preflight' ||
wm_die "Nginx stellt den ACME-Webroot nicht korrekt bereit."
certbot_args=(
certonly
--webroot
--webroot-path /var/www/certbot
--domain "$domain"
--email "$email"
--agree-tos
--non-interactive
--keep-until-expiring
)
cert_name="$domain"
if [[ "${WATERMAPS_CERTBOT_STAGING:-false}" == "true" ]]; then
cert_name="${domain}-staging"
certbot_args+=(--staging)
fi
certbot_args+=(--cert-name "$cert_name")
wm_log "Let's-Encrypt-Zertifikat wird angefordert."
wm_compose --profile maintenance run --rm certbot "${certbot_args[@]}"
certificate_path="$WATERMAPS_DATA_DIR/certbot/letsencrypt/live/$cert_name/fullchain.pem"
private_key_path="$WATERMAPS_DATA_DIR/certbot/letsencrypt/live/$cert_name/privkey.pem"
[[ -s "$certificate_path" && -s "$private_key_path" ]] ||
wm_die "Certbot war beendet, aber Zertifikat oder privater Schlüssel fehlen."
candidate="$(mktemp "$WATERMAPS_RUNTIME_DIR/nginx/conf.d/.https.XXXXXX")"
trap 'rm -f "$challenge_file" "$candidate"' EXIT
sed \
-e "s/__WATERMAPS_DOMAIN__/$domain/g" \
-e "s/__WATERMAPS_CERT_NAME__/$cert_name/g" \
"$WM_DEPLOY_DIR/nginx/https.conf.template" \
>"$candidate"
wm_compose run --rm --no-deps \
--volume "$candidate:/etc/nginx/conf.d/default.conf:ro" \
nginx nginx -t
active_config="$WATERMAPS_RUNTIME_DIR/nginx/conf.d/default.conf"
previous_config="$WATERMAPS_RUNTIME_DIR/nginx/conf.d/.default.conf.previous"
cp --preserve=mode,timestamps "$active_config" "$previous_config"
install -m 0644 "$candidate" "$active_config"
if ! wm_compose exec --no-TTY nginx nginx -t; then
install -m 0644 "$previous_config" "$active_config"
wm_compose exec --no-TTY nginx nginx -s reload || true
wm_die "HTTPS-Konfiguration war ungültig; Bootstrap-Konfiguration wurde wiederhergestellt."
fi
wm_compose exec --no-TTY nginx nginx -s reload
https_curl_args=(--fail --silent --show-error)
if [[ "${WATERMAPS_CERTBOT_STAGING:-false}" == "true" ]]; then
https_curl_args+=(--insecure)
fi
if ! curl "${https_curl_args[@]}" \
--resolve "$domain:443:$expected_ipv4" \
"https://$domain/health" \
>/dev/null; then
install -m 0644 "$previous_config" "$active_config"
wm_compose exec --no-TTY nginx nginx -t
wm_compose exec --no-TTY nginx nginx -s reload
wm_die "HTTPS-Smoke-Test fehlgeschlagen; vorherige Nginx-Konfiguration wurde wiederhergestellt."
fi
wm_log "Livegang erfolgreich: https://$domain"