ADR 0008: VM deployment pattern (Ubuntu 24.04 + systemd + Caddy)¶
- Status: Superseded by ADR 0016
- Date: 2026-05-20
- Authors: rmednitzer
- Builds on: ADR 0001, ADR 0005
- Superseded by: ADR 0016
Context¶
The simulator deploys to a single Linux VM. The deployment must:
- start on boot,
- terminate cleanly so per-tick state lands in SQLite,
- expose the MCP HTTP transport behind TLS,
- restrict the OAuth surface to the Anthropic CIDR ranges plus the operator's workstation,
- rotate the audit log without re-opening the file descriptor.
Decision¶
The deployment bundle in deploy/ targets Ubuntu 24.04 LTS:
- A
nous.servicesystemd unit (Type=simple,ExecStart=the venv Python entry point,ExecStopPost=flushes state). - A daily
nous-state-flush.servicetriggered by anous-state-flush.timer(OnCalendar=*-*-* 00:14:00 UTC,RandomizedDelaySec=15m,Persistent=true). - A
Caddyfile.exampletemplate: TLS, a CIDR gate on Anthropic's published ranges plus the operator's/32, and an explicit carveout for/authorizeand/.well-known/oauth-*so the OAuth dance works. - A
logrotate.confwithdaily,rotate 90,postrotate chattr +ato keep the audit log append-only after rotation. cloud-init.yamlinstalls Python 3.12, git, Caddy, logrotate, and sqlite3; creates thenoussystem user; clones the repo; runsinstall.sh.install.shis idempotent: it creates the venv, installs the package, places the systemd units, generates an OAuth signing key if one is not present.
Consequences¶
Easier: a clean VM goes from cloud-init to a running nous in one boot.
The Caddy template makes the OAuth surface auditable.
Harder: the bundle assumes Ubuntu 24.04 LTS and systemd. Other distros need a port.
Revisit triggers¶
- A second OS becomes a deployment target (then split out a
deploy/per OS). - The OAuth surface needs a public registration endpoint (multi-tenant).
Supersession¶
ADR 0016 advances the baseline to Ubuntu 26.04 LTS in May 2026 to pick up the platform Python 3.14 and the systemd 256+ sandboxing directives. The structural shape (cloud-init + install.sh + systemd + Caddy + logrotate) is unchanged; only the OS pin moves.