← docs index · ← cloud-deployment.md · ← cloud-troubleshooting.md
This page is a pre-flight checklist for opening an iterion deployment to traffic outside your private network (i.e., putting it behind a public Ingress, on the internet, or accessible to users you don’t fully trust). Every item below is a hard prerequisite — skipping any of them is how incidents happen.
If you are running iterion only on a private network (VPN, internal cluster, single-tenant lab), this page is informational. The checklist is geared toward multi-tenant or internet-exposed deployments.
This is not a substitute for a full security review. It is the minimum bar.
DisableAuth is not set in the iterion server config (cloud mode requires auth by default; see pkg/config/config.go). There is no AUTH_REQUIRED env var — auth is gated by the DisableAuth config field, which must remain false/unset in any public deployment./api/* route is gated by requireAuth (verified in pkg/server/server.go). The health endpoints (/healthz, /readyz) and auth bootstrap routes are the only intentional exceptions; both are read-only and reveal no tenant state.ITERION_JWT_SECRET must be a base64-encoded signing key with at least 32 decoded random bytes (for example, openssl rand -base64 48), held in a Kubernetes Secret, not the values file.How to verify: try curl https://<host>/api/runs with no token — must return 401. Try with an expired token — must return 401. Try with a valid token from tenant A reading tenant B’s run — must return 404 or 403.
tenantID=<id> matching the JWT.runs/<run-id>/... and the run-id is itself a tenant-scoped value. No cross-tenant prefix collision possible./api/admin/*) require both requireAuth AND a role check (requireSuperAdmin).How to verify: log in as user A on tenant A, take their JWT, try to call /api/runs/<a-run-id-from-tenant-B> — must return 404 or 403, never 200.
kubectl describe networkpolicy … or by observing that kubectl exec into a runner pod cannot reach 1.1.1.1.How to verify: from a runner pod with sandbox active, attempt curl https://example.com/ — must fail. Attempt curl https://api.anthropic.com/ — must succeed.
valueFrom / external-secrets.How to verify: kubectl describe pod <iterion-server-pod> | grep -i secret — env vars must reference valueFrom.secretKeyRef, never literal value:.
main, weekly schedule, and post-image builds; the workflow publishes SARIF/results summaries for HIGH/CRITICAL findings but intentionally does not fail the PR or image release by itself. If you require a hard gate, configure branch protection or a code-scanning rule outside the current workflow. See .github/workflows/trivy.yml.image: ghcr.io/socialgouv/iterion:<digest>@sha256:…, not floating tags like :latest or :v1.sandbox.build: by design — production deployments reference a CI-built iterion-sandbox-slim:<version> digest.How to verify: helm template ./charts/iterion -f values-prod.yaml | grep image: — every image string ends in @sha256:….
/metrics on the server. The chart’s metrics.podMonitor.enabled switch wires this when prometheus-operator is installed.OTEL_EXPORTER_OTLP_ENDPOINT (or the traces-specific OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) on server + runner.ITERION_LOG_FORMAT=json set on server + runner; verified by piping a server log line through jq./readyz 503 > 1m, NATS queue depth > 100 sustained, runner OOM kills, Trivy failed scan, JWT signing-key proximity to expiry.cloud-troubleshooting.md plus alert-specific notes.How to verify: kill a runner pod; /api/runs/<id>/events should not stream new events (run hangs); the alert for queue-depth or stale-run should fire within its configured window.
kubectl get deploy -o yaml | grep -i probe.runner.keda.consumerName); two parallel deployments do not collide on the same JetStream consumer.How to verify: kubectl get scaledobject -n <ns> -o yaml | grep consumer shows the parameterised name. Drain a runner node; KEDA recreates pods on a remaining node within ~30s.
budget: block AND a server-side default override (operator can refuse to launch a run with no budget)./api/runs/launch and /api/runs/resume to prevent a single misconfigured client from saturating the queue./readyz 503s, downstream users need a way to know without paging the on-call manually.| Role | Name | Date | Notes |
|---|---|---|---|
| Operator (deploys + monitors) | |||
| Security reviewer | |||
| Privacy / legal reviewer | |||
| On-call manager |
A deployment is ready for public exposure when all four sign-offs are present and dated, and every checkbox above is ticked. Half-completed checklists are how incidents are made.
If a box can’t be ticked, do not open the deployment to traffic until it can — or accept the risk explicitly, in writing, with a named owner.