Skip to content

fix: Caddy bootstrap on fresh config + persist deploy history to SQLite#25

Merged
mitchelljphayes merged 1 commit into
mainfrom
fix-caddy-bootstrap-and-deploy-history
Jun 24, 2026
Merged

fix: Caddy bootstrap on fresh config + persist deploy history to SQLite#25
mitchelljphayes merged 1 commit into
mainfrom
fix-caddy-bootstrap-and-deploy-history

Conversation

@mitchelljphayes

Copy link
Copy Markdown
Owner

Two bugs found during the first real deployment on a clean VPS (Ubuntu 24.04 + Docker + Caddy):

1. Caddy bootstrap failed on fresh install (critical)

A freshly-started Caddy has only the admin endpoint configured — no apps.http tree. The old bootstrap POSTed to config/apps/http/servers/slip, which returned invalid traversal path because the parent path didn't exist. This blocked every fresh install.

Fix: fetch the full config, merge the slip server block in, and reload atomically via POST /load — preserving existing config (e.g. admin).

2. Deploy history stuck at 'accepted' (broke SLIP-70)

The deploy state machine's record_deploy only updated the in-memory cache, never SQLite. Only the initial 'accepted' write (from the API handler) was persisted, so GET /v1/deploys/{id} never showed progress and history didn't survive restart — defeating the entire point of SLIP-70.

Fix: give DeploySharedState access to the Db and persist every state transition.

Verification

Both verified end-to-end on a real Docker + Caddy VPS:

  • Fresh Caddy bootstrap succeeds, admin config preserved
  • Deploy progresses accepted -> pulling -> ... -> completed
  • Blue-green redeploy swaps containers correctly
  • Deploy history survives daemon restart

380 tests pass, clippy clean.

Two bugs found during first real deployment on a clean VPS:

1. Caddy bootstrap failed on a fresh Caddy that has only the admin
   endpoint configured. POSTing to config/apps/http/servers/slip returned
   'invalid traversal path' because the apps.http tree did not exist yet.
   Fix: fetch the full config, merge the slip server block in, and reload
   atomically via POST /load — preserving existing config (e.g. admin).
   This blocked EVERY fresh install.

2. Deploy history was stuck at 'accepted' in SQLite. The deploy state
   machine's record_deploy only updated the in-memory cache, never SQLite —
   only the initial 'accepted' write from the API handler was persisted.
   GET /v1/deploys/{id} (which reads SQLite) never showed progress.
   Fix: give DeploySharedState access to the Db and persist every state
   transition. Verified live: deploys now progress accepted -> ... ->
   completed and survive daemon restart.

Both verified end-to-end on a real Docker + Caddy VPS.
@mitchelljphayes mitchelljphayes merged commit 0f7c971 into main Jun 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant