Decision 0010
Hetzner ARM servers, deploy user only, one first-boot template
accepted · 2026-11-07
Context
ADR 0004 makes a generic Debian/Ubuntu VPS the baseline and Hetzner an optional OpenTofu module. This records what the module and the first boot actually set up.
Decision
- Ampere ARM servers:
cax21for apps (8 GB),cax11for ops (4 GB), Debian 13, in aneu-centrallocation. All Spotcraft images are multi-arch (ADR 0009). - One cloud-init template for both servers, with a
rolevalue; it's usable by hand on other providers. - Logins: only the
deployuser, by key. Root login and passwords are off. The deploy user is in thedockergroup, which is root-equivalent, so the key is guarded like a root key. - Docker comes from Docker's signed apt repository rather than a piped install script.
- Two firewalls: Hetzner's cloud firewall allows only SSH, HTTP(S) and ping from outside; ufw on each server adds the same rules and allows the private network. Services that must not be public bind to the private IP, because Docker-published ports bypass ufw.
- Delete and rebuild protection on by default.
user_data,imageandssh_keyschanges are ignored after creation, so editing the template never replaces a running server. - OpenTofu state stays local and git-ignored for the MVP.
Consequences
- A lost state file means re-importing the servers; a remote state backend is post-MVP.
- SSH stays reachable from anywhere by default because GitHub Actions deploys over SSH;
ssh_source_ipsnarrows it for setups that don't.