Deploying with Helm
The chart at deploy/chart/ is the deploy primitive: one chart serves both
disposable per-PR previews and production. It runs the
container image; the per-PR preview environments (a
later slice) are its first consumer, and production reuses it unchanged by
flipping two values.
Two modes
Section titled “Two modes”| Mode | postgres.enabled | bootstrap.enabled | Database |
|---|---|---|---|
| Preview (default) | true | true | bundled, ephemeral (emptyDir) |
| Production | false | false | external, via externalDsn |
The bundled Postgres is deliberately ephemeral: its data is an emptyDir and
does not survive a pod restart, which is what you want for a throwaway preview.
Production points at a real, managed Postgres.
Install
Section titled “Install”Preview (bundled Postgres, an auto-created owner):
helm install og-pr-42 deploy/chart -n og-pr-42 --create-namespace \ --set image.tag=sha-<short>Production (BYO Postgres, no auto-owner):
helm install omniglass deploy/chart -n omniglass --create-namespace \ --set postgres.enabled=false \ --set externalDsn='postgres://user:pass@db:5432/omniglass?sslmode=require' \ --set bootstrap.enabled=false \ --set image.tag=<release>How it boots
Section titled “How it boots”The server Deployment gates startup with init containers rather than Helm pre-install hooks, because a bundled Postgres in the same release is not up during the pre-install phase:
wait-for-db(only whenpostgres.enabled) blocks until Postgres answers.migrateapplies the schema (idempotent: dbmate runs each migration once).bootstrap(only whenbootstrap.enabled) creates the first owner and mints its bearer token, printed once to this container’s logs. Idempotent: a restart mints no second token.
Both migrate and bootstrap are safe to re-run on every rollout. At
server.replicas > 1 in production, run migrate as a separate one-shot Job
instead, to avoid concurrent migrators.
Values
Section titled “Values”| Key | Default | Purpose |
|---|---|---|
image.repository | ghcr.io/hyperscaleav/omniglass | image to run |
image.tag | latest | pin to sha-<full-sha> for an exact, immutable build |
image.pullPolicy | IfNotPresent | |
server.replicas | 1 | server pod count |
server.resources | small requests/limits | |
service.port | 8080 | ClusterIP service port |
ingress.enabled | false | create an Ingress (on for per-PR previews) |
ingress.className | traefik | ingress controller class |
ingress.host | empty | required when ingress.enabled; the public host |
bootstrap.enabled | true | auto-create an owner (previews) |
bootstrap.username | preview | owner username |
bootstrap.email / bootstrap.displayName | empty / Preview Owner | optional owner fields |
postgres.enabled | true | bundle an ephemeral Postgres |
postgres.image / user / password / database | postgres:18 / omniglass x3 | bundled Postgres settings |
postgres.resources | small requests/limits | bound the throwaway DB |
externalDsn | empty | required when postgres.enabled is false |
Exposure
Section titled “Exposure”By default the chart creates no Ingress: the standing deploy is reached by port-forward (or a cloudflared route dialing the ClusterIP Service directly).
kubectl -n omniglass port-forward svc/omniglass 8080:8080kubectl -n omniglass logs deploy/omniglass -c bootstrap # the one-time tokenFor per-PR previews, set ingress.enabled=true and an ingress.host. The chart
then emits a plain-HTTP Ingress (class traefik) that the in-cluster controller
Host-routes; the shared cloudflared tunnel fronts it with one wildcard route and
terminates TLS at the edge, so the Ingress carries no tls block.
helm install og-pr-42 deploy/chart -n og-pr-42 --create-namespace \ --set image.tag=sha-<full-sha> \ --set ingress.enabled=true \ --set ingress.host=og-pr-42.preview.hyperscaleav.com \ --set fullnameOverride=omniglass