fix(domain): unblock domain add for static apps on the control plane - #184
Open
samo-agent wants to merge 3 commits into
Open
fix(domain): unblock domain add for static apps on the control plane#184samo-agent wants to merge 3 commits into
domain add for static apps on the control plane#184samo-agent wants to merge 3 commits into
Conversation
The custom-domain vhost script runs as the admin SSH user 'samo', but static release checkouts are owned by the app user, so 'git rev-parse HEAD' aborted with dubious-ownership and the guard falsely reported release drift, blocking 'domain add' for every static app. Scope git safe.directory to the already realpath-validated checkout path so the integrity check runs regardless of checkout ownership. Deploy path is unaffected (it SSHes as the app user). Apply the same fix to src/app/bootstrap.ts:762 (re-bootstrap of a host with an active static deployment runs as root, which also trips dubious-ownership on app-user-owned release dirs). Drop 2>/dev/null in both sites so real git errors reach the operator instead of being masked by the drift message. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
'systemctl reload caddy' can fail on the control plane with systemd status=226/NAMESPACE when the long-running caddy service's PrivateTmp namespace goes stale, which blocked 'domain add' at the control-plane vhost step. Fall back to 'caddy reload --config ... --force' (the admin API, zero-downtime, Caddy's recommended reload) when systemctl reload fails, so control-plane routing changes still apply. Fail-closed on a genuinely invalid config is preserved (both paths validate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…teTmp namespace failure Records the systemd status=226/NAMESPACE failure mode (stale PrivateTmp staging dir on long-running caddy.service) and the admin-API reload fallback that samohost now uses on the control plane, plus the host-side maintenance remedy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent root-cause fixes that together block
samohost domain addfor a static app on the control plane, plus a docs note. Discovered while attaching a customer custom domain to a live static site; each fix is TDD'd and independently reviewed (correctness + security/safety lenses).1. Ownership-safe
git rev-parsein the static custom-domain guard (c3716a0)domain addfailed withactive static release checkout does not match its recorded sha.samo, but static release checkouts are owned by the app user.git -C <release> rev-parse HEADaborts with dubious ownership; the2>/dev/nullmasked it → empty string → never equals the recorded sha. (The deploy path is unaffected — it SSHes as the app user, Issue SSH previews as the app user on shared-web VMs (mirror #161) #163.)-c safe.directory="$SAMOHOST_CHECKOUT_REAL"to the already-realpath-validated canonical checkout path (per-invocation, non-persistent; matches the fix(deploy): emit safe.directory before first git call (unblocks dubious-ownership deploy failure) #160 trust model but narrower) and drop2>/dev/nullso real git errors surface. Same guard inbootstrap.ts(root-run) fixed identically.HEAD == recorded-shacheck is unchanged; only git's ownership refusal is lifted for the one validated path. Verified live: assamo, old form → empty, new form → correct sha (release is a linked worktree; git 2.43).2. Resilient control-plane Caddy reload (
9195df7)domain addfailed at the control-plane step:Job for caddy.service failed.caddy.service(PrivateTmp=true, running 88 days) lost its systemd-private/tmpstaging dir to theD /tmp … 30dtmpfiles cleaner, sosystemctl reload caddyfails withstatus=226/NAMESPACE. Caddy keeps serving, but config changes silently don't apply. Host-wide for long-runningPrivateTmpservices.systemctl reload caddy || caddy reload --config /etc/caddy/Caddyfile --force. The admin-API fallback is zero-downtime (verified live on all 41 hosts) and immune to the namespace issue; fails closed on an invalid config. App-VM reloads left assystemctl-only (their sudoers grant only that).3. Docs (
fc6894f)docs/stack/routing.md: the reload failure mode + fallback + host remedy.Host follow-up (NOT in this PR — needs a maintenance window)
systemctl reload/restart caddyon the control plane still fails untilcaddy.serviceis restarted once (recreates the namespace dir). Also fix the/tmptmpfiles rule so it stops evicting livesystemd-private-*dirs — this affects every long-runningPrivateTmpservice, not just Caddy.Tests
tsc --noEmitclean.bash -n; resilient CP reload + fail-closed lock (not.toContain("reload caddy || true")) + app-VM scope guard.🤖 Generated with Claude Code