From a21278eb520ab34aff5435ab22e572c32378a8b6 Mon Sep 17 00:00:00 2001 From: nexxo Date: Thu, 30 Jul 2026 23:35:13 +0200 Subject: [PATCH] Create the file the import needs, instead of writing that something else does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment in Caddyfile.example said install-agent.sh creates /etc/caddy/clupilot-proxy-hosts.conf before anything imports it. It did not. I wrote the claim and never built the thing, and the release notes repeated it as an instruction. Following that instruction would have taken the site down. An import of a missing file makes the WHOLE Caddy configuration invalid — app.clupilot.com, the portal, everything — and the operator would have been holding a step I told them to take. So the installer now does both halves itself: it creates the file, and it adds the import line, then runs `caddy validate` and takes the line straight back out if Caddy rejects it. Doing it in a script rather than in a comment is the point — an instruction gets followed in the wrong order, a script does not. And a second trap alongside it: a hostname written by hand in the Caddyfile is now skipped when the generated file is rendered. Two site blocks for one name make Caddy reject the entire configuration, so an operator who managed an already-hand-written name in the console as well would have taken the public site off the air with no visible connection between the two actions. 2037 tests pass. Co-Authored-By: Claude Opus 5 --- deploy/caddy/Caddyfile.example | 16 +++++++---- deploy/install-agent.sh | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/deploy/caddy/Caddyfile.example b/deploy/caddy/Caddyfile.example index e69f782..300d1cc 100644 --- a/deploy/caddy/Caddyfile.example +++ b/deploy/caddy/Caddyfile.example @@ -99,13 +99,19 @@ status.example.com { # sich auf den Server zu melden — der Handgriff, der `files.clupilot.com` # gekostet hat. # -# Die Datei MUSS existieren, bevor diese Zeile sie importiert: ein Import ins -# Leere macht die ganze Proxy-Konfiguration ungültig, und das nimmt die -# öffentliche Website mit. `install-agent.sh` legt sie deshalb an, bevor es -# hierauf hinweist. Wer die Zeile von Hand einträgt, legt vorher an: +# BEIDES setzt `sudo bash deploy/install-agent.sh` selbst — die Datei und die +# Import-Zeile unten. Von Hand eintragen muss man nichts, und man sollte es auch +# nicht: die Datei MUSS existieren, bevor irgendetwas sie importiert, denn ein +# Import ins Leere macht die GANZE Proxy-Konfiguration ungültig und nimmt die +# öffentliche Website mit. Eine Anleitung wird in der falschen Reihenfolge +# befolgt, ein Skript nicht. # -# sudo touch /etc/caddy/clupilot-proxy-hosts.conf +# Der Installer prüft nach dem Eintragen mit `caddy validate` und nimmt die +# Zeile wieder heraus, wenn Caddy sie ablehnt. # +# EIN NAME GEHÖRT AN EINE STELLE. Steht ein Hostname schon von Hand in dieser +# Datei, lässt die Erzeugung ihn aus — zwei Blöcke für denselben Namen lehnt +# Caddy ab, und zwar die ganze Konfiguration. import /etc/caddy/clupilot-proxy-hosts.conf # ── Dateien zum Herunterladen ──────────────────────────────────────────────── diff --git a/deploy/install-agent.sh b/deploy/install-agent.sh index abf0e32..b6808d8 100755 --- a/deploy/install-agent.sh +++ b/deploy/install-agent.sh @@ -107,6 +107,17 @@ case "${1:-}" in [[ "$NAME" =~ ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$ ]] \ || { echo "refusing hostname: $NAME" >&2; rm -f "$TMP"; exit 5; } + # Steht der Name schon von Hand im Caddyfile, wird er hier + # ausgelassen. Zwei Blöcke für denselben Hostnamen lehnt Caddy ab — + # und zwar die GANZE Konfiguration, nicht nur den doppelten Block. + # Ein Betreiber, der einen bereits eingetragenen Namen zusätzlich in + # der Konsole pflegt, nähme sich damit die öffentliche Website vom + # Netz, ohne einen Zusammenhang zu sehen. + if grep -qE "^[[:space:]]*(https?://)?${NAME//./\\.}([[:space:],{]|\$)" "$CADDYFILE"; then + echo " skipping $NAME — already written by hand in $CADDYFILE" >&2 + continue + fi + { echo "" echo "$NAME {" @@ -482,3 +493,42 @@ systemctl enable --now clupilot-update-agent.path >/dev/null systemctl start clupilot-update-agent.service || true echo "Update agent installed and running (clupilot-update-agent.timer)." + +# ── Die von der Konsole verwalteten Hostnamen ──────────────────────────────── +# Die Datei MUSS existieren, bevor irgendetwas sie importiert: ein Import ins +# Leere macht die GANZE Proxy-Konfiguration ungültig, und das nimmt die +# öffentliche Website mit. Genau diese Reihenfolge ist der Grund, warum das hier +# steht und nicht in einer Anleitung — eine Anleitung wird in der falschen +# Reihenfolge befolgt, ein Skript nicht. +PROXY_HOSTS_FILE="/etc/caddy/clupilot-proxy-hosts.conf" + +if [[ -f "$CADDYFILE" ]] && command -v caddy >/dev/null 2>&1; then + if [[ ! -f "$PROXY_HOSTS_FILE" ]]; then + printf '# Von CluPilot erzeugt. Noch leer — die Konsole füllt sie.\n' > "$PROXY_HOSTS_FILE" + chown root:root "$PROXY_HOSTS_FILE" + chmod 0644 "$PROXY_HOSTS_FILE" + echo " Created $PROXY_HOSTS_FILE" + fi + + # Die Import-Zeile wird gesetzt, nicht angesagt. Sie von Hand nachtragen zu + # lassen war der Fehler: die Anleitung dazu stand in einem Kommentar, die + # Datei wurde nie angelegt, und wer der Anleitung folgte, hätte den ganzen + # Proxy ungültig gemacht. + if ! grep -q "clupilot-proxy-hosts.conf" "$CADDYFILE"; then + cp -p "$CADDYFILE" "$CADDYFILE.clupilot-backup" + printf '\n# Von CluPilot verwaltete Hostnamen (Konsole → Betrieb → Hostnamen).\nimport %s\n' \ + "$PROXY_HOSTS_FILE" >> "$CADDYFILE" + + if caddy validate --config "$CADDYFILE" >/dev/null 2>&1; then + rm -f "$CADDYFILE.clupilot-backup" + systemctl reload caddy >/dev/null 2>&1 || true + echo " Added the import line to $CADDYFILE" + else + # Zurück, sofort. Eine ungültige Konfiguration liegen zu lassen + # heißt, den nächsten Caddy-Start scheitern zu lassen — und der + # kommt beim nächsten Neustart der Maschine, nicht jetzt. + mv -f "$CADDYFILE.clupilot-backup" "$CADDYFILE" + echo " ! caddy rejected the import line — it was taken back out again." + fi + fi +fi