steid

@jamesgill /

fix: an upgrade no longer discards the operator's Caddyfile

install.sh kept /etc/steid/steid.env across a re-run but rewrote
/etc/caddy/Caddyfile unconditionally. Found the hard way on the live instance: a
www redirect added by hand vanished on the first upgrade and took the www
hostname with it, with nothing in the output to say so. On a .dev domain, which
is HSTS-preloaded, that is a hard TLS failure rather than a warning.

The Caddyfile is now written on first install only, matching how the env file is
already treated, with --force-caddyfile to opt into replacing it. --www generates
the redirect properly rather than leaving it as a manual patch that the next
upgrade eats; it is off by default because it requires a www DNS record, and
without one Caddy would retry a certificate it can never obtain.

Verified against the live instance by upgrading twice: the second run reported
"keeping existing /etc/caddy/Caddyfile" and www still answered 301.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZwc7URWKVhkAuRTWiDmjA
JamesPatrickGill authored 21 hours agoparent7da29e0Browse filescadde5c069bb594a7f868654d1be52ef4123f926

1 file changed+34 −7

install.sh+34 −7View file
@@ -66,6 +66,8 @@ VERSION="${STEID_VERSION:-0.2.0}"
6666 FLAVOUR="gnu"
6767
6868 DOMAIN=""
69+WWW=0
70+FORCE_CADDYFILE=0
6971 # A local artefact to install instead of downloading one. This exists because of
7072 # a bootstrap: the very first instance is what will *serve* the releases, so at
7173 # that moment there is nowhere to download from. It doubles as the offline and
@@ -88,6 +90,11 @@ Usage: install.sh --domain <hostname> [options]
8890 --tarball <path> install from a local tarball instead of downloading.
8991 Needed for the first install, which has nowhere to
9092 download from yet, and for offline installs.
93+ --www also serve www.<hostname>, redirecting it to the bare
94+ hostname. Requires a www DNS record pointing here —
95+ without one Caddy retries a certificate it cannot get.
96+ --force-caddyfile overwrite an existing /etc/caddy/Caddyfile. Off by
97+ default so an upgrade cannot silently discard your edits.
9198 --domain <hostname> the public hostname, e.g. git.example.com. Its DNS must
9299 already point at this machine or the certificate cannot
93100 be issued. Required.
@@ -109,6 +116,8 @@ while [ $# -gt 0 ]; do
109116 case "$1" in
110117 --domain) DOMAIN="${2:-}"; [ -n "$DOMAIN" ] || die "--domain needs a hostname"; shift 2 ;;
111118 --tarball) TARBALL="${2:-}"; [ -n "$TARBALL" ] || die "--tarball needs a path"; shift 2 ;;
119+ --www) WWW=1; shift ;;
120+ --force-caddyfile) FORCE_CADDYFILE=1; shift ;;
112121 --version) VERSION="${2:-}"; [ -n "$VERSION" ] || die "--version needs a value"; shift 2 ;;
113122 --flavour) FLAVOUR="${2:-}"; [ -n "$FLAVOUR" ] || die "--flavour needs a value"; shift 2 ;;
114123 --port) PORT="${2:-}"; [ -n "$PORT" ] || die "--port needs a number"; shift 2 ;;
@@ -346,13 +355,28 @@ if [ "$INSTALL_CADDY" = 1 ]; then
346355 say "Caddy already installed"
347356 fi
348357
349 # Rewritten every run so the domain and port always match this install. If
350 # you have hand-edited it, back it up first — this is the one file the
351 # installer overwrites.
352 say "writing /etc/caddy/Caddyfile for ${DOMAIN}"
353 mkdir -p /etc/caddy
354 cat > /etc/caddy/Caddyfile <<EOF
355# Managed by install.sh. Re-running the installer rewrites this file.
358+ # NOT rewritten on upgrade. This used to be overwritten every run, which
359+ # silently discarded operator edits — a www redirect added by hand vanished on
360+ # the next install and took the site's www hostname with it, with nothing in the
361+ # output to say so. The env file was already treated this way; the two now agree.
362+ if [ -f /etc/caddy/Caddyfile ] && [ "$FORCE_CADDYFILE" = 0 ]; then
363+ say "keeping existing /etc/caddy/Caddyfile (--force-caddyfile to replace)"
364+ else
365+ say "writing /etc/caddy/Caddyfile for ${DOMAIN}"
366+ mkdir -p /etc/caddy
367+
368+ WWW_BLOCK=""
369+ if [ "$WWW" = 1 ]; then
370+ WWW_BLOCK="
371+# www redirects to the bare hostname so there is one canonical URL.
372+www.${DOMAIN} {
373+ redir https://${DOMAIN}{uri} permanent
374+}"
375+ fi
376+
377+ cat > /etc/caddy/Caddyfile <<EOF
378+# Written by install.sh on first install only. Later runs leave it alone, so edits
379+# here survive an upgrade. Use --force-caddyfile to have the installer replace it.
356380 #
357381 # Steid has no TLS of its own (Topcoat 0.5 ships none), and it authenticates git
358382 # over HTTP Basic — so without this proxy every push would send a personal access
@@ -365,7 +389,10 @@ ${DOMAIN} {
365389 flush_interval -1
366390 }
367391 }
392+${WWW_BLOCK}
368393 EOF
394+ fi
395+
369396 systemctl enable --quiet caddy
370397 systemctl reload caddy 2>/dev/null || systemctl restart caddy
371398 fi