docs(deploy): caddy conf bind mounts are inode-pinned — recreate, not reload
Document the gotcha hit fixing distribution CORS: caddy/conf.d/*.caddy are single-file bind mounts pinned to the host inode at container creation. git pull rewrites tracked files via atomic rename (new inode), so a running caddy keeps the old config; `restart`/`caddy reload` reuse the stale inode. Apply conf changes with `docker compose up -d --force-recreate caddy` (or the --hard down/up). Added to plan/14-deploy.md and the deploy skill guardrails. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,14 @@ invoking this skill is the authorization to proceed, but:
|
|||||||
|
|
||||||
- Never `git reset --hard` or discard changes on `cochi` without telling the user
|
- Never `git reset --hard` or discard changes on `cochi` without telling the user
|
||||||
first — there may be host-local edits.
|
first — there may be host-local edits.
|
||||||
|
- **Caddy conf changes need a recreate, not reload/restart.** If the deploy
|
||||||
|
touched any `caddy/conf.d/*.caddy` or the Caddyfile and you did a *rolling*
|
||||||
|
`update-all.sh` (not `--hard`), the change WON'T apply: those are single-file
|
||||||
|
bind mounts pinned to the host inode, and `git pull` gives the file a new inode.
|
||||||
|
`restart`/`caddy reload` reuse the stale inode. Run
|
||||||
|
`docker compose up -d --force-recreate caddy`, then verify with
|
||||||
|
`docker compose exec caddy cat /etc/caddy/conf.d/<file>`. The `--hard` path
|
||||||
|
(full `down`/`up`) already recreates, so it's unaffected.
|
||||||
- Volumes (`mc_data`, `drasl_state`, `kuma_data`) persist across `down`; the
|
- Volumes (`mc_data`, `drasl_state`, `kuma_data`) persist across `down`; the
|
||||||
world and monitors are safe. Do NOT pass `-v`/`--volumes` to `down`.
|
world and monitors are safe. Do NOT pass `-v`/`--volumes` to `down`.
|
||||||
- If a step fails, STOP and surface the exact error + the failing command. Do not
|
- If a step fails, STOP and surface the exact error + the failing command. Do not
|
||||||
|
|||||||
@@ -24,7 +24,18 @@ Two modes:
|
|||||||
ONLY the services whose mounted inputs changed since a pre-run snapshot
|
ONLY the services whose mounted inputs changed since a pre-run snapshot
|
||||||
(drasl/nmsr on a config re-render, minecraft on a mod change). Minimal
|
(drasl/nmsr on a config re-render, minecraft on a mod change). Minimal
|
||||||
downtime. Does **not** detect caddy static-conf (`caddy/conf.d/*.caddy`)
|
downtime. Does **not** detect caddy static-conf (`caddy/conf.d/*.caddy`)
|
||||||
changes — use `--hard` for those.
|
changes — apply those with a **recreate**, not a reload/restart (see gotcha
|
||||||
|
below): `docker compose up -d --force-recreate caddy` (no world downtime), or
|
||||||
|
`--hard` for a full redeploy.
|
||||||
|
|
||||||
|
> **Caddy conf bind mounts are inode-pinned — recreate, don't reload.** Each
|
||||||
|
> `caddy/conf.d/*.caddy` is a *single-file* bind mount, which Docker pins to
|
||||||
|
> the host file's inode at container creation. `git pull` rewrites a tracked
|
||||||
|
> file via atomic rename = a NEW inode, so the running container keeps the OLD
|
||||||
|
> config. `docker compose restart caddy` and `caddy reload` reuse the same
|
||||||
|
> container → same stale inode → no effect. Only re-creating the container
|
||||||
|
> (`up -d --force-recreate caddy`, or the `--hard` down/up) re-resolves the
|
||||||
|
> mount. Verify: `docker compose exec caddy cat /etc/caddy/conf.d/<file>`.
|
||||||
- `./update-all.sh --hard` — `docker compose down --remove-orphans && up -d
|
- `./update-all.sh --hard` — `docker compose down --remove-orphans && up -d
|
||||||
--build`. Full restart (Minecraft world downtime); picks up everything.
|
--build`. Full restart (Minecraft world downtime); picks up everything.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user