Skip to content

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 hostIn containers
Caddy, Docker engine, Fail2Ban, code-server, unattended-upgradesNextcloud stack, n8n, Radicale, Portainer, HeyPuter fleets
Optional host PostgreSQL 16Nextcloud’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 dist

When something breaks, decide first: edge (Caddy/UFW/DNS), runtime (Docker), or app data — then open the matching how-to.

Northeast Systems · Aux Server · Infra Server