Wire Postgres search backend through chart

Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
(cherry picked from commit 86368981635df8b2f050069827b70c7ceea0e5fd)
Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
This commit is contained in:
npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta
2026-06-24 19:27:35 -04:00
parent 5304a9b242
commit 4a771fd08c
23 changed files with 232 additions and 116 deletions
+8 -4
View File
@@ -159,7 +159,7 @@ impl Config {
"BUZZ_SEARCH_BACKEND={bad:?} (expected `typesense`, `postgres`, or `disabled`)"
))
})?,
Err(_) => buzz_search::SearchBackend::Typesense,
Err(_) => buzz_search::SearchBackend::Postgres,
};
let relay_url =
@@ -562,17 +562,21 @@ mod tests {
}
#[test]
fn search_backend_defaults_to_typesense() {
fn search_backend_defaults_to_postgres() {
let _guard = ENV_MUTEX.lock().unwrap();
std::env::remove_var("BUZZ_SEARCH_BACKEND");
let config = Config::from_env().expect("default config");
assert_eq!(config.search_backend, buzz_search::SearchBackend::Typesense);
assert_eq!(config.search_backend, buzz_search::SearchBackend::Postgres);
}
#[test]
fn search_backend_parses_postgres_and_disabled() {
fn search_backend_parses_typesense_postgres_and_disabled() {
let _guard = ENV_MUTEX.lock().unwrap();
std::env::set_var("BUZZ_SEARCH_BACKEND", "typesense");
let config = Config::from_env().expect("config");
assert_eq!(config.search_backend, buzz_search::SearchBackend::Typesense);
std::env::set_var("BUZZ_SEARCH_BACKEND", "postgres");
let config = Config::from_env().expect("config");
assert_eq!(config.search_backend, buzz_search::SearchBackend::Postgres);
+14 -6
View File
@@ -1250,13 +1250,21 @@ mod tests {
.await
.expect("pubsub manager"),
);
let audit = buzz_audit::AuditService::new(pool);
let audit = buzz_audit::AuditService::new(pool.clone());
let auth = buzz_auth::AuthService::new(config.auth.clone());
let search = buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
});
let search = match config.search_backend {
buzz_search::SearchBackend::Typesense => {
buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
})
}
buzz_search::SearchBackend::Postgres => {
buzz_search::SearchService::with_postgres(pool.clone())
}
buzz_search::SearchBackend::Disabled => buzz_search::SearchService::disabled(),
};
let workflow_engine = Arc::new(buzz_workflow::WorkflowEngine::new(
db.clone(),
buzz_workflow::WorkflowConfig::default(),
@@ -443,13 +443,21 @@ mod tests {
.await
.ok()?,
);
let audit = buzz_audit::AuditService::new(pool);
let audit = buzz_audit::AuditService::new(pool.clone());
let auth = buzz_auth::AuthService::new(config.auth.clone());
let search = buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
});
let search = match config.search_backend {
buzz_search::SearchBackend::Typesense => {
buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
})
}
buzz_search::SearchBackend::Postgres => {
buzz_search::SearchService::with_postgres(pool.clone())
}
buzz_search::SearchBackend::Disabled => buzz_search::SearchService::disabled(),
};
let workflow_engine = Arc::new(buzz_workflow::WorkflowEngine::new(
db.clone(),
buzz_workflow::WorkflowConfig::default(),
@@ -507,13 +507,21 @@ mod tests {
.await
.expect("pubsub manager"),
);
let audit = buzz_audit::AuditService::new(pool);
let audit = buzz_audit::AuditService::new(pool.clone());
let auth = buzz_auth::AuthService::new(config.auth.clone());
let search = buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
});
let search = match config.search_backend {
buzz_search::SearchBackend::Typesense => {
buzz_search::SearchService::new(buzz_search::SearchConfig {
url: config.typesense_url.clone(),
api_key: config.typesense_key.clone(),
collection: "events".to_string(),
})
}
buzz_search::SearchBackend::Postgres => {
buzz_search::SearchService::with_postgres(pool.clone())
}
buzz_search::SearchBackend::Disabled => buzz_search::SearchService::disabled(),
};
let workflow_engine = std::sync::Arc::new(buzz_workflow::WorkflowEngine::new(
db.clone(),
buzz_workflow::WorkflowConfig::default(),
+26 -22
View File
@@ -1,13 +1,13 @@
# Buzz Helm Chart
[Buzz](https://github.com/block/buzz) is a Nostr-based messaging platform for humanagent collaboration: a single relay binary serving WebSocket + REST + web UI, backed by PostgreSQL, Redis, Typesense, and S3-compatible object storage.
[Buzz](https://github.com/block/buzz) is a Nostr-based messaging platform for humanagent collaboration: a single relay binary serving WebSocket + REST + web UI, backed by PostgreSQL, Redis, and S3-compatible object storage. NIP-50 search defaults to Postgres full-text search, with Typesense available as a fallback backend.
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/Typesense/S3, `secrets.existingSecret:`, no chart-side autogen, HA-capable (`replicaCount ≥ 2`) |
| **Quickstart** (eval) | Eval, single-node, one-off demo | In-cluster Postgres + Redis + MinIO + Typesense subcharts/Deployments, chart auto-generates relay + service secrets, single replica |
| **Production** (default) | Self-hosted multi-tenant, regulated, or GitOps-managed | External managed Postgres/Redis/S3, Postgres FTS search by default, `secrets.existingSecret:`, no chart-side autogen, HA-capable (`replicaCount ≥ 2`) |
| **Quickstart** (eval) | Eval, single-node, one-off demo | In-cluster Postgres + Redis + MinIO, chart auto-generates relay + service secrets, single replica |
## Quickstart (eval only)
@@ -18,18 +18,18 @@ helm install buzz oci://ghcr.io/block/buzz/charts/buzz --version 0.1.0 \
--set postgresql.enabled=true \
--set redis.enabled=true \
--set minio.enabled=true \
--set typesense.enabled=true \
--set relayUrl=wss://buzz.example.com \
--set ownerPubkey=<64-char-hex-pubkey>
```
This brings up **everything in-cluster** — Postgres, Redis, MinIO (with its
bucket created by a post-install Job), and Typesense — and composes the relay's
`BUZZ_S3_ENDPOINT` / `TYPESENSE_URL` 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.
This brings up the required quickstart dependencies 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.
Search defaults to Postgres FTS (`search.backend=postgres`), so no Typesense
service is required. The `quickstart=true` flag is an intent marker surfaced in
NOTES.txt; the bundled services are opted in via the per-service `*.enabled`
flags (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)
@@ -50,7 +50,7 @@ See:
| `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` / `typesense.url` / `s3.endpoint` | External service URLs | Production — when the matching bundled service is disabled (the default) |
| `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`).
@@ -81,17 +81,21 @@ Save these. Losing any of them is data loss. See NOTES.txt printed by `helm inst
## Honest limitations (v1)
- **Bundled MinIO + Typesense are eval-only.** The quickstart profile runs an
in-cluster MinIO and Typesense (single replica, no HA, `lookup`-autogenerated
credentials) so the relay starts with zero external services. Production
leaves `minio.enabled` / `typesense.enabled` off and points `s3.endpoint` +
`typesense.url` (or `BUZZ_S3_*` / `TYPESENSE_URL` in `existingSecret`) at
managed S3-compatible storage and Typesense. The bundled Deployments are not
GitOps-safe and are not intended for production traffic.
- **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 dependencies. Production leaves
`minio.enabled` off and points `s3.endpoint` (or `BUZZ_S3_*` in
`existingSecret`) at managed S3-compatible storage. The bundled Deployment is
not GitOps-safe and is not intended for production traffic.
- **Typesense is a fallback search backend.** Default search is Postgres FTS
(`search.backend=postgres`). To use Typesense instead, set
`search.backend=typesense` and provide either `typesense.url`/`apiKey`,
`TYPESENSE_URL`/`TYPESENSE_API_KEY` in `secrets.existingSecret`, or
`typesense.enabled=true` for eval-only in-cluster Typesense.
- **Minimal-mode is not yet supported.** The relay's `BUZZ_PUBSUB=local` /
`BUZZ_SEARCH=pg` / filesystem media paths are upstream work in progress —
even quickstart currently stands up real Redis, Typesense, and S3 rather than
the relay's single-node fallbacks.
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.
- **OCI publish to GHCR + cosign signing** is a follow-up PR. For now, install the chart from source: `helm install buzz ./deploy/charts/buzz` after cloning the repo.
## Development
+4 -4
View File
@@ -1,7 +1,9 @@
# Quickstart / eval: subcharts on, autogen secrets, single replica.
# This is the scenario `ct install` exercises against a kind cluster — it
# spins up postgres + redis + minio + typesense in-cluster so the relay can
# actually start and pass its S3 conformance probe.
# spins up postgres + redis + minio in-cluster so the relay can actually
# start and pass its S3 conformance probe. Search defaults to Postgres FTS, so
# the quickstart no longer needs in-cluster Typesense unless explicitly testing
# search.backend=typesense.
quickstart: true
postgresql:
enabled: true
@@ -9,8 +11,6 @@ redis:
enabled: true
minio:
enabled: true
typesense:
enabled: true
relayUrl: wss://buzz.test.local
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000001"
relay:
+2 -3
View File
@@ -37,9 +37,8 @@ spec:
externalRedis:
url: ""
typesense:
url: "http://typesense.buzz.svc.cluster.local:8108"
# apiKey lives in buzz-secrets
search:
backend: postgres
s3:
endpoint: "https://s3.us-east-1.amazonaws.com"
@@ -37,9 +37,8 @@ spec:
secrets:
existingSecret: buzz-secrets
typesense:
url: "http://typesense.buzz.svc.cluster.local:8108"
# apiKey lives in buzz-secrets
search:
backend: postgres
s3:
endpoint: "https://s3.us-east-1.amazonaws.com"
@@ -11,6 +11,7 @@
# REDIS_URL — redis://... (required when replicaCount > 1)
# TYPESENSE_URL
# TYPESENSE_API_KEY
# Only required when Helm value search.backend=typesense.
# BUZZ_S3_ACCESS_KEY
# BUZZ_S3_SECRET_KEY
apiVersion: v1
+3 -3
View File
@@ -26,19 +26,19 @@
──────────────────────────────────────────────────────────────────────────────
Profile
──────────────────────────────────────────────────────────────────────────────
{{ if or .Values.postgresql.enabled .Values.redis.enabled .Values.minio.enabled .Values.typesense.enabled }}
{{ if or .Values.postgresql.enabled .Values.redis.enabled .Values.minio.enabled (and .Values.typesense.enabled (eq (include "buzz.searchBackend" .) "typesense")) }}
⚠ QUICKSTART / EVALUATION PROFILE
{{ if .Values.postgresql.enabled }}- In-cluster Postgres subchart (CloudPirates){{ end }}
{{ if .Values.redis.enabled }}- In-cluster Redis subchart (CloudPirates){{ end }}
{{ if .Values.minio.enabled }}- In-cluster MinIO (eval-only, single replica; bucket "{{ .Values.s3.bucket }}" created by post-install Job){{ end }}
{{ if .Values.typesense.enabled }}- In-cluster Typesense (eval-only, single replica){{ end }}
{{ if and .Values.typesense.enabled (eq (include "buzz.searchBackend" .) "typesense") }}- In-cluster Typesense (eval-only, single replica){{ end }}
- Chart auto-generates secrets via the `lookup` pattern. This is NOT
GitOps-safe — secrets will silently rotate under ArgoCD/Flux. For
production, see examples/argocd-app.yaml or examples/flux-helmrelease.yaml.
{{ else }}
✓ PRODUCTION PROFILE
External Postgres, Redis (if enabled), Typesense, S3.
External Postgres, Redis (if enabled), S3; search backend: {{ include "buzz.searchBackend" . }}.
{{ if .Values.secrets.existingSecret }}- Secrets sourced from: {{ .Values.secrets.existingSecret }}{{ end }}
{{ end }}
@@ -116,6 +116,12 @@ secrets.existingSecret, use that. Otherwise use the chart-managed one.
{{- end -}}
{{- end -}}
{{/* Search backend flag. Defaults to Postgres FTS; Typesense remains opt-in fallback. */}}
{{- define "buzz.searchBackend" -}}
{{- $search := default dict .Values.search -}}
{{- default "postgres" $search.backend -}}
{{- end -}}
{{/* In-cluster Typesense URL, used when typesense.enabled and url unset. */}}
{{- define "buzz.typesenseUrl" -}}
{{- if .Values.typesense.url -}}
+3 -3
View File
@@ -50,9 +50,9 @@ surface at template time regardless of which manifest helm renders first.
{{- fail "Postgres source missing: enable postgresql.enabled=true, set externalPostgresql.url, or provide secrets.existingSecret with key DATABASE_URL." -}}
{{- end -}}
{{/* Typesense source must exist somewhere */}}
{{- if not (or .Values.typesense.enabled .Values.typesense.url .Values.secrets.existingSecret) -}}
{{- fail "Typesense source missing: enable typesense.enabled=true (quickstart in-cluster), set typesense.url + typesense.apiKey, or provide secrets.existingSecret with keys TYPESENSE_URL + TYPESENSE_API_KEY." -}}
{{/* Typesense source is required only when search.backend=typesense. */}}
{{- if and (eq (include "buzz.searchBackend" .) "typesense") (not (or .Values.typesense.enabled .Values.typesense.url .Values.secrets.existingSecret)) -}}
{{- fail "Typesense source missing for search.backend=typesense: enable typesense.enabled=true (quickstart in-cluster), set typesense.url + typesense.apiKey, or provide secrets.existingSecret with keys TYPESENSE_URL + TYPESENSE_API_KEY." -}}
{{- end -}}
{{/* S3 / object-storage source must exist somewhere (relay hard-fails its
@@ -1,4 +1,5 @@
{{- include "buzz.validate" . -}}
{{- $searchBackend := include "buzz.searchBackend" . -}}
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -80,6 +81,7 @@ spec:
- { name: BUZZ_REQUIRE_RELAY_MEMBERSHIP, value: {{ .Values.relay.requireRelayMembership | quote }} }
- { name: BUZZ_ALLOW_NIP_OA_AUTH, value: {{ .Values.relay.allowNipOaAuth | quote }} }
- { name: BUZZ_PUBKEY_ALLOWLIST, value: {{ .Values.relay.pubkeyAllowlist | quote }} }
- { name: BUZZ_SEARCH_BACKEND, value: {{ $searchBackend | quote }} }
{{- if .Values.relay.corsOrigins }}
- { name: BUZZ_CORS_ORIGINS, value: {{ join "," .Values.relay.corsOrigins | quote }} }
{{- end }}
@@ -130,6 +132,7 @@ spec:
name: {{ include "buzz.envSecretName" . }}
key: REDIS_URL
optional: {{ and (eq (.Values.replicaCount | int) 1) (not .Values.redis.enabled) (not .Values.externalRedis.url) }}
{{- if eq $searchBackend "typesense" }}
- name: TYPESENSE_URL
valueFrom:
secretKeyRef:
@@ -140,6 +143,7 @@ spec:
secretKeyRef:
name: {{ include "buzz.envSecretName" . }}
key: TYPESENSE_API_KEY
{{- end }}
- name: BUZZ_S3_ACCESS_KEY
valueFrom:
secretKeyRef:
@@ -4,7 +4,7 @@ single replica, no TLS, API key from the chart-managed Secret. Production
deploys leave typesense.enabled=false and point typesense.url/apiKey (or
secrets.existingSecret) at a managed Typesense service.
*/ -}}
{{- if .Values.typesense.enabled -}}
{{- if and .Values.typesense.enabled (eq (include "buzz.searchBackend" .) "typesense") -}}
{{- if .Values.secrets.existingSecret -}}
{{- fail "typesense.enabled=true (quickstart) is incompatible with secrets.existingSecret. Quickstart autogenerates the Typesense key in the chart-managed Secret; for external Typesense set typesense.enabled=false and provide TYPESENSE_URL/TYPESENSE_API_KEY." -}}
{{- end -}}
@@ -73,8 +73,9 @@ data:
REDIS_URL: {{ .Values.externalRedis.url | b64enc | quote }}
{{- end }}
{{- /* Typesense — bundled (quickstart) composes URL + autogen key; else
pass through external values. */}}
{{- /* Typesense — only when search.backend=typesense. Bundled quickstart
composes URL + autogen key; else pass through external values. */}}
{{- if eq (include "buzz.searchBackend" .) "typesense" }}
{{- if .Values.typesense.enabled }}
{{- $tsKey := "" }}
{{- if (index $existingData "TYPESENSE_API_KEY") }}
@@ -94,6 +95,7 @@ data:
TYPESENSE_API_KEY: {{ .Values.typesense.apiKey | b64enc | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- /* S3 creds — bundled MinIO (quickstart) autogenerates; else pass
through external values. */}}
@@ -9,8 +9,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -29,8 +27,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -47,8 +43,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -68,8 +62,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -1,6 +1,6 @@
suite: quickstart bundled services
# The dev quickstart must stand up MinIO + Typesense in-cluster so the relay's
# startup S3 conformance probe passes with zero external dependencies.
# The dev quickstart must stand up MinIO in-cluster so the relay's startup S3
# conformance probe passes. Typesense is only bundled when search.backend=typesense.
templates:
- templates/quickstart-minio.yaml
- templates/quickstart-minio-init.yaml
@@ -17,6 +17,7 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
search.backend: typesense
typesense.enabled: true
minio.enabled: true
asserts:
@@ -40,6 +41,7 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
search.backend: typesense
typesense.enabled: true
minio.enabled: true
asserts:
@@ -58,6 +60,7 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
search.backend: typesense
typesense.enabled: true
minio.enabled: true
asserts:
@@ -76,6 +79,7 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
search.backend: typesense
typesense.enabled: true
minio.enabled: true
asserts:
@@ -103,6 +107,7 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
search.backend: typesense
typesense.enabled: true
minio.enabled: true
asserts:
@@ -10,8 +10,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
typesense.url: http://ts:8108
typesense.apiKey: k
minio.enabled: true
secrets.existingSecret: "buzz-secrets"
asserts:
@@ -28,6 +26,7 @@ tests:
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
search.backend: typesense
typesense.enabled: true
secrets.existingSecret: "buzz-secrets"
asserts:
+54 -5
View File
@@ -8,14 +8,12 @@ templates:
- templates/service.yaml
- templates/pvc-git.yaml
tests:
- it: renders cleanly in production profile (external pg/redis/typesense)
- it: renders cleanly in production profile (external pg/redis/s3, postgres search)
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
externalRedis.url: redis://h:6379
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -39,8 +37,6 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
externalRedis.url: redis://h:6379
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -55,3 +51,56 @@ tests:
path: spec.accessModes[0]
value: ReadWriteMany
template: templates/pvc-git.yaml
- it: postgres backend does not require a Typesense source
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: BUZZ_SEARCH_BACKEND
value: "postgres"
template: templates/deployment.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: TYPESENSE_URL
template: templates/deployment.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: TYPESENSE_API_KEY
template: templates/deployment.yaml
- it: disabled backend does not require a Typesense source
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
search.backend: disabled
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: BUZZ_SEARCH_BACKEND
value: "disabled"
template: templates/deployment.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: TYPESENSE_URL
template: templates/deployment.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: TYPESENSE_API_KEY
template: templates/deployment.yaml
+41 -12
View File
@@ -8,8 +8,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -31,8 +29,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -47,8 +43,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -70,8 +64,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -93,8 +85,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
@@ -106,6 +96,47 @@ tests:
value: "true"
template: templates/deployment.yaml
- it: postgres search Secret omits Typesense keys
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- notExists:
path: data.TYPESENSE_URL
template: templates/secret-chart.yaml
- notExists:
path: data.TYPESENSE_API_KEY
template: templates/secret-chart.yaml
- it: typesense search Secret includes Typesense keys
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
search.backend: typesense
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
asserts:
- equal:
path: data.TYPESENSE_URL
decodeBase64: true
value: http://ts:8108
template: templates/secret-chart.yaml
- equal:
path: data.TYPESENSE_API_KEY
decodeBase64: true
value: k
template: templates/secret-chart.yaml
- it: quickstart composes DATABASE_URL/REDIS_URL at the actual subchart Service hosts
release:
name: rel
@@ -114,8 +145,6 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
postgresql.enabled: true
redis.enabled: true
typesense.url: http://ts:8108
typesense.apiKey: k
s3.endpoint: http://minio:9000
s3.accessKey: a
s3.secretKey: s
+2 -17
View File
@@ -7,8 +7,6 @@ tests:
relayUrl: ""
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- failedTemplate:
errorMessage: "relayUrl is required: set --set relayUrl=wss://your.domain"
@@ -18,8 +16,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: ""
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- failedTemplate:
errorPattern: "ownerPubkey is required when relay.requireRelayMembership=true"
@@ -29,8 +25,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "NOTAHEX"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- failedTemplate:
errorPattern: "ownerPubkey: Does not match pattern"
@@ -40,8 +34,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
replicaCount: 3
asserts:
- failedTemplate:
@@ -53,8 +45,6 @@ tests:
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
externalRedis.url: redis://h:6379
typesense.url: http://ts:8108
typesense.apiKey: k
replicaCount: 3
persistence.git.accessMode: ReadWriteOnce
asserts:
@@ -66,8 +56,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
ingress.enabled: true
httproute.enabled: true
asserts:
@@ -78,17 +66,16 @@ tests:
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- failedTemplate:
errorPattern: "Postgres source missing"
- it: fails when Typesense source is missing
- it: fails when Typesense source is missing for typesense backend
set:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
search.backend: typesense
asserts:
- failedTemplate:
errorPattern: "Typesense source missing"
@@ -98,8 +85,6 @@ tests:
relayUrl: wss://buzz.example.com
ownerPubkey: "0000000000000000000000000000000000000000000000000000000000000000"
externalPostgresql.url: postgres://u:p@h:5432/d
typesense.url: http://ts:8108
typesense.apiKey: k
asserts:
- failedTemplate:
errorPattern: "S3/object-storage source missing"
+7
View File
@@ -162,6 +162,13 @@
"url": { "type": "string", "pattern": "^(rediss?://.+)?$" }
}
},
"search": {
"type": "object",
"additionalProperties": false,
"properties": {
"backend": { "type": "string", "enum": ["postgres", "typesense", "disabled"] }
}
},
"typesense": {
"type": "object",
"additionalProperties": false,
+14 -7
View File
@@ -6,11 +6,11 @@
# refs everywhere, no chart-side autogeneration, GitOps-safe (ArgoCD/Flux).
# HA-ready: replicaCount >= 2 (requires Redis and RWX storage for git).
#
# QUICKSTART — bundles in-cluster Postgres + Redis + MinIO + Typesense and
# auto-generates relay secrets via the `lookup` pattern (NOT GitOps-safe —
# see README), single replica, evaluation only. Opt in by enabling each
# bundled service: postgresql.enabled, redis.enabled, minio.enabled,
# typesense.enabled. See ci/quickstart-values.yaml and the README.
# QUICKSTART — bundles in-cluster Postgres + Redis + MinIO and auto-generates
# relay secrets via the `lookup` pattern (NOT GitOps-safe — see README),
# single replica, evaluation only. Opt in by enabling each bundled service:
# postgresql.enabled, redis.enabled, minio.enabled. Typesense is optional only
# when search.backend=typesense. See ci/quickstart-values.yaml and the README.
#
# See examples/argocd-app.yaml and examples/flux-helmrelease.yaml for the
# canonical GitOps configurations.
@@ -56,8 +56,8 @@ ownerPubkey: ""
# BUZZ_GIT_HOOK_HMAC_SECRET — 32+ chars; required when replicaCount > 1
# DATABASE_URL — full Postgres URL (preferred over externalPostgresql.url)
# REDIS_URL — full Redis URL with auth
# TYPESENSE_URL — Typesense base URL
# TYPESENSE_API_KEY — Typesense API key
# TYPESENSE_URL — Typesense base URL (only when search.backend=typesense)
# TYPESENSE_API_KEY — Typesense API key (only when search.backend=typesense)
# BUZZ_S3_ACCESS_KEY — S3 access key
# BUZZ_S3_SECRET_KEY — S3 secret key
secrets:
@@ -211,6 +211,13 @@ redis:
externalRedis:
url: "" # redis://:pass@host:6379
# ── Search ───────────────────────────────────────────────────────────────────
# Postgres FTS is the default. Set backend=typesense only while using the
# fallback Typesense index; set backend=disabled to fail NIP-50 search closed
# (queries return no hits, without weakening auth/channel filtering).
search:
backend: postgres # postgres | typesense | disabled
# ── Typesense ────────────────────────────────────────────────────────────────
# Production: point url/apiKey at an external Typesense service (or supply
# TYPESENSE_URL/TYPESENSE_API_KEY via secrets.existingSecret).