Four services per spec §2.2:
* caddy — image rutster-edge; ports 80/443; volume caddy-data:/data
(Caddy ACME state — loss risks LE 5/week duplicate-cert lockout
per TLS brief §5 risk 5; mounts ./Caddyfile for edit-without-
rebuild).
* engine — image rutster-engine; ports 8080 + 49152-49407/udp (media
UDP direct, never proxied — spec §2.1); stop_grace_period 660s
paired with RUTSTER_DRAIN_DEADLINE_SECS=600 (grace exceeds drain
invariant, spec §2.2/§8).
* brain — image rutster-brain; network_mode: "service:engine" so the
loopback-only tap posture survives unchanged (resolve_tap_url
rejects non-loopback until step 6 per spec §2.2). Quoted in
YAML — `service:engine` would parse as a mapping otherwise.
* valkey — upstream valkey/valkey:8.0 (BSD-3); volume valkey-data:/data;
dark on day one except slice-E ValkeyEventSink consumer.
Bring-your-own-proxy: comment out the caddy service; the engine keeps
plaintext :8080; tuned-timeout snippets land in slice-G reverse-proxies.md.
Signed-off-by: Aaron D. Lee <himself@adlee.work>