# infra/

Infrastructure for [Thermograph](https://thermograph.org): Terraform host
provisioning, the SOPS+age secrets vault, WireGuard/Swarm networking, Forgejo,
Caddy, mail, and the deploy scripts that run the already-built app images on each
host. This is a domain of the `emi/thermograph` monorepo — hosts' `/opt/thermograph`
is a checkout of the whole monorepo, and `infra/` never builds app source; it only
runs published images.

- **`terraform/`** — provisions/configures hosts (SSH-driven by default; an
  optional GCP-creating module is scaffolded, no live resources yet). See
  `terraform/README.md`. No tfstate is persisted anywhere — treat `apply` as
  executable documentation, not a routine operation.
- **`deploy/secrets/`** — the git-native SOPS+age secrets vault (every app secret,
  encrypted at rest, rendered at deploy time). See `deploy/secrets/README.md`.
- **`deploy/swarm/`, `deploy/forgejo/`** — the WireGuard/Swarm cluster hosting
  Forgejo (git + CI + registry). See `ACCESS.md`.
- **`deploy/deploy.sh`** — the single deploy entry point for beta and prod.
  Takes `SERVICE=backend|frontend|all` plus `BACKEND_IMAGE_TAG`/`FRONTEND_IMAGE_TAG`,
  resets the host checkout, renders secrets, and routes to the right orchestrator.
- **`deploy/stack/`** — the **Swarm** path, live on **prod**:
  `thermograph-stack.yml` (db, web, worker, lake, daemon, frontend, autoscaler,
  autoscaler-lake), `deploy-stack.sh`, `autoscale.sh`, and the LB. Rolling updates
  are start-first, health-gated, with auto-rollback. `STACK_TEST=1` rehearses the
  whole stack on throwaway volumes and ports.
- **`docker-compose*.yml`** — the **compose** path, live on **beta** and LAN dev
  (db, backend, lake, daemon, frontend). `docker-compose.dev.yml` is the LAN
  overlay; `docker-compose.openmeteo.yml` is the self-hosted Open-Meteo overlay.

Which path a host takes is decided by `/etc/thermograph/deploy-mode`: the string
`stack` makes `deploy.sh` exec `deploy/stack/deploy-stack.sh`; anything else is
compose. The workflows never need to know which mode a host runs.

## Branches & how changes reach each environment

- **`main`** — what **prod and beta** run. `infra-sync.yml` fires on a push to
  `main` touching `infra/**`, fast-forwards each host's `/opt/thermograph` checkout
  and re-renders `/etc/thermograph.env` from the vault. It deliberately does
  **not** roll any service: image tags are the app domains' axis, not infra's. A
  compose or stack change that must recreate containers takes effect on the next
  app deploy, or a by-hand `SERVICE=all … deploy/deploy.sh`.
- **`dev`** — what LAN dev would run via `deploy/deploy-dev.sh`. The CI trigger
  for this is currently inert (the LAN box still holds a split-era checkout); use
  `make dev-up` locally.
- **`release`** — consumed by app deploys only. Both hosts track infra via `main`;
  prod's *app images* are staged by `release`, but its checkout follows `main`.

Note the asymmetry with the app domains: app code IS environment-staged
(`dev`→`main`→`release` maps to LAN→beta→prod via image tags); infra is not.
