Deploy to Kubernetes (Helm)¶
The deployment-dashboard Helm chart deploys the full stack to any Kubernetes cluster you already run. For an overview of deployment shapes and shared prerequisites, see the Install & deploy landing.
Topology¶
| Component | Kubernetes resource | Ingress |
|---|---|---|
| Gateway | Deployment + Service (nginx) | Ingress (Option A) โ or none, see Routing options |
| Frontend | Deployment + Service (Angular/nginx) | Internal (Option A) โ or its own Ingress path (Option B) |
| API | Deployment + Service (.NET 10) | Internal (Option A) โ or its own Ingress path (Option B) |
| Fetcher | Deployment | None โ outbound only |
| PostgreSQL | StatefulSet (bundled) โ or external managed instance (standalone) | Internal / external |
| Secret | โ | API key ยท control key ยท PostgreSQL password |
Prerequisites¶
- A running Kubernetes cluster and
kubectlcontext pointed at it helm>= 3.x- An Ingress Controller (or a Gateway API implementation) โ required to expose the stack publicly
- A default
StorageClassโ required only if using the bundled PostgreSQL
Install¶
Install straight from the published chart โ no clone needed.
Full mode (bundled PostgreSQL, Option A gateway routing):
helm install deployment-dashboard oci://ghcr.io/kostiantyn-matsebora/charts/deployment-dashboard \
--version <ver> \
--set apiKey=<strong-write-key> \
--set postgresql.auth.password=<strong-db-password> \
--set ingress.enabled=true \
--set ingress.className=<your-ingress-class> \
--set ingress.host=<dashboard.example.com>
Standalone mode (external managed PostgreSQL):
helm install deployment-dashboard oci://ghcr.io/kostiantyn-matsebora/charts/deployment-dashboard \
--version <ver> \
--set apiKey=<strong-write-key> \
--set postgresql.enabled=false \
--set externalDatabase.host=<pg-host> \
--set externalDatabase.database=deployment_dashboard \
--set externalDatabase.username=<db-user> \
--set externalDatabase.existingSecret=<secret-with-pg-password> \
--set ingress.enabled=true \
--set ingress.className=<your-ingress-class> \
--set ingress.host=<dashboard.example.com>
Pin a release
Replace <ver> with a chart release tag for a reproducible deploy โ mirrors Pinning a release version for the other install methods.
Values reference¶
| Value | Meaning |
|---|---|
image.tag |
Pin to a release tag; empty defaults to the chart's appVersion. |
gateway.enabled |
true (default) = Option A โ nginx gateway pod + one Ingress. false = Option B โ native Ingress path routing, no gateway pod. |
ingress.enabled |
true (default) โ expose the stack through an Ingress Controller. The Install examples set it explicitly for clarity; it's already on. |
ingress.className |
Ingress class to target (e.g. nginx). |
ingress.host |
Public hostname routed to the stack. |
ingress.tls |
TLS configuration for the Ingress (secret name, hosts). |
postgresql.enabled |
true (default) = bundled in-chart PostgreSQL (full mode). false = external managed PostgreSQL via externalDatabase.* (standalone mode). |
postgresql.auth.password |
Bundled PostgreSQL password. Required when postgresql.enabled and no postgresql.auth.existingSecret. |
externalDatabase.host / .port / .database / .username / .existingSecret |
External PostgreSQL connection details (standalone mode only). |
fetcher.enabled |
Opt-in pull-mode Fetcher; pair with fetcher.github.* for the GitHub token and repos to poll. |
apiKey |
Write-endpoint secret (X-Api-Key). Required. |
controlApiKey |
Distinct secret to enable POST /api/control/reset; leave unset to hide the reset surface. |
existingSecret |
Reference an existing Kubernetes Secret for apiKey / controlApiKey instead of setting them inline. |
api.corsAllowedOrigins |
Empty (default) = CORS off โ single-origin gateway routing. Set only for split-host Option B deployments; see the CORS caveat. |
demo.enabled |
Opt-in demo simulators (demo-driver + GitHub emulator) and /demo/* routes. Off by default โ unsafe for production. See Demo mode. |
Routing options¶
Two mutually exclusive ways to expose the stack, matching the gateway's GW6 decision:
| Option | gateway.enabled |
Ingress shape | CORS |
|---|---|---|---|
| A โ Gateway (default) | true |
One Ingress โ gateway pod, which proxies to frontend + API internally | Off โ single origin, no api.corsAllowedOrigins needed |
| B โ Native Ingress | false |
Ingress routes paths directly to frontend and API Services, no gateway pod | Required whenever frontend and API resolve to different hosts |
CORS caveat for Option B
Option B with a single Ingress host and path-based routing (e.g. / โ frontend, /api โ API) still shares one origin โ CORS stays off. But if you split frontend and API onto distinct hosts, you must set api.corsAllowedOrigins to the frontend's origin, or browser requests to the API are rejected. This mirrors backend decision D6 in API_SPECIFICATION.md.
Demo mode¶
Set --set demo.enabled=true to add a demo-driver Deployment, a GitHub-emulator Deployment, /demo/* routes, and a Fetcher repointed at the emulator โ the same story as the Quickstart, running in-cluster instead of via Compose.
Not for production
demo.enabled is off by default and ships insecure defaults (a placeholder demo-api-key, no real secrets). Never enable it on a cluster that also serves real traffic.
Upgrade / uninstall¶
helm upgrade deployment-dashboard oci://ghcr.io/kostiantyn-matsebora/charts/deployment-dashboard --version <new-ver>
helm uninstall deployment-dashboard
Chart versions track dashboard releases in lockstep with image.tag โ pin both together for a reproducible upgrade.
PVC retention
helm uninstall does not delete the PersistentVolumeClaim backing the bundled PostgreSQL StatefulSet. Delete it manually (kubectl delete pvc ...) if you want a clean slate; leave it in place to preserve data across a reinstall.
Networking & security¶
- The bundled PostgreSQL uses a static password via a Kubernetes Secret (
postgresql.auth.passwordorpostgresql.auth.existingSecret) โ there is no managed-identity auth path on Kubernetes. Azure managed-identity AAD auth stays Azure-only, available through the Azure (Terraform) path instead. - With
gateway.enabled: true(Option A), the gateway pod is the single public surface (GW1) โ frontend and API stay internal Services, reachable only through the gateway's Ingress. - Store
apiKey/controlApiKeyin a Secret (existingSecret) rather than passing them as plain--setvalues in production โ Helm records--setvalues in its release history.