Skip to content

feat(deploy): add Helm chart for Kubernetes deployments#323

Open
melihsunbul wants to merge 1 commit into
QuackbackIO:mainfrom
ExcellenceCloudGmbH:feat/helm-chart-k8s-deploy-upstream
Open

feat(deploy): add Helm chart for Kubernetes deployments#323
melihsunbul wants to merge 1 commit into
QuackbackIO:mainfrom
ExcellenceCloudGmbH:feat/helm-chart-k8s-deploy-upstream

Conversation

@melihsunbul

Copy link
Copy Markdown

What

Adds a Helm chart at deploy/kubernetes/quackback for deploying Quackback on Kubernetes, alongside the existing Docker/Docker Compose self-hosting path. Closes #322.

Changes

  • Migration hook Job (templates/migration-job.yaml): runs bun /app/migrate.mjs as a pre-install,pre-upgrade Helm hook, implementing the pattern apps/web/Dockerfile already documents but has no chart for. The app Deployment sets SKIP_MIGRATIONS=true automatically whenever migrations.enabled (default true).
  • Bundled datastores, all optional: Postgres (StatefulSet), Dragonfly, and MinIO — same stack as docker-compose.prod.yml — each with an enabled flag and an external*Url escape hatch for managed services.
  • Stable generated secrets: bundled Postgres/MinIO passwords are read back from the existing Secret on upgrade (via lookup) instead of re-rolled on every render, so they don't desync from what's already on the PVC.
  • SLA-tick CronJob (templates/sla-tick-cronjob.yaml, opt-in): hits POST /api/v1/internal/sla-tick, matching the Kubernetes CronJob alternative deploy/self-hosted/README.md already recommends for operators not running pg_cron.
  • Generic, portable defaults: ghcr.io/quackbackio/quackback image, no hardcoded StorageClass (empty string = cluster default), imagePullSecrets, pod/container securityContext matching the Dockerfile's non-root quackback user (uid/gid 1001).
  • Ingress: nginx-specific annotations only apply when ingress.className: nginx (the default) — other controllers (Traefik, Caddy — both already documented as supported reverse proxies) get just ingress.annotations verbatim.
  • Optional production knobs: HPA (app.autoscaling) and PodDisruptionBudget (app.podDisruptionBudget), both off by default.
  • app.extraEnv / app.extraEnvFrom: escape hatch for the many optional integration env vars (Slack, Linear, Discord, etc.) and AI model overrides this chart doesn't wire up individually — see .env.prod.example for the full list.
  • Docs: deploy/kubernetes/quackback/README.md (quick start, config reference, migrations, ingress, scheduled jobs, upgrade/uninstall), plus links from deploy/README.md and the root README.md.

Testing

  • helm lint — passes with no warnings.
  • helm template — verified rendering for both the bundled-datastore (default) and fully-external-datastore paths, plus app.autoscaling.enabled, app.podDisruptionBudget.enabled, slaTickCronJob.enabled, and non-nginx ingress.className. Confirmed SKIP_MIGRATIONS and the migration Job both disappear together under migrations.enabled=false, and that bundled-only env vars (DB_PASSWORD, S3_SECRET_ACCESS_KEY) don't leak into the external-datastore path.
  • Not yet exercised against a live cluster.

Out of scope (follow-ups)

  • values.schema.json for helm install --validate-time type checking.
  • ServiceMonitor / Prometheus scrape config — blocked on the metrics endpoint itself (see [Feature] Add OpenTelemetry and Prometheus-compatible metrics #313).
  • The webhook-delivery audit purge job — it's a raw SQL statement in the self-hosting docs, not an HTTP endpoint, so it doesn't fit the CronJob pattern used for the SLA tick. Still needs pg_cron or a DB-capable job image.

Note on sequencing

This is independent of the ticketing/CRM/RBAC stack in #283 (touches only deploy/, no overlap), and I don't want it competing for review bandwidth with that stack — happy for this to wait until #283's PRs have landed.

Adds a self-contained Helm chart at deploy/kubernetes/quackback mirroring
docker-compose.prod.yml's bundled Postgres + Dragonfly + MinIO stack for
cluster deployments, plus a few things Kubernetes needs that the compose
file doesn't:

- A pre-install/pre-upgrade migration hook Job, following the pattern
  apps/web/Dockerfile already documents ("K8s deployments should set
  SKIP_MIGRATIONS=true and run migrations from a pre-upgrade Helm hook Job
  instead"). The app sets SKIP_MIGRATIONS=true automatically once this is
  enabled (the default).
- An optional CronJob driving the SLA-tick endpoint, for operators who
  aren't running pg_cron — the alternative deploy/self-hosted/README.md
  already recommends ("Kubernetes CronJob").
- Stable auto-generated passwords for the bundled Postgres/MinIO across
  helm upgrade (read back via lookup instead of re-rolled every render).
- Generic defaults (ghcr.io image, no hardcoded StorageClass/registry),
  imagePullSecrets, pod/container securityContext matching the image's
  non-root user, optional HPA/PodDisruptionBudget, and an extraEnv/
  extraEnvFrom escape hatch for the integrations this chart doesn't wire
  up individually.

Links the chart from deploy/README.md and the root README's Self-Hosted
section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add an official Helm chart for Kubernetes deployments

1 participant