Appearance
System architecture
Role in the fleet
auxserver-prod is the heavy application host: Dockerized collaboration and automation (Nextcloud, n8n, Radicale, Portainer, HeyPuter), plus host-level Caddy and supporting daemons. It is distinct from:
- Hermes VPS — agent/control plane and git-centric work
- neuralmeadow.xyz — lighter SSO/app distribution model
- pbx-onprem — telephony
Keeping those roles separate avoids turning one failure domain into “everything we run.”
Design choices
Single public VM, many logical services
Hardware is a Contabo-class KVM VM (12 vCPU, ~47 GiB RAM, 500 GB SSD). Vertical integration is intentional: one place to patch, one edge proxy, shared operational habits. The cost is concentration risk — mitigated with backups, tight exposure, and stack isolation via Compose networks.
Caddy as the only public HTTP(S) door
Applications bind to 127.0.0.1. Caddy terminates TLS (Let’s Encrypt) and reverse-proxies by hostname. That pattern means:
- UFW only needs 22/80/443
- Apps never speak TLS themselves (except rare internal cases)
- Hostname routing is documentation-friendly and certificate-friendly
Loopback publishing over “Docker ports on the internet”
Publishing container ports on 0.0.0.0 would fight UFW/Docker’s FORWARD quirks and expand the blast radius of a single misbind. Loopback + Caddy is the standard on this host.
Host tools vs containers
| On the host | In containers |
|---|---|
| Caddy, Docker engine, Fail2Ban, code-server, unattended-upgrades | Nextcloud stack, n8n, Radicale, Portainer, HeyPuter fleets |
| Optional host PostgreSQL 16 | Nextcloud’s Postgres/Redis as compose services |
Containers isolate app dependencies; host systemd keeps the edge and runtime boring and restartable.
Identity and access
Day-to-day human/automation access is user ty with sudo. SSH keys are the real gate; Fail2Ban absorbs noisy scanners on port 22. Longer term, admin access is healthier on Tailscale than on the open internet — the security model discusses that tradeoff.
Mental model
text
Internet
│
├─ :22 sshd (+ Fail2Ban)
└─ :80/:443 Caddy
├─ cloud.* → 127.0.0.1:9080 Nextcloud
├─ n8n.* → 127.0.0.1:5678
├─ dav.* → 127.0.0.1:5232 Radicale
├─ portainer.* → 127.0.0.1:9000
├─ puterN.* → 127.0.0.1:410N HeyPuter nginx
└─ portal.* → static distWhen something breaks, decide first: edge (Caddy/UFW/DNS), runtime (Docker), or app data — then open the matching how-to.