Skip to content

Deploy: one compose file, shapes chosen by profiles and env - #296

Merged
czpython merged 3 commits into
mainfrom
deploy-one-compose-profiles
Aug 21, 2026
Merged

Deploy: one compose file, shapes chosen by profiles and env#296
czpython merged 3 commits into
mainfrom
deploy-one-compose-profiles

Conversation

@czpython

@czpython czpython commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Why

Deployment shapes were a file for each shape: compose.local.yaml and compose.remote.yaml, stitched onto the base with COMPOSE_FILE. Each provider that needed different services meant a new file that copied the others, because a shape is a combination of two independent choices: which provider, and whether an edge exists. A fourth file for docker-sbx would have copied Caddy and the janitor from the remote overlay.

What

One compose.yaml holds every service. The variation splits by kind:

  • Service presence — the hosted profile gates the Caddy edge and the janitor; the gateway profile gates the SSH gateway. install.sh writes COMPOSE_PROFILES to .env: empty for a local docker box, hosted for a hosted one, hosted,gateway for docker-sbx.
  • Service shape — the per-provider drukbox values (provider, tailnet, token) come from .env, as before for exe and generic remote.
  • Structural shapecompose.docker-sbx.yaml adds the mounts that connect drukbox and the gateway to the host Docker Sandboxes daemon. Only a provider with different mounts needs an overlay. An env-only provider costs zero new files.

Safety and upgrade behavior

  • A pre-PR local-shape install keeps service_url = :8000 in its druks.toml while drukbox now listens on :8780. There is no code migration on purpose: no such installs exist that upgrade in place. The fix on an affected box is one edit: set sandbox.service_url to http://127.0.0.1:8780.
  • SERVICE_TOKENS renders on every shape and compose has no default: a missing token stops drukbox instead of accepting a known one.
  • drukbox binds 127.0.0.1 through DRUKS_DRUKBOX_BIND_HOST, separate from the web bind variable that macOS sets to 0.0.0.0.
  • install.sh writes the shape selection to .env before each exit path (a setup gaps-exit included), removes the retired overlay files, and for docker-sbx: pins DRUKS_SBX_HOME, creates the .drukbox bind source with the correct owner, and stops with instructions when the sandboxd socket is missing.
  • The gateway extends the base drukbox anchor, so it reads the shared Postgres, not the sqlite default in .env.

Verified

All three shapes rendered with docker compose config; the guards fail loudly (missing DRUKS_SBX_HOME, missing SERVICE_TOKENS). The setup changes (always-rendered token, preserved keys) validated against run_setup directly, plus new tests. ruff check and ruff format pass on the touched backend files. The full backend pytest suite needs a live Postgres and was not run in this environment.

Comments and docs in this PR use simplified English (ASD-STE100).

czpython and others added 3 commits August 21, 2026 12:56
Deployment shapes were a file per shape (compose.local.yaml, compose.remote.yaml)
stitched onto the base via COMPOSE_FILE. Each new provider that needed different
services was a new whole file duplicating the others — a combinatorial pile, since
a shape is really a combination of orthogonal axes (which provider, whether an
edge exists), not a single choice.

Collapse to one compose.yaml. Every service lives there; the two genuinely
optional ones — the Caddy identity edge and the janitor — are gated by profiles,
and the per-provider drukbox differences (provider, tailnet, service token, bind
host) were already env values, so they ride in .env exactly as exe vs generic-
remote already did. install.sh writes COMPOSE_PROFILES instead of picking a file:
empty for a local docker box, caddy,janitor for a hosted one.

drukbox now listens on its image default port (8780) in every shape; the local
overlay's :8000 override and matching healthcheck were incidental drift, so the
docker shape's service_url moves to 8780 to match. (The from-source `make dev`
flow in development.md keeps :8000 — that is bare uvicorn's default, unrelated.)

A provider whose drukbox needs a structurally different shape — different mounts,
a different user, an extra service — still warrants an overlay, because env can
substitute values but cannot restructure a service. compose.docker-sbx.yaml is
the first: it reshapes the drukbox services to drive the host's Docker Sandboxes
daemon (microVM sandboxes) and adds the SSH gateway, selected by install.sh with
COMPOSE_PROFILES=caddy,janitor,gateway when the provider is docker-sbx. Adding an
env-only provider now costs zero new files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gateway now extends the base drukbox anchor, and it gets the Postgres
DATABASE_URL instead of the sqlite default from .env. Setup migrates the
retired :8000 service_url of old docker-shape installs to :8780, and it
renders SERVICE_TOKENS on every shape — the compose default is gone, and a
missing token stops drukbox instead of accepting a known one. drukbox binds
127.0.0.1 through its own variable, not through the web bind variable that
macOS sets to 0.0.0.0.

install.sh writes the shape selection to .env before each exit path, and it
removes the retired overlay files. The docker-sbx branch pins DRUKS_SBX_HOME
(setup preserves it), creates the .drukbox bind source with the correct
owner, and stops with instructions when the sandboxd socket is missing. The
overlay requires DRUKS_SBX_HOME and does not fall back to the ambient HOME.

One "hosted" profile replaces the paired caddy/janitor profiles. The
full-local diagram shows the correct port. The deploy README documents the
host preparation and maps the retired overlay files to their replacements.
Comments and docs use simplified English (ASD-STE100).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No legacy local-shape installs exist that upgrade in place. A stale value
is a one-line manual edit, not a code path to keep forever.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@czpython
czpython merged commit b63f934 into main Aug 21, 2026
1 check passed
@czpython
czpython deleted the deploy-one-compose-profiles branch August 21, 2026 13:49
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