Secrets management
Default (dev)
Section titled “Default (dev)”With secrets.create: true (default), Helm creates a Secret from the values you pass via --set or a values file:
helm install relay ./helm/relay \ --set secrets.openaiApiKey=sk-...This is convenient for development but should not be used in production — --set values appear in shell history and Helm release history.
Production: bring your own Secret
Section titled “Production: bring your own Secret”Step 1 — pre-provision the Secret
Section titled “Step 1 — pre-provision the Secret”Create the Secret outside of Helm (Vault Agent, External Secrets Operator, Sealed Secrets, kubectl, CI pipeline):
apiVersion: v1kind: Secretmetadata: name: llm-proxy-secrets namespace: defaulttype: OpaquestringData: OPENAI_API_KEY: "sk-..." ANTHROPIC_API_KEY: "sk-ant-..." GOOGLE_CLIENT_ID: "" GOOGLE_CLIENT_SECRET: "" AUTH_BASE_URL: "https://proxy.internal" LANGFUSE_PUBLIC_KEY: "" LANGFUSE_SECRET_KEY: "" LANGFUSE_HOST: "" # DATABASE_URL: only needed when externalDatabase.url is setStep 2 — disable chart-managed Secret
Section titled “Step 2 — disable chart-managed Secret”secrets: create: false existingSecret: llm-proxy-secretsRequired keys
Section titled “Required keys”The Secret must contain all keys that the proxy references. Optional keys (e.g. ANTHROPIC_API_KEY) can be empty strings — they are mounted as optional env vars.
| Key | Required |
|---|---|
OPENAI_API_KEY | If using OpenAI |
ANTHROPIC_API_KEY | If using Anthropic directly |
AZURE_OPENAI_API_KEY | If using Azure OpenAI |
AZURE_OPENAI_ENDPOINT | If using Azure OpenAI |
GOOGLE_CLIENT_ID | If using Google SSO |
GOOGLE_CLIENT_SECRET | If using Google SSO |
AUTH_BASE_URL | If using Google SSO |
LANGFUSE_PUBLIC_KEY | If using Langfuse |
LANGFUSE_SECRET_KEY | If using Langfuse |
LANGFUSE_HOST | If using self-hosted Langfuse |
DATABASE_URL | If using externalDatabase.url |
Master key management
Section titled “Master key management”The PROXY_MASTER_KEY is stored in a separate Secret (<release>-master-key) — it is never part of the main API keys Secret.
Auto-generation (default)
Section titled “Auto-generation (default)”Leave secrets.existingMasterKeySecret empty. The chart:
- On first install: generates a random 32-character key and stores it in the Secret
- On
helm upgrade: reads the existing Secret vialookup()— the key is never rotated - On
helm uninstall: the Secret is kept (helm.sh/resource-policy: keep)
Bring your own master key
Section titled “Bring your own master key”secrets: existingMasterKeySecret: my-master-key-secretThe referenced Secret must contain:
stringData: PROXY_MASTER_KEY: "your-32-char-key"Retrieve the auto-generated key
Section titled “Retrieve the auto-generated key”kubectl get secret <release>-master-key \ -o jsonpath='{.data.PROXY_MASTER_KEY}' | base64 -dExternal Secrets Operator
Section titled “External Secrets Operator”Example ExternalSecret for AWS Secrets Manager:
apiVersion: external-secrets.io/v1beta1kind: ExternalSecretmetadata: name: llm-proxy-secretsspec: refreshInterval: 1h secretStoreRef: name: aws-secretsmanager kind: SecretStore target: name: llm-proxy-secrets creationPolicy: Owner data: - secretKey: OPENAI_API_KEY remoteRef: key: prod/llm-proxy/openai-api-key - secretKey: ANTHROPIC_API_KEY remoteRef: key: prod/llm-proxy/anthropic-api-keyThen:
secrets: create: false existingSecret: llm-proxy-secrets