Files
ced4568 eae8e48d43 feat(routing): Lab Host Router closes the Gateway-to-Lab cross-VM gap
Adds platform/lab-router/ — a narrow service that runs on the Lab Host,
authenticates the Gateway via mTLS, and resolves an opaque routing token to
a local container purely from Docker label state (no Postgres access, no
callback to the Provisioner). Replaces the Gateway's env.internal_ip
assumption (only valid when Gateway and Lab share a Docker daemon) with a
data-driven direct/router decision per lab_host
(lab_hosts.routing_mode/router_endpoint, migration 004), resolved in one
place (platform/gateway/src/lab-endpoint.js's labTarget()) that every
proxy/fetch call site in server.js now goes through.

Extends the existing Docker TLS CA (infra/scripts/docker-tls/generate-docker-tls.sh)
with a second mTLS leaf pair (router-server/gateway-client) for this new
data-plane connection, deployed by the docker-tls Ansible role into a
separate directory from the control-plane pair. Firewall
(rn-lab-host-01.rules) replaces the old speculative wide port-range
allowance with one narrow rule: platform_ip -> the Router's port only.

dev-local stays routing_mode: direct — zero behavior change for local dev,
confirmed by the full existing regression suite passing unmodified.
2026-08-24 20:14:39 -05:00
..

Environment configuration

Three environments, explicitly separated so production never silently inherits a dev default:

dev staging production
Where it runs any dev machine, platform/docker-compose.dev.yml homelab or a resource-limited slice of the dedicated server once it exists rn-platform-01 / rn-lab-host-01 on Proxmox
COOKIE_SECURE unset (plain HTTP) 1 if served over HTTPS, else unset 1 — required
TRUST_PROXY unset 1 if fronted by a proxy 1 — required, real reverse proxy in front
ADMIN/owner bootstrap platform/api/bootstrap-owner.js manually same, against staging DB same, against production DB, run once by a human, credential handled per docs/PRODUCTION_DEPLOYMENT.md §10
Secrets platform/.env (gitignored, throwaway) infra/environments/staging/*.env (gitignored, real but low-stakes) infra/environments/production/*.env (gitignored, real, backed up per docs/BACKUP_DR.md)
Lab image built locally, :test tag tagged build from CI, :staging-<sha> tagged release, :<sha> or :vX.Y.Z, never :latest

Each environment directory holds *.env.template files (tracked) — copy to *.env (gitignored via infra/.gitignore) and fill in real values. Never commit a filled .env file. See docs/PRODUCTION_DEPLOYMENT.md §10 for how production secrets are actually generated, stored, and rotated (not just "don't commit them").

dev/ is intentionally thin — it just points back at the existing platform/docker-compose.dev.yml workflow (Phase 1–3B, unchanged); there was nothing new to build there for Phase 4.