Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Buzz Helm Chart
Buzz is a Nostr-based messaging platform for human–agent collaboration: a single relay binary serving WebSocket + REST + web UI, backed by PostgreSQL, Redis, and S3-compatible object storage.
This chart has two operating profiles selected by values:
| Profile | When | What you get |
|---|---|---|
| Production (default) | Self-hosted multi-tenant, regulated, or GitOps-managed | External managed Postgres/Redis/S3, secrets.existingSecret:, no chart-side autogen, HA-capable (replicaCount ≥ 2) |
| Quickstart (eval) | Eval, single-node, one-off demo | In-cluster Postgres + Redis + MinIO subcharts/Deployments, chart auto-generates relay + service secrets, single replica |
Quickstart (eval only)
helm install buzz oci://ghcr.io/block/buzz/charts/buzz --version 0.1.0 \
--create-namespace --namespace buzz \
--set quickstart=true \
--set postgresql.enabled=true \
--set redis.enabled=true \
--set minio.enabled=true \
--set relayUrl=wss://buzz.example.com \
--set ownerPubkey=<64-char-hex-pubkey>
This brings up everything in-cluster — Postgres, Redis, and MinIO (with
its bucket created by a post-install Job) — and composes the relay's
BUZZ_S3_ENDPOINT plus autogenerated credentials automatically. No external services required. The quickstart=true flag is an
intent marker surfaced in NOTES.txt; the bundled services are opted in via the
four *.enabled flags above (see ci/quickstart-values.yaml for the exact set
CI installs). Eval-only: every bundled service is a single replica with no HA.
Production (GitOps)
The chart is designed for ArgoCD and Flux. Both render charts with helm template, in which mode Helm's lookup function returns empty — any chart-side randAlphaNum call would regenerate secrets on every sync. The chart-managed Secret path is only safe for helm install / helm upgrade.
Production deploys MUST use secrets.existingSecret:. The Secret is consumed for any keys present and ignored for keys missing — extras are harmless.
See:
examples/argocd-app.yaml— ArgoCD Applicationexamples/flux-helmrelease.yaml— Flux HelmRelease v2examples/secret-sample.yaml— Secret schema
Required inputs
| Key | What | When required |
|---|---|---|
relayUrl |
Public wss:// URL clients connect to |
Always |
ownerPubkey |
64-char lowercase hex Nostr pubkey of the relay operator | When relay.requireRelayMembership=true (default) |
secrets.existingSecret |
Name of pre-created Secret | Production / GitOps |
externalPostgresql.url / externalRedis.url / s3.endpoint |
External service URLs | Production — when the matching bundled service is disabled (the default) |
The chart fails at helm install / helm template time with a clear message if any of these are missing or malformed (see templates/_validate.tpl).
Device pairing relay
The chart can run Buzz's stateless pairing WebSocket relay as an independent Deployment and Service using the same image as the main relay:
pairingRelay:
enabled: true
url: wss://pairing.example.com
pairingRelay.url is advertised in the main relay's NIP-11 document so Buzz
clients connect directly to the dedicated endpoint. The chart does not create
an Ingress or HTTPRoute for the pairing Service; route the public hostname to
<release>-buzz-pairing:5000 with your platform's ingress configuration.
HA (production)
replicaCount > 1 hard-requires Redis:
- Redis (
redis.enabled=true,externalRedis.url, orREDIS_URLinexistingSecret) — forbuzz-pubsubfan-out
It does not require ReadWriteMany git storage. Git ref/object state is object-store-backed (each request hydrates an ephemeral repo from S3-compatible storage; writer serialization is the object-store pointer CAS — see docs/git-on-object-storage.md), and repo-name uniqueness lives in Postgres. Each replica can use its own ReadWriteOnce volume; no shared filesystem is needed.
The chart template-fails if the Redis invariant is broken at replicaCount > 1. No silent degradation.
Relay autoscaling
The optional HPA scales the relay on the larger recommendation from CPU or average active WebSockets per pod:
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 15
targetCPUUtilizationPercentage: 65
websocketMetricEnabled: true
websocketMetricName: buzz_ws_connections_active
targetWebsocketConnections: 5000
CPU scaling requires Kubernetes Metrics Server. Set websocketMetricEnabled: false
for a CPU-only HPA. WebSocket scaling additionally requires a custom-metrics
adapter (for example Prometheus Adapter) configured to expose the relay's
buzz_ws_connections_active gauge as a pod metric with the name in
websocketMetricName. The chart creates the HPA but deliberately does not
install or configure a cluster-wide metrics adapter. Scale-down is gradual by
default so long-lived WebSocket connections have time to drain.
Upgrades
Schema migrations are embedded in the relay binary via sqlx::migrate! and run at startup, gated by BUZZ_AUTO_MIGRATE (default true). Multiple replicas race-safely behind a Postgres advisory lock. helm upgrade is the entire upgrade procedure.
If you prefer decoupling migrations from serving, set migrate.autoMigrate=false. In that mode the chart does not run migrations for you — you own running buzz-admin migrate (separate Pod / one-shot Job) against the database before every helm install / helm upgrade. Readiness probes only verify DB connectivity, not schema freshness, so a pod will appear healthy against an unmigrated schema and fail under load. A pre-upgrade Helm Job for this is on the chart roadmap; the values knob migrate.preUpgradeJob.enabled is reserved.
Backups
Save these. Losing any of them is data loss. See NOTES.txt printed by helm install for the live list:
BUZZ_RELAY_PRIVATE_KEY— relay identity. Rotating it = new identity (federation peers will not recognize the relay).- PostgreSQL database — the canonical event store.
- S3 bucket — media blobs (chart default bucket:
buzz-media). - Git PVC — repo on-disk state served by the relay's git endpoint.
- Owner private key — held by the operator, not by this chart. Restore by re-installing with the same
ownerPubkey.
Honest limitations (v1)
- Bundled MinIO is eval-only. The quickstart profile runs an in-cluster
MinIO (single replica, no HA,
lookup-autogenerated credentials) so the relay starts with zero external object storage. Production leavesminio.enabledoff and pointss3.endpoint(orBUZZ_S3_*inexistingSecret) at managed S3-compatible storage. The bundled Deployment is not GitOps-safe and is not intended for production traffic. - Minimal-mode is not yet supported. The relay's
BUZZ_PUBSUB=local/ filesystem media paths are upstream work in progress — even quickstart currently stands up real Redis and S3 rather than the relay's single-node fallbacks. (Full-text search already runs in Postgres, so no separate search service is provisioned.) - Cosign signing of the published chart is a follow-up (the relay image is
attested via
actions/attest-build-provenance; the chart is not yet). The chart itself is published to GHCR — see Releasing.
Releasing
The chart is published to GHCR as an OCI artifact at
oci://ghcr.io/block/buzz/charts/buzz by the helm chart workflow
(.github/workflows/helm-chart.yml), versioned independently of the desktop app
and the relay image via its own chart-v* tags. Every PR/main push still
lints, unit-tests, and render-checks the chart; only a chart-v* tag publishes,
so an in-progress main can never overwrite a released version.
To cut a release, push a chart-release/<version> branch whose <version>
matches Chart.yaml's version; merging it auto-tags chart-v<version> and
dispatches the publish job (same lane machinery as the desktop and relay
releases — see .github/workflows/auto-tag-on-release-pr-merge.yml). The publish
job fails loudly if the tag version and Chart.yaml version disagree.
Development
# Render every fixture
for f in ci/*-values.yaml tests/fixtures/*-values.yaml; do
helm template buzz . -f "$f" >/dev/null && echo "ok: $f"
done
# Unit tests
helm plugin install https://github.com/helm-unittest/helm-unittest
helm unittest .
# Lint
helm dependency build .
ct lint --config ../../../ct.yaml --charts .