infra: edge-control install.sh overwrites /etc/caddy/Caddyfile with no carve-out for apex/static sites — landing page lost on install #788
Labels
No labels
action
backlog
blocked
bug-report
cannot-reproduce
in-progress
in-triage
needs-triage
prediction/actioned
prediction/dismissed
prediction/unreviewed
priority
rejected
reproduced
tech-debt
underspecified
vision
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: disinto-admin/disinto#788
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
tools/edge-control/install.shline 227-240 writes/etc/caddy/Caddyfileunconditionally with a minimal template:No backup of the pre-existing file. No import directive. No site block for the apex domain or static content. All actual serving is then expected to happen through dynamic routes injected by
lib/caddy.sh add_route, and those routes only handle<project>.<DOMAIN_SUFFIX>hosts via reverse_proxy to127.0.0.1:<port>.Consequence on a real deployment (harb-staging as observed 2026-04-15): the current Caddyfile serves three distinct things —
disinto.ai(static landing page from/home/debian/disinto-site),www.disinto.ai(redirect to apex), and<project>.disinto.aireverse-proxies. Runninginstall.shas-is would lose the apex + www blocks and leave visitors with an empty catch-all.The installer is presented in the README as idempotent (
curl … | bash -s -- --gandi-token …) but cannot safely be re-run on a box that already serves non-tunnel content. This matches the class of drift we just eliminated fordocker-compose.ymlvia #770.Fix
Back up the existing Caddyfile before overwriting. At the top of the "Create Caddyfile with admin API and wildcard cert" step:
So an operator who runs install.sh on a non-empty box loses nothing.
Support an
--extra-caddyfile <path>flag that causes the emitted Caddyfile to end withimport <path>. Operators write their apex/www/static blocks once into a site-owned file and edge-control leaves them alone:Default the path to
/etc/caddy/extra.d/(glob import) so operators can drop inlanding.caddy,www-redirect.caddy, etc., and re-running install.sh preserves them.Document the contract in
tools/edge-control/README.md: edge-control owns<project>.<DOMAIN_SUFFIX>routing; the operator owns apex, www, and any non-tunnel content via/etc/caddy/extra.d/.Out of scope for this issue
Extending the register protocol with a first-class "static site" verb (e.g.
ssh disinto-register@edge "static <name> <path>") would be nice — you could serve the landing page as just another registered entry — but it changes the control-plane surface. Treat as a separate follow-up if ever needed. The import-directive approach above is small enough to ship now.Affected files
tools/edge-control/install.sh— backup + extra-caddyfile support + extra.d directory scaffoldingtools/edge-control/README.md— document the operator/edge-control boundaryAcceptance criteria
install.shon a box with an existing/etc/caddy/Caddyfilecreates/etc/caddy/Caddyfile.pre-disintoas a backup before overwritingimport /etc/caddy/extra.d/*.caddy(or equivalent) so operator-owned blocks survive across re-installs/etc/caddy/extra.d/directory is created during install with 0755 perms, root:caddy ownership/etc/caddy/extra.d/, edge-control only touches the top-level Caddyfile + dynamic routes via admin API/etc/caddy/extra.d/contentsadd_routetargets non-existent Caddy serveredge— registration succeeds in registry but traffic never routes #789