Dependencies
External dependencies and deployment configurations for Berserk (and managing secrets)
Berserk requires PostgreSQL (v17+) for metadata storage and S3-compatible object storage for segment data. The gateway also needs a small set of auth secrets (a cookie signing key plus internal service tokens), which the chart generates automatically by default. Depending on the features you enable you may also need an ingest token, a separate auth database, and an OIDC client secret. (The Git-synced query library's credentials are configured at runtime in the admin UI, not as a chart-managed Secret.)
The table below lists every Kubernetes Secret the chart uses. For each one you choose whether the Helm chart manages it for you (managed: true) or you create it yourself with kubectl (managed: false) — the per-secret sections that follow show both paths. The default differs per secret, as noted in the last column.
| Secret | Purpose | When needed | Helm-managed |
|---|---|---|---|
postgres-credentials | Metadata DB connection string (meta, ui) | Always | Yes — off by default |
s3-credentials | Object-store access keys (query, ingest, janitor, nursery) | Always, unless EKS/IRSA | Yes — off by default |
gateway-secrets | Cookie signing key + internal service tokens (gateway, ui, admin-ui, permissions) | Always | Yes — on by default |
auth-postgres-credentials | Connection string for a separate auth-stack database | Only with a dedicated auth DB (otherwise shares postgres-credentials) | Yes — off by default |
gateway-oidc-secrets | OIDC client_secret from your identity provider (gateway, admin-ui) | Only with OIDC SSO | No (external only) |
ingest-token | Default ingest authentication token | Optional (ingest auth) | Yes — on by default |
If you run helm upgrade/install directly, you can use managed: true,
otherwise, like deploying via Argo or similar, it is best to create the
secrets externally.
The reason is that when installing the helm chart, it needs to read whether an existing secret exists or not, which for example is not supported by Argo.
PostgreSQL Credentials
The meta service needs a PostgreSQL (v18+) connection string.
global:
postgresCredentials:
managed: truehelm install berserk berserk/berserk \
--namespace bzrk \
-f values.yaml \
--set global.postgresCredentials.databaseUrl="postgres://<user>:<password>@host:5432/berserk"Create the secret before installing:
kubectl create namespace bzrk
kubectl create secret generic postgres-credentials \
--namespace bzrk \
--from-literal=database_url="postgres://<user>:<password>@host:5432/berserk"global:
postgresCredentials:
managed: false # default
secretName: "postgres-credentials"helm install berserk berserk/berserk \
--namespace bzrk \
-f values.yamlS3 Object Store
Query, ingest, janitor, and nursery services all need access to an S3-compatible object store (AWS S3, MinIO, R2, etc.).
All approaches require the storage location in your values file:
global:
storage:
endpoint: "https://s3.eu-central-1.amazonaws.com"
bucket: "your-berserk-bucket"
region: "eu-central-1"global:
s3Credentials:
managed: truehelm install berserk berserk/berserk \
--namespace bzrk \
-f values.yaml \
--set global.s3Credentials.accessKeyId="AKIA..." \
--set global.s3Credentials.secretAccessKey="secret..."Create the secret before installing:
kubectl create namespace bzrk
kubectl create secret generic s3-credentials \
--namespace bzrk \
--from-literal=AWS_ACCESS_KEY_ID=<key> \
--from-literal=AWS_SECRET_ACCESS_KEY=<secret>global:
s3Credentials:
managed: false # default
secretName: "s3-credentials"helm install berserk berserk/berserk \
--namespace bzrk \
-f values.yamlOn EKS, S3 credentials are handled automatically through IAM Roles for Service Accounts (IRSA). No S3 secret is needed — Berserk picks up access from the pod's IAM role.
IAM Role Setup — create an IAM role with S3 permissions and associate it with a Kubernetes service account. If you use Terraform:
module "irsa" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
role_name = "berserk-s3-access"
oidc_providers = {
main = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["bzrk:berserk"]
}
}
}The IAM policy needs at minimum s3:GetObject, s3:PutObject, s3:ListBucket, and s3:DeleteObject on your data bucket.
global:
s3Credentials:
managed: false
serviceAccountName: "berserk"The serviceAccountName is applied to all Berserk pod specs, which lets the AWS SDK resolve credentials from the IRSA-annotated service account automatically.
helm install berserk berserk/berserk \
--namespace bzrk \
-f values.yamlGateway Auth Secrets
The gateway signs session cookies and authenticates its internal calls to the ui, admin-ui, and permissions services. These values live in one Secret (gateway-secrets) with three keys:
cookie_signing_key— signs session cookies (must be at least 64 bytes)service_token— presented on theX-Bzrk-Service-Tokenheader soui/admin-uitrust the identity the gateway injectspermissions_service_token— authenticates calls to the permissions service
Unlike the other secrets, this one is Helm-managed by default: the chart generates strong random values on first install and preserves them across upgrades, so most installs need no action here. Create it yourself only when integrating with an external secret manager, or when the values must survive a full uninstall/reinstall.
No action needed — the chart creates gateway-secrets with random values:
gateway:
secrets:
managed: true # defaultTo pin your own values instead of random ones, set cookieSigningKey, serviceToken, and permissionsServiceToken under gateway.secrets.
Create the secret before installing:
kubectl create namespace bzrk
kubectl create secret generic gateway-secrets \
--namespace bzrk \
--from-literal=cookie_signing_key="$(openssl rand -hex 64)" \
--from-literal=service_token="$(openssl rand -hex 32)" \
--from-literal=permissions_service_token="$(openssl rand -hex 32)"gateway:
secrets:
managed: false
secretName: "gateway-secrets"ui, admin-ui, and permissions reference the same gateway-secrets Secret by default, so no further wiring is needed.
An optional fourth key, bootstrap_admin_password, seeds the first admin user
at startup. See Admin UI Setup for the
bootstrap-admin flow.
Auth Database (Optional)
The auth stack — gateway, admin-ui, permissions, and the optional source service — stores its tables in PostgreSQL. By default it shares the same database as meta (postgres-credentials) and isolates itself in an auth schema, so no extra secret is required.
To run the auth stack against a physically separate database, point it at its own connection string and opt out of the shared schema by setting global.authDatabaseSchema: "".
global:
authPostgresCredentials:
managed: true
secretName: "auth-postgres-credentials"
authDatabaseSchema: "" # opt out of the shared `auth` schemahelm install berserk berserk/berserk \
--namespace bzrk \
-f values.yaml \
--set global.authPostgresCredentials.databaseUrl="postgres://<user>:<password>@host:5432/berserk_auth"Create the secret before installing:
kubectl create namespace bzrk
kubectl create secret generic auth-postgres-credentials \
--namespace bzrk \
--from-literal=database_url="postgres://<user>:<password>@host:5432/berserk_auth"global:
authPostgresCredentials:
managed: false # default
secretName: "auth-postgres-credentials"
authDatabaseSchema: ""OIDC Client Secret (Optional)
When you enable OIDC single sign-on, the gateway needs the client_secret issued by your identity provider. Because that value comes from the IdP, this secret is always external — the chart never generates it. gateway and admin-ui read the same Secret and key.
kubectl create namespace bzrk
# client_secret must be at least 32 characters
kubectl create secret generic gateway-oidc-secrets \
--namespace bzrk \
--from-literal=client_secret="<client-secret-from-your-idp>"gateway:
config:
oidc:
enabled: true
issuer: "https://idp.example.com"
clientId: "berserk"
secrets:
oidcClientSecret:
existingSecret:
name: "gateway-oidc-secrets"
key: "client_secret"
admin-ui:
config:
oidc:
enabled: true
secrets:
oidcClientSecret:
existingSecret:
name: "gateway-oidc-secrets"
key: "client_secret"See Admin UI Setup for the full OIDC walkthrough.
Trusted-Proxy Authentication (Optional)
When you front the gateway with a trusted authenticating reverse proxy (PP), it can assert the signed-in user in a request header. Unlike the OIDC client secret, this path needs no secret material — identity is trusted on network grounds alone, so the gateway must be unreachable except through the proxy.
gateway:
config:
trustedProxy:
enabled: true
# Direct email header, SPIFFE on-behalf-of, or both:
userHeader: X-PP-USER
onBehalfOf:
enabled: true
header: on-behalf-of
spiffePrefix: "spiffe://prod.example.net/user/"
emailDomain: example.comSee Admin UI Setup → Path D for the full walkthrough, including directory mode and the security model.
Default Ingest Token
An ingest token authenticates data sent to the ingest service. By default, all requests into the ingest service are authenticated via the ingest token. If you want to allow unauthenticated requests to the ingest service, then set up a default ingest token as follows.
global:
ingestToken:
managed: truehelm install berserk berserk/berserk \
--namespace bzrk \
-f values.yamlAn init container on the ingest service waits for Meta to be ready, creates the token via Meta's API, and stores it in a K8s secret. On subsequent deployments the init container is skipped if the secret already exists.
Create the secret before installing:
kubectl create namespace bzrk
kubectl create secret generic ingest-token \
--namespace bzrk \
--from-literal=default_ingest_token="<token>"global:
ingestToken:
managed: false # default
secretName: "ingest-token"helm install berserk berserk/berserk \
--namespace bzrk \
-f values.yamlWith this you can manage the ingest token secret directly.
UI Library (Optional)
The Query Library can be mirrored to a Git repo. This is not configured via Helm — a cluster admin sets the HTTPS remote and token at runtime in the admin UI, and it's stored in the database. See Git Sync Configuration for the walkthrough.
Full Install Example
When letting Helm manage all secrets, a single install command covers everything. The gateway's auth secrets (gateway-secrets) are generated automatically, so they need no flags below:
global:
storage:
endpoint: "https://s3.eu-central-1.amazonaws.com"
bucket: "your-berserk-bucket"
region: "eu-central-1"
s3Credentials:
managed: true
postgresCredentials:
managed: true
ingestToken:
managed: truehelm repo add berserk https://berserkdb.github.io/helm-charts
helm install berserk berserk/berserk \
--namespace bzrk \
-f values.yaml \
--set global.s3Credentials.accessKeyId="AKIA..." \
--set global.s3Credentials.secretAccessKey="secret..." \
--set global.postgresCredentials.databaseUrl="postgres://user:password@host:5432/berserk" \On subsequent helm upgrade calls, you do not need to pass the credential
--set flags again — the secrets already exist in the cluster and the chart
will not overwrite them.
See example values for minimal, Helm-managed, and EKS configurations.