Add optional standalone pairing relay to Helm chart (#1799)

Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Tyler
2026-07-13 11:36:04 -04:00
committed by GitHub
co-authored by npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757
parent d38a7ef775
commit 9b47c8548f
15 changed files with 454 additions and 64 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ description: |
PostgreSQL and Redis. Configurable for single-node evaluation
(subcharts on) and HA production (external services, existingSecret).
type: application
version: 0.1.2
version: 0.1.3
appVersion: "0.1.0"
home: https://github.com/block/buzz
sources:
+16
View File
@@ -52,6 +52,22 @@ See:
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:
```yaml
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:
@@ -121,3 +121,8 @@ secrets.existingSecret, use that. Otherwise use the chart-managed one.
{{- include "buzz.minioEndpoint" . -}}
{{- end -}}
{{- end -}}
{{- define "buzz.pairingRelaySelectorLabels" -}}
{{ include "buzz.selectorLabels" . }}
app.kubernetes.io/component: pairing-relay
{{- end -}}
@@ -46,6 +46,11 @@ surface at template time regardless of which manifest helm renders first.
{{- end -}}
{{- end -}}
{{/* Pairing relay deployment must have an advertised public URL. */}}
{{- if and .Values.pairingRelay.enabled (not .Values.pairingRelay.url) -}}
{{- fail "pairingRelay.url is required when pairingRelay.enabled=true" -}}
{{- end -}}
{{/* ingress + httproute mutually exclusive */}}
{{- if and .Values.ingress.enabled .Values.httproute.enabled -}}
{{- fail "ingress.enabled and httproute.enabled cannot both be true — choose one." -}}
@@ -69,6 +69,9 @@ spec:
- { name: BUZZ_HEALTH_PORT, value: {{ .Values.service.healthPort | quote }} }
- { name: BUZZ_METRICS_PORT, value: {{ .Values.service.metricsPort | quote }} }
- { name: RELAY_URL, value: {{ .Values.relayUrl | quote }} }
{{- if .Values.pairingRelay.url }}
- { name: BUZZ_PAIRING_RELAY_URL, value: {{ .Values.pairingRelay.url | quote }} }
{{- end }}
- { name: BUZZ_MEDIA_BASE_URL, value: {{ include "buzz.mediaBaseUrl" . | quote }} }
# ── Behavior ─────────────────────────────────────────────
@@ -0,0 +1,72 @@
{{- include "buzz.validate" . -}}
{{- if .Values.pairingRelay.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "buzz.fullname" . }}-pairing
labels:
{{- include "buzz.labels" . | nindent 4 }}
app.kubernetes.io/component: pairing-relay
spec:
replicas: {{ .Values.pairingRelay.replicaCount }}
selector:
matchLabels:
{{- include "buzz.pairingRelaySelectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "buzz.pairingRelaySelectorLabels" . | nindent 8 }}
{{- with .Values.pairingRelay.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.pairingRelay.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
securityContext:
{{- toYaml .Values.relay.securityContext | nindent 8 }}
containers:
- name: pairing-relay
image: {{ include "buzz.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/usr/local/bin/buzz-pair-relay"]
securityContext:
{{- toYaml .Values.relay.containerSecurityContext | nindent 12 }}
env:
- name: BUZZ_PAIR_RELAY_BIND_ADDR
value: "0.0.0.0:{{ .Values.pairingRelay.service.port }}"
ports:
- name: websocket
containerPort: {{ .Values.pairingRelay.service.port }}
protocol: TCP
readinessProbe:
tcpSocket:
port: websocket
livenessProbe:
tcpSocket:
port: websocket
resources:
{{- toYaml .Values.pairingRelay.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "buzz.fullname" . }}-pairing
labels:
{{- include "buzz.labels" . | nindent 4 }}
app.kubernetes.io/component: pairing-relay
{{- with .Values.pairingRelay.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.pairingRelay.service.type }}
selector:
{{- include "buzz.pairingRelaySelectorLabels" . | nindent 4 }}
ports:
- name: websocket
port: {{ .Values.pairingRelay.service.port }}
targetPort: websocket
protocol: TCP
{{- end }}
@@ -0,0 +1,54 @@
suite: optional pairing relay
templates:
- templates/deployment.yaml
- templates/secret-chart.yaml
- templates/pairing-relay.yaml
- templates/serviceaccount.yaml
tests:
- it: does not render the pairing relay by default
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
externalRedis.url: redis://h:6379
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
asserts:
- hasDocuments:
count: 0
template: templates/pairing-relay.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: BUZZ_PAIRING_RELAY_URL
template: templates/deployment.yaml
- it: renders and advertises the configured pairing relay
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
externalRedis.url: redis://h:6379
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
pairingRelay.enabled: true
pairingRelay.url: wss://pairing.buzz.xyz
asserts:
- equal:
path: kind
value: Deployment
documentIndex: 0
template: templates/pairing-relay.yaml
- equal:
path: kind
value: Service
documentIndex: 1
template: templates/pairing-relay.yaml
- contains:
path: spec.template.spec.containers[0].env
content:
name: BUZZ_PAIRING_RELAY_URL
value: wss://pairing.buzz.xyz
template: templates/deployment.yaml
+25
View File
@@ -230,6 +230,31 @@
"labels": { "type": "object" }
}
},
"pairingRelay": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": { "type": "boolean" },
"url": {
"type": "string",
"pattern": "^(wss?://.+)?$",
"description": "Public WebSocket URL advertised to clients for NIP-AB device pairing."
},
"replicaCount": { "type": "integer", "minimum": 1 },
"service": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer"] },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"annotations": { "type": "object" }
}
},
"podAnnotations": { "type": "object" },
"podLabels": { "type": "object" },
"resources": { "type": "object" }
}
},
"extraManifests": {
"type": "array"
}
+22
View File
@@ -150,6 +150,28 @@ relay:
extraEnv: []
extraEnvFrom: []
# ── Device pairing relay ─────────────────────────────────────────────────────
# Optional, stateless NIP-AB relay. When enabled, the main relay advertises
# pairingRelay.url in NIP-11 and Buzz clients use it instead of the legacy
# same-host /pair convention.
pairingRelay:
enabled: false
url: ""
replicaCount: 1
service:
type: ClusterIP
port: 5000
annotations: {}
podAnnotations: {}
podLabels: {}
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "250m"
memory: "128Mi"
# ── Service ──────────────────────────────────────────────────────────────────
service:
type: ClusterIP