Documentation / 1. Architecture

Chapter 1

Architecture

Hub + worker + SSH fleet + Mailcow — how the pieces fit.

The hub is a small-footprint stack: one Next.js process, one SQLite database, one worker process, an encrypted secret vault, plus a Mailcow server for email. Everything designed to run on a single commodity VPS and scale horizontally as the fleet grows (see §11 Scaling plan).

Component layout

ComponentWhat it does
Next.js 16 (Turbopack)Serves both the public marketing site and the admin console at /admin/*. Pages + App Router hybrid.
SQLite (better-sqlite3)Canonical state. Path: ./data/app.db. WAL mode on; versioned migrations in db/migrations/ run on first boot.
Worker process (worker/index.ts)Holds a database lease (one leader at a time). Executes jobs: SSH probes, benchmarks, installs, backups, scoring ticks, tip polls, rich-list refresh.
SSH fleetPer-node ed25519 keys stored in a libsodium-encrypted vault. Every remote action is a shell script + captured stdout. Pooled connections (v0.7.8z14) for low-overhead reuse.
MailcowIndependent mail server on the same VPS. Provides IMAP/SMTP/webmail for authentication and hub-domain mailboxes.
iron-session cookieEncrypted session state. One active account in scope at a time; add-more-accounts switcher lives in the Account widget.

Firewall (Cerberus)

Cerberus is the hub’s firewall control plane for managed nodes. Three endpoints drive the lifecycle: /api/hub/nodes/[id]/firewall/bootstrap installs UFW and applies the initial ruleset, /reconcile re-pushes the desired state and sweeps drift, and /state reads the live snapshot from the node. Every probe cycle re-evaluates posture against the desired ruleset; drift surfaces on the node card within the next tick (~30s budget). Mutations are gated on fresh-admin-confirm and write to admin_audit with operator email, target, action, and result — the full audit trail is the integrity guarantee. Bootstrap budgets ~8s end-to-end on a warm SSH pool; reconcile and state stay under 2s in steady state.

Deployment model

  • Source: /home/ancientholdings/ancientholdings-website on the VPS.
  • Runtime: PM2 manages the Next.js server + worker as separate processes. Nginx fronts the site on port 443 with a Let’s-Encrypt cert.
  • Workflow: edit locally → push to GitHub → deploy script on the server pulls + npm ci + npm run build + PM2 reloads. The deploy skill automates the whole triple.

Data flow at a glance

  • Operator action(e.g. “run a benchmark”) → HTTP request to Next.js → insert a row in jobs → worker dequeues + SSHes into the node + runs the benchmark script + writes the result back to SQLite → UI polls for status.
  • Background ticks (every 30s / 60s / hourly / daily) fire from the worker: chainweb-tip poller, scoring tick, rich-list refresh, daily mint, etc.
  • Customer nodes never talk to the hub directly — all communication is hub-initiated SSH. The hub pulls data from nodes; nothing is pushed.