Commit Graph

15 Commits

Author SHA256 Message Date
4ff3048dd3 fix(helm): hardening from review
- _helpers.tpl: required guard on image.tag — silent empty deploys can
  no longer happen; helm fails fast with a clear message.
- configmap-nginx: HTTPS fastcgi param uses if_not_empty, so PHP only
  sees HTTPS when X-Forwarded-Proto is actually present.
- deployment-app: add startupProbe with 100s budget so first-boot cache
  warmup doesn't trip liveness.
- deployment-horizon: failureThreshold=5 on the horizon:status probe;
  transient Valkey blips no longer cause restart loops.
- job-migrate: mount oauth-keys so seeders that touch Passport clients
  don't silently fail.
- statefulset-valkey: replace separate password Secret with a
  requirePassword toggle that reads REDIS_PASSWORD from the main chart
  Secret (same Secret app/horizon/scheduler already mount). Liveness
  probe authenticates with the password when set.
- values-us-prod: enable valkey.requirePassword.
- README: add REDIS_PASSWORD to bootstrap procedure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:08:10 -04:00
d94a196300 docs(helm): chart README + APP_KEY/Passport bootstrap procedure
Spells out the one-time secret generation that must NEVER be re-run.
Documents local k3d setup and operations runbooks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:56:58 -04:00
1c1cc0681d feat(helm): values-local + values-us-prod
Local: in-cluster MariaDB + Valkey, port-forward instead of ingress,
chart-generated APP_KEY (dev only).
Prod: external MariaDB (ezscale ns), Longhorn-backed Valkey, Traefik
IngressRoute with cloudflarewarp + cert-manager TLS, image.tag set
at deploy time, secret pre-created out-of-band.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:56:25 -04:00
7238095a77 feat(helm): Traefik IngressRoute + cert-manager Certificate
Two IngressRoutes (web → http-to-https redirect, websecure → app)
covering all configured hosts. Certificate covers all hosts as SANs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:55:52 -04:00
b0f0cd2c16 feat(helm): in-cluster Valkey StatefulSet (toggleable)
AOF persistence + LRU eviction + optional password. PVC for the
queue data so Horizon doesn't lose pending jobs on pod restart.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:55:32 -04:00
f4ec009840 feat(helm): in-cluster MariaDB CR (toggleable for dev)
Renders only when mariadb.enabled=true. Generates a random root
password Secret with helm.sh/resource-policy=keep so uninstall
doesn't orphan the data volume.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:55:17 -04:00
c46f02bca5 feat(helm): mariadb-operator Database/User/Grant CRDs
When mariadb.enabled=true, references the in-cluster MariaDB this
chart deploys. When false, references an external CR via
mariadb.externalRef. Privileges scoped to the website's database
only — no global ALL PRIVILEGES.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:55:06 -04:00
3c2cb907d3 feat(helm): pre-install/pre-upgrade migration Job
Helm hook runs migrate (and optionally seed) before any pod rolls.
If the Job fails, helm upgrade aborts and the previous ReplicaSet
keeps serving traffic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:54:44 -04:00
67cd6f243a feat(helm): scheduler deployment (single replica, schedule:work)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:54:31 -04:00
2d633e37ab feat(helm): Horizon deployment (Recreate strategy, 60s grace)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:54:21 -04:00
4b63fec032 feat(helm): HPA for app deployment (toggleable, CPU-based)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:54:08 -04:00
02c8abb67b feat(helm): app Deployment (nginx + php-fpm sidecar)
Two-container pod sharing source via emptyDir populated by init
container. Nginx vhost in a separate ConfigMap. OAuth keys mounted
from the chart Secret as files under /var/www/html/secrets/, copied
into storage/ by the prod entrypoint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:53:56 -04:00
fb50dae658 feat(helm): Service template (ClusterIP, port 80 → http)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:53:25 -04:00
a4b65e61d2 feat(helm): ConfigMap + Secret templates
ConfigMap renders all non-secret env vars including dynamic DB_HOST
and REDIS_HOST. Secret template only renders when secret.create=true
(dev convenience); production references an existing Secret.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:53:17 -04:00
9222c8e973 feat(helm): chart skeleton (Chart.yaml, values, helpers)
Initial scaffold for the ezscale-website chart. Defaults assume
self-contained local dev (in-cluster MariaDB + Valkey). Production
overrides will live in values-us-prod.yaml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:52:53 -04:00