Skip to content

Self-hosting

LoadBrainPostgres
< 10 agents, < 1M events/day1 CPU, 512 MiB, 10 GB disk1 CPU, 2 GiB, 10 GB
10–50 agents, < 10M events/day2 CPU, 2 GiB, 50 GB2 CPU, 4 GiB, 50 GB
50–200 agents, < 100M events/day4 CPU, 4 GiB, 200 GB4 CPU, 8 GiB, 500 GB

The brain is stateless beyond its Postgres connection. Horizontal scaling is supported in v1.1 (requires sticky routing for WebSockets).

  • Inbound to brain - TCP 7700 (HTTP + WebSocket) from the internet or private network.
  • Outbound from agent - agents initiate WebSocket connections to the brain. Agents need DNS + TCP 443 (if you TLS-terminate at a reverse proxy).
  • Brain to Postgres - usual asyncpg connection.

The brain does not need to reach agents. Agents sit behind NAT / private networks freely.

Terminate TLS at a reverse proxy (nginx / Caddy / Cloudflare). The brain speaks plain HTTP internally; X-Forwarded-Proto is respected.

Sample Caddy config:

z4j.example.com {
reverse_proxy localhost:7700 {
header_up X-Forwarded-Proto https
}
}
  • Minimum: PostgreSQL 17. Recommended: PostgreSQL 18.3+.
  • Extensions: none required (no pgvector, no timescale in v1).
  • Connection pool: Z4J_DB_POOL_SIZE default 10, tune up for high-agent deployments.

Generate at deploy time:

Terminal window
Z4J_SECRET=$(openssl rand -hex 32)
Z4J_SESSION_SECRET=$(openssl rand -hex 32)
Z4J_AUDIT_SECRET=$(openssl rand -hex 32)

Rotate secrets by changing the env and restarting. All three are independent - rotating Z4J_SESSION_SECRET invalidates sessions; rotating Z4J_AUDIT_SECRET breaks the audit chain (old rows still verify with the old secret if you keep both - see audit log).

  • Postgres: standard pg_dump or managed service snapshots. See backups guide.
  • Secrets: store in your secret manager (Vault, AWS Secrets Manager, SOPS).

The brain exposes /metrics in Prometheus format (auth-gated; set Z4J_METRICS_TOKEN). See operations § monitoring.