Skip to content
BoringStack
Star

Secrets backends (k3s)

2 min read

The k3s target decouples what the app reads from how secrets are stored. Every workload consumes plain k8s Secrets, boringstack-secrets (app env) and ghcr-registry-secret (GHCR pull), plus the CloudNativePG-generated boringstack-db-app that carries DATABASE_URL. The manifests never reference Vault directly, so the producer is a swappable Kustomize component in overlays/prod/secrets/.

Switch backends by editing one line under # Secrets backend (pick ONE) in overlays/prod/kustomization.yaml.

Option A: Vault + Vault Secrets Operator (default)

Section titled “Option A: Vault + Vault Secrets Operator (default)”

Requires Vault and the VSO on the cluster. The component ships VaultConnection, VaultAuth, and VaultStaticSecret resources that sync Vault KV-v2 into the k8s Secrets.

Seed Vault (KV-v2 mount secret):

Terminal window
# App env. Full key list: the api env validator, documented at
# /reference/env-vars/. DATABASE_URL is injected by CNPG, so it's not here.
vault kv put secret/boringstack \
JWT_SECRET="$(openssl rand -base64 48)" \
MFA_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
VALKEY_PASSWORD="$(openssl rand -base64 24)" \
GLITCHTIP_SECRET_KEY="$(openssl rand -base64 50)" \
FRONTEND_URL="https://<domain>" PUBLIC_API_URL="https://<domain>" \
QUEUES_ENABLED=true CACHE_PROVIDER=valkey \
# ...email / OAuth / Stripe / VAPID as needed...
# GHCR pull creds. One key holding a full docker config.json
vault kv put secret/boringstack-registry DOCKER_CONFIG_JSON=@dockerconfig.json

Bind a Vault Kubernetes-auth role so the operator can read those paths:

Terminal window
vault write auth/kubernetes/role/boringstack-prod-role \
bound_service_account_names=default \
bound_service_account_namespaces=boringstack-prod \
policies=boringstack-read ttl=10m

No external Vault. Encrypt the two Secrets with kubeseal and commit the SealedSecret manifests; the Bitnami controller decrypts them in-cluster. Full steps in overlays/prod/secrets/sealed/README.md.

Simplest. Kustomize’s secretGenerator builds boringstack-secrets from a gitignored secret.env; create ghcr-registry-secret with kubectl create secret docker-registry. Steps in overlays/prod/secrets/plain/README.md.

A pure-GitOps caveat: option C keeps secret values outside git, so it suits a cluster you apply to yourself rather than a fully declarative pipeline.