## Traffic flow

    flowchart LR
        DNS["lomavuokraus.fi\nstaging.lomavuokraus.fi\napi.lomavuokraus.fi"] --> Traefik["Traefik ingress\n(class: traefik)"]
        User["User browser"] -->|"HTTPS"| Traefik
        CertMgr["cert-manager\nletsencrypt prod/staging"] -->|"TLS"| Traefik
        subgraph Cluster["k3s hel1 cx23 (157.180.66.64)"]
            Traefik --> Service["Service :80 -> 8080"]
            Service --> Varnish["Varnish cache\n(static + /api/images/*)"]
            Varnish --> Pod["Next.js pods (2)\n(port 3000)"]
            Pod --> DB["PostgreSQL 46.62.203.202"]
            Pod --> SMTP["smtp.lomavuokraus.fi"]
            Secret["Secret: lomavuokraus-web-secrets"]
            CM["ConfigMap: lomavuokraus-web-config"]
        end
        Registry["registry.halla-aho.net/thalla/lomavuokraus-web"] -->|"pull"| Pod

Mermaid renders directly in the browser; edit the graph in this file to update.

## Hetzner nodes

    flowchart TB
        Users["Users"] -->|"HTTPS"| K3s["Node A: k3s (hel1 cx23)\nTraefik + cert-manager"]
        subgraph HetznerCloud["Hetzner Cloud"]
            K3s
            DB["Node B: Postgres VM\n46.62.203.202"]
        end

        subgraph Prod["Prod namespace"]
            Prod1["Next.js pod #1 (prod)"]
            Prod2["Next.js pod #2 (prod)"]
        end

        subgraph Staging["Staging namespace"]
            Stg1["Next.js pod #1 (staging)"]
            Stg2["Next.js pod #2 (staging)"]
        end

        K3s --> Prod1
        K3s --> Stg1
        Prod1 --> DB
        Prod2 --> DB
        Stg1 --> DB
        Stg2 --> DB

## Cluster & Namespaces

- Single-node k3s (Hetzner hel1 cx23) at `157.180.66.64`.
- Namespaces: `lomavuokraus-prod`, `lomavuokraus-staging`, `lomavuokraus-test`.
- Ingress controller: Traefik (k3s default).
- cert-manager v1.15.3 with ClusterIssuers:
  - `letsencrypt-prod` (ACME prod)
  - `letsencrypt-staging` (ACME staging for test certs)
- Service points to a Varnish sidecar (port 8080) in each pod before the Next.js container (3000) to cache `/api/images/*` and static assets.
- Cache policy: images cached 24h with `Cache-Control: public, max-age=86400, immutable`; `_next/static` cached 7d; non-GET traffic and health checks bypass cache.
- DNS: `lomavuokraus.fi`, `staging.lomavuokraus.fi`, `api.lomavuokraus.fi` -> cluster IP.

## Registry

- Private registry: `registry.halla-aho.net/thalla/lomavuokraus-web`.
- Credentials stored outside repo (`creds/`), image pull secret `registry-halla` in staging/prod namespaces.
- Images tagged with git SHA-derived numeric tag and `:latest`.

## App Manifests

- `k8s/app.yaml` templated via envsubst in deploy scripts.
- Objects:
  - ConfigMap: `lomavuokraus-web-config` (public env).
  - Deployment: 2 replicas, Varnish sidecar on port 8080 in front of the Next.js container (3000), liveness/readiness on `/api/health` via Varnish.
  - Service: ClusterIP on port 80 targeting the Varnish container.
  - Ingress: Traefik class, TLS via cert-manager, HTTPS redirect middleware.
  - Traefik Middleware: `https-redirect` to force HTTPS.
- Secrets: `lomavuokraus-web-secrets` in cluster (not in repo).

## Runtime Environment

- Next.js 14.2.33 (App Router) running via Node.js 20 in Docker.
- PostgreSQL at `46.62.203.202`; staging/prod DB `lomavuokraus` is clean with only the seeded admin, testing DB `lomavuokraus_testing` holds the previous data. Schema snapshot tracked in `docs/db-schema.sql`.
- SMTP: smtp.lomavuokraus.fi (CNAME to smtp.sohva.org), DKIM key under `creds/dkim/...`.
- Session auth: signed JWT cookie `session_token`; roles: USER, ADMIN, USER_MODERATOR, LISTING_MODERATOR.

## Emergency shutdown

- Script: `scripts/emergency-shutdown.sh` issues Hetzner poweroff/shutdown commands for tracked nodes (currently `node1.lomavuokraus.fi` and `db1.lomavuokraus.fi`).
- List tracked nodes: `./scripts/emergency-shutdown.sh --list`.
- Hard stop everything: `./scripts/emergency-shutdown.sh --yes --confirm "SHUTDOWN ALL LOMAVUOKRAUS NODES NOW"` (default action is `poweroff`; use `--action shutdown` for ACPI).
- Requires `hcloud` CLI with `HCLOUD_TOKEN` or configured at `~/.config/hcloud/cli.toml`; keep the node list updated when adding servers.