Rohmilchkaese 7 days ago
committed by GitHub
parent
commit
bbbbfcedd7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      helm/vaultwarden/.helmignore
  2. 18
      helm/vaultwarden/Chart.yaml
  3. 437
      helm/vaultwarden/README.md
  4. 52
      helm/vaultwarden/templates/NOTES.txt
  5. 133
      helm/vaultwarden/templates/_helpers.tpl
  6. 40
      helm/vaultwarden/templates/configmap.yaml
  7. 228
      helm/vaultwarden/templates/deployment.yaml
  8. 45
      helm/vaultwarden/templates/ingress.yaml
  9. 33
      helm/vaultwarden/templates/pvc.yaml
  10. 81
      helm/vaultwarden/templates/secret.yaml
  11. 32
      helm/vaultwarden/templates/service.yaml
  12. 14
      helm/vaultwarden/templates/serviceaccount.yaml
  13. 16
      helm/vaultwarden/templates/tests/test-connection.yaml
  14. 367
      helm/vaultwarden/values.yaml

12
helm/vaultwarden/.helmignore

@ -0,0 +1,12 @@
# Patterns to ignore when building packages.
.DS_Store
*.swp
*.bak
*.tmp
*~
.git
.gitignore
.project
.idea
*.tmproj
.vscode

18
helm/vaultwarden/Chart.yaml

@ -0,0 +1,18 @@
apiVersion: v2
name: vaultwarden
description: Vaultwarden - unofficial Bitwarden-compatible server written in Rust
type: application
version: 0.1.0
appVersion: "1.35.3"
home: https://github.com/dani-garcia/vaultwarden
icon: https://raw.githubusercontent.com/dani-garcia/vaultwarden/main/resources/vaultwarden-icon.svg
sources:
- https://github.com/dani-garcia/vaultwarden
keywords:
- vaultwarden
- bitwarden
- password-manager
- secrets
maintainers:
- name: dani-garcia
url: https://github.com/dani-garcia

437
helm/vaultwarden/README.md

@ -0,0 +1,437 @@
# Vaultwarden Helm Chart
Official Helm chart for [Vaultwarden](https://github.com/dani-garcia/vaultwarden) — an unofficial Bitwarden-compatible server written in Rust.
## Quick Start
```bash
helm install vaultwarden ./helm/vaultwarden \
--set vaultwarden.domain=https://vault.example.com
```
This deploys vaultwarden with **SQLite** (the default). Data is persisted in a 5Gi PVC.
> **For production deployments, we recommend PostgreSQL.** See [Production Setup with PostgreSQL](#production-setup-with-postgresql) below.
## Production Setup with PostgreSQL
```yaml
# values-production.yaml
vaultwarden:
domain: https://vault.example.com
signupsAllowed: false
admin:
enabled: true
existingSecret: vaultwarden-admin
existingSecretKey: admin-token
database:
type: postgresql
existingSecret: vaultwarden-db-credentials
existingSecretKey: database-url
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
cert-manager.io/private-key-algorithm: ECDSA
cert-manager.io/private-key-size: "384"
cert-manager.io/private-key-rotation-policy: Always
hosts:
- host: vault.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: vault-tls
hosts:
- vault.example.com
persistence:
storageClassName: longhorn # or your preferred storage class
size: 10Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
```
```bash
helm install vaultwarden ./helm/vaultwarden -f values-production.yaml
```
## Configuration
### Image
| Parameter | Description | Default |
|-----------|-------------|---------|
| `image.repository` | Container image repository | `vaultwarden/server` |
| `image.tag` | Image tag (defaults to `appVersion`) | `""` |
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
| `replicaCount` | Number of replicas (keep at 1 for SQLite) | `1` |
### Vaultwarden
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.domain` | **(required)** Public URL of your instance | `""` |
| `vaultwarden.signupsAllowed` | Allow new user registrations | `false` |
| `vaultwarden.rocketPort` | HTTP server port | `8080` |
| `vaultwarden.websocket.enabled` | Enable websocket notifications | `true` |
| `vaultwarden.logging.level` | Log level (trace/debug/info/warn/error/off) | `info` |
| `vaultwarden.icons.service` | Icon service (internal/bitwarden/duckduckgo/google) | `internal` |
### Admin Panel
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.admin.enabled` | Enable the admin panel at `/admin` | `false` |
| `vaultwarden.admin.token` | Admin token (argon2 hash recommended) | `""` |
| `vaultwarden.admin.existingSecret` | Existing secret name for admin token | `""` |
| `vaultwarden.admin.existingSecretKey` | Key in existing secret | `admin-token` |
### Database
The chart supports two ways to configure the database connection for PostgreSQL/MySQL:
**Option 1: Full connection URL** — provide a complete `DATABASE_URL` via a secret:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `database.type` | Database backend: `sqlite`, `postgresql`, or `mysql` | `sqlite` |
| `database.url` | Full connection URL (inline, not recommended) | `""` |
| `database.existingSecret` | Secret containing the full database URL | `""` |
| `database.existingSecretKey` | Key in existing secret | `database-url` |
```yaml
database:
type: postgresql
existingSecret: my-db-url-secret
existingSecretKey: database-url
```
**Option 2: Compose from parts** (recommended for Postgres operators) — the chart reads username and password from a credentials secret and assembles the `DATABASE_URL` automatically. This is ideal for Zalando Postgres Operator, CloudNativePG, or any operator that creates per-user credential secrets:
| Parameter | Description | Default |
|-----------|-------------|---------|
| `database.host` | Database hostname (triggers compose mode) | `""` |
| `database.port` | Database port | `5432` |
| `database.dbName` | Database name | `vaultwarden` |
| `database.credentialsSecret` | Secret with `username` and `password` keys | `""` |
| `database.credentialsSecretUsernameKey` | Key for username | `username` |
| `database.credentialsSecretPasswordKey` | Key for password | `password` |
```yaml
# Example: Zalando Postgres Operator
database:
type: postgresql
host: vaultwarden-db.postgres-cluster
port: 5432
dbName: vaultwarden
credentialsSecret: vaultwarden.user.vaultwarden-db.credentials.postgresql.acid.zalan.do
```
This renders as:
```yaml
env:
- name: _DB_USER
valueFrom:
secretKeyRef:
name: vaultwarden.user.vaultwarden-db.credentials.postgresql.acid.zalan.do
key: username
- name: _DB_PASSWORD
valueFrom:
secretKeyRef:
name: vaultwarden.user.vaultwarden-db.credentials.postgresql.acid.zalan.do
key: password
- name: DATABASE_URL
value: postgresql://$(_DB_USER):$(_DB_PASSWORD)@vaultwarden-db.postgres-cluster:5432/vaultwarden
```
**Common settings:**
| Parameter | Description | Default |
|-----------|-------------|---------|
| `database.maxConnections` | Max database connections | `10` |
| `database.wal` | Enable WAL mode (SQLite only) | `true` |
### SMTP (Email)
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.smtp.host` | SMTP server hostname | `""` |
| `vaultwarden.smtp.from` | Sender email address | `""` |
| `vaultwarden.smtp.port` | SMTP port | `587` |
| `vaultwarden.smtp.security` | Security mode (starttls/force_tls/off) | `starttls` |
| `vaultwarden.smtp.username` | SMTP username | `""` |
| `vaultwarden.smtp.password` | SMTP password | `""` |
| `vaultwarden.smtp.existingSecret` | Existing secret for SMTP credentials | `""` |
| `vaultwarden.smtp.existingSecretUsernameKey` | Key in existing secret for username | `smtp-username` |
| `vaultwarden.smtp.existingSecretPasswordKey` | Key in existing secret for password | `smtp-password` |
### SSO (OpenID Connect)
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.sso.enabled` | Enable SSO authentication | `false` |
| `vaultwarden.sso.only` | Require SSO (disable password login) | `false` |
| `vaultwarden.sso.authority` | OIDC authority URL | `""` |
| `vaultwarden.sso.clientId` | OIDC client ID | `""` |
| `vaultwarden.sso.clientSecret` | OIDC client secret | `""` |
| `vaultwarden.sso.existingSecret` | Existing secret for SSO credentials | `""` |
| `vaultwarden.sso.existingSecretClientIdKey` | Key in existing secret for client ID | `sso-client-id` |
| `vaultwarden.sso.existingSecretClientSecretKey` | Key in existing secret for client secret | `sso-client-secret` |
### Push Notifications
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.push.enabled` | Enable push notifications | `false` |
| `vaultwarden.push.installationId` | Installation ID from bitwarden.com/host | `""` |
| `vaultwarden.push.installationKey` | Installation key from bitwarden.com/host | `""` |
| `vaultwarden.push.existingSecret` | Existing secret for push credentials | `""` |
| `vaultwarden.push.relayUri` | Push relay URI | `""` |
| `vaultwarden.push.identityUri` | Push identity URI | `""` |
### Yubico OTP
| Parameter | Description | Default |
|-----------|-------------|---------|
| `vaultwarden.yubico.enabled` | Enable Yubico OTP | `false` |
| `vaultwarden.yubico.clientId` | Yubico client ID | `""` |
| `vaultwarden.yubico.secretKey` | Yubico secret key | `""` |
| `vaultwarden.yubico.existingSecret` | Existing secret for Yubico credentials | `""` |
### Service
| Parameter | Description | Default |
|-----------|-------------|---------|
| `service.type` | Service type (`ClusterIP`, `NodePort`, `LoadBalancer`) | `ClusterIP` |
| `service.port` | Service port | `8080` |
| `service.nodePort` | Node port (when type is `NodePort`) | `""` |
| `service.loadBalancerIP` | Load balancer IP (when type is `LoadBalancer`) | `""` |
| `service.externalTrafficPolicy` | External traffic policy (`Local` or `Cluster`) | `""` |
| `service.annotations` | Service annotations (e.g. for external-dns) | `{}` |
| `service.labels` | Additional service labels | `{}` |
### Ingress
| Parameter | Description | Default |
|-----------|-------------|---------|
| `ingress.enabled` | Enable ingress | `false` |
| `ingress.className` | Ingress class name (e.g. `nginx`, `traefik`, `haproxy`) | `""` |
| `ingress.annotations` | Ingress annotations (e.g. cert-manager, rate-limiting) | `{}` |
| `ingress.labels` | Additional ingress labels | `{}` |
| `ingress.hosts` | Ingress host rules | see `values.yaml` |
| `ingress.tls` | Ingress TLS configuration | `[]` |
Example with full ingress configuration:
```yaml
ingress:
enabled: true
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
cert-manager.io/private-key-algorithm: ECDSA
cert-manager.io/private-key-size: "384"
cert-manager.io/private-key-rotation-policy: Always
hosts:
- host: vault.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: vault-tls
hosts:
- vault.example.com
```
### Persistence
| Parameter | Description | Default |
|-----------|-------------|---------|
| `persistence.enabled` | Enable persistent storage | `true` |
| `persistence.storageClassName` | Storage class name (see below) | `nil` |
| `persistence.accessModes` | PVC access modes | `[ReadWriteOnce]` |
| `persistence.size` | Storage size | `5Gi` |
| `persistence.existingClaim` | Use an existing PVC | `""` |
| `persistence.annotations` | Additional PVC annotations | `{}` |
| `persistence.labels` | Additional PVC labels | `{}` |
**Storage class behavior:**
| Value | Behavior |
|-------|----------|
| `nil` (unset) | Uses the cluster default storage class |
| `"-"` | Disables dynamic provisioning (`storageClassName: ""`) |
| `"longhorn"` | Uses the specified storage class |
**High availability (multiple replicas):** Running `replicaCount > 1` requires PostgreSQL (SQLite does not support concurrent access) and a storage class that supports `ReadWriteMany` (RWX) access mode, such as NFS, CephFS, or a cloud-native RWX provider (e.g. AWS EFS, Azure Files, GCP Filestore). Update your persistence accordingly:
```yaml
replicaCount: 2
database:
type: postgresql
host: my-cluster.postgres
credentialsSecret: my-pg-credentials
persistence:
storageClassName: efs-sc # or any RWX-capable storage class
accessModes:
- ReadWriteMany
```
### Security Context
The chart runs vaultwarden as a non-root user (UID 1000) by default with a read-only root filesystem. The `ROCKET_PORT` is set to `8080` to avoid requiring privileged ports.
| Parameter | Description | Default |
|-----------|-------------|---------|
| `podSecurityContext.runAsUser` | Pod user ID | `1000` |
| `podSecurityContext.runAsGroup` | Pod group ID | `1000` |
| `podSecurityContext.runAsNonRoot` | Enforce non-root | `true` |
| `podSecurityContext.fsGroup` | Pod filesystem group | `1000` |
| `podSecurityContext.seccompProfile.type` | Seccomp profile | `RuntimeDefault` |
| `securityContext.readOnlyRootFilesystem` | Read-only root FS | `true` |
| `securityContext.allowPrivilegeEscalation` | Prevent privilege escalation | `false` |
| `securityContext.capabilities.drop` | Dropped capabilities | `["ALL"]` |
### Scheduling
| Parameter | Description | Default |
|-----------|-------------|---------|
| `nodeSelector` | Node selector constraints | `{}` |
| `tolerations` | Pod tolerations | `[]` |
| `affinity` | Affinity rules | `{}` |
| `topologySpreadConstraints` | Topology spread constraints | `[]` |
| `priorityClassName` | Priority class for pod scheduling | `""` |
### Other
| Parameter | Description | Default |
|-----------|-------------|---------|
| `serviceAccount.create` | Create a service account | `true` |
| `serviceAccount.annotations` | Service account annotations | `{}` |
| `serviceAccount.automountServiceAccountToken` | Automount SA token | `false` |
| `resources` | CPU/memory resources | see `values.yaml` |
| `revisionHistoryLimit` | Deployment revision history limit | `3` |
| `terminationGracePeriodSeconds` | Termination grace period | `30` |
| `startupProbe` | Startup probe config (for slow starts) | `{}` |
| `initContainers` | Init containers | `[]` |
| `extraVolumes` | Additional volumes | `[]` |
| `extraVolumeMounts` | Additional volume mounts | `[]` |
| `podAnnotations` | Pod annotations | `{}` |
| `podLabels` | Additional pod labels | `{}` |
### Environment Variables
The chart provides three layers for setting environment variables, from simplest to most flexible:
**`env`** — plain key-value map for any vaultwarden env var:
```yaml
env:
SIGNUPS_ALLOWED: "true"
INVITATION_ORG_NAME: "My Org"
SENDS_ALLOWED: "true"
```
**`secretEnv`** — shorthand for sourcing env vars from Kubernetes secrets:
```yaml
secretEnv:
ADMIN_TOKEN:
secretName: my-admin-secret
secretKey: admin-token
DATABASE_URL:
secretName: my-db-secret
secretKey: database-url
```
**`extraEnv`** — raw Kubernetes env spec for complex cases (fieldRef, resourceFieldRef, etc.):
```yaml
extraEnv:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
```
These layers are additive and render in order: structured values (from `vaultwarden.*`), then `env`, then `secretEnv`, then `extraEnv`. Later values override earlier ones for the same env var name.
## Using Existing Secrets
For production deployments, use `existingSecret` references instead of putting credentials in `values.yaml`. All sensitive values support `existingSecret`:
```bash
# Create secrets before installing the chart
kubectl create secret generic vaultwarden-admin \
--from-literal=admin-token='$argon2id$...'
kubectl create secret generic vaultwarden-db \
--from-literal=database-url='postgresql://user:pass@host:5432/vaultwarden'
kubectl create secret generic vaultwarden-smtp \
--from-literal=smtp-username='user@example.com' \
--from-literal=smtp-password='password'
kubectl create secret generic vaultwarden-sso \
--from-literal=sso-client-id='vaultwarden' \
--from-literal=sso-client-secret='secret'
kubectl create secret generic vaultwarden-push \
--from-literal=push-installation-id='...' \
--from-literal=push-installation-key='...'
```
Then reference them in your values:
```yaml
vaultwarden:
admin:
enabled: true
existingSecret: vaultwarden-admin
smtp:
host: smtp.example.com
from: vault@example.com
existingSecret: vaultwarden-smtp
sso:
enabled: true
authority: https://auth.example.com/realms/main
existingSecret: vaultwarden-sso
push:
enabled: true
existingSecret: vaultwarden-push
database:
type: postgresql
existingSecret: vaultwarden-db
```
## Mounting Custom CA Certificates
To trust custom CA certificates (e.g. for LDAP or SSO with self-signed certs):
```yaml
extraVolumes:
- name: custom-certs
secret:
secretName: ca-bundle
extraVolumeMounts:
- name: custom-certs
mountPath: /etc/ssl/certs/custom
readOnly: true
extraEnv:
- name: SSL_CERT_DIR
value: /etc/ssl/certs:/etc/ssl/certs/custom
```

52
helm/vaultwarden/templates/NOTES.txt

@ -0,0 +1,52 @@
Vaultwarden has been deployed successfully!
{{- if .Values.ingress.enabled }}
Your vaultwarden instance is available at:
{{- range .Values.ingress.hosts }}
https://{{ .host }}
{{- end }}
{{- else }}
To access vaultwarden, run:
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "vaultwarden.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
Then open http://localhost:{{ .Values.service.port }} in your browser.
{{- end }}
{{- if not .Values.vaultwarden.domain }}
WARNING: vaultwarden.domain is not set. You must set this to the URL
where vaultwarden will be accessible (e.g. https://vault.example.com).
{{- end }}
{{- if .Values.vaultwarden.admin.enabled }}
Admin panel is enabled at /admin
{{- if not .Values.vaultwarden.admin.existingSecret }}
Make sure to use an existingSecret for the admin token in production.
{{- end }}
{{- end }}
{{- if eq .Values.database.type "sqlite" }}
NOTE: You are using SQLite (default). For production deployments with
multiple users, consider switching to PostgreSQL:
database.type=postgresql
database.host=<your-postgres-host>
database.credentialsSecret=<your-credentials-secret>
{{- end }}
{{- if and (gt (int .Values.replicaCount) 1) (eq .Values.database.type "sqlite") }}
WARNING: replicaCount > 1 is not supported with SQLite. Use PostgreSQL
for multi-replica deployments.
{{- end }}
{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled }}
NOTE: Running multiple replicas with persistence requires a storage class
that supports ReadWriteMany (RWX) access mode, such as NFS, CephFS, or
a cloud-native RWX provider. Ensure persistence.accessModes includes
ReadWriteMany.
{{- end }}

133
helm/vaultwarden/templates/_helpers.tpl

@ -0,0 +1,133 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "vaultwarden.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "vaultwarden.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "vaultwarden.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels.
*/}}
{{- define "vaultwarden.labels" -}}
helm.sh/chart: {{ include "vaultwarden.chart" . }}
{{ include "vaultwarden.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels.
*/}}
{{- define "vaultwarden.selectorLabels" -}}
app.kubernetes.io/name: {{ include "vaultwarden.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use.
*/}}
{{- define "vaultwarden.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "vaultwarden.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Return the appropriate image tag.
*/}}
{{- define "vaultwarden.imageTag" -}}
{{- default .Chart.AppVersion .Values.image.tag }}
{{- end }}
{{/*
Return the secret name for admin token.
*/}}
{{- define "vaultwarden.adminSecretName" -}}
{{- if .Values.vaultwarden.admin.existingSecret }}
{{- .Values.vaultwarden.admin.existingSecret }}
{{- else }}
{{- printf "%s-admin" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}
{{/*
Return the secret name for SMTP credentials.
*/}}
{{- define "vaultwarden.smtpSecretName" -}}
{{- if .Values.vaultwarden.smtp.existingSecret }}
{{- .Values.vaultwarden.smtp.existingSecret }}
{{- else }}
{{- printf "%s-smtp" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}
{{/*
Return the secret name for SSO credentials.
*/}}
{{- define "vaultwarden.ssoSecretName" -}}
{{- if .Values.vaultwarden.sso.existingSecret }}
{{- .Values.vaultwarden.sso.existingSecret }}
{{- else }}
{{- printf "%s-sso" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}
{{/*
Return the secret name for push notification credentials.
*/}}
{{- define "vaultwarden.pushSecretName" -}}
{{- if .Values.vaultwarden.push.existingSecret }}
{{- .Values.vaultwarden.push.existingSecret }}
{{- else }}
{{- printf "%s-push" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}
{{/*
Return the secret name for Yubico credentials.
*/}}
{{- define "vaultwarden.yubicoSecretName" -}}
{{- if .Values.vaultwarden.yubico.existingSecret }}
{{- .Values.vaultwarden.yubico.existingSecret }}
{{- else }}
{{- printf "%s-yubico" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}
{{/*
Return the secret name for database URL.
*/}}
{{- define "vaultwarden.databaseSecretName" -}}
{{- if .Values.database.existingSecret }}
{{- .Values.database.existingSecret }}
{{- else }}
{{- printf "%s-database" (include "vaultwarden.fullname" .) }}
{{- end }}
{{- end }}

40
helm/vaultwarden/templates/configmap.yaml

@ -0,0 +1,40 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "vaultwarden.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
data:
ROCKET_PORT: {{ .Values.vaultwarden.rocketPort | quote }}
SIGNUPS_ALLOWED: {{ .Values.vaultwarden.signupsAllowed | quote }}
ENABLE_WEBSOCKET: {{ .Values.vaultwarden.websocket.enabled | quote }}
LOG_LEVEL: {{ .Values.vaultwarden.logging.level | quote }}
ICON_SERVICE: {{ .Values.vaultwarden.icons.service | quote }}
{{- if .Values.vaultwarden.domain }}
DOMAIN: {{ .Values.vaultwarden.domain | quote }}
{{- end }}
{{- if eq .Values.database.type "sqlite" }}
ENABLE_DB_WAL: {{ .Values.database.wal | quote }}
{{- end }}
DATABASE_MAX_CONNS: {{ .Values.database.maxConnections | quote }}
{{- if .Values.vaultwarden.smtp.host }}
SMTP_HOST: {{ .Values.vaultwarden.smtp.host | quote }}
SMTP_FROM: {{ .Values.vaultwarden.smtp.from | quote }}
SMTP_PORT: {{ .Values.vaultwarden.smtp.port | quote }}
SMTP_SECURITY: {{ .Values.vaultwarden.smtp.security | quote }}
{{- end }}
{{- if .Values.vaultwarden.sso.enabled }}
SSO_ENABLED: "true"
SSO_ONLY: {{ .Values.vaultwarden.sso.only | quote }}
SSO_AUTHORITY: {{ .Values.vaultwarden.sso.authority | quote }}
{{- end }}
{{- if .Values.vaultwarden.push.enabled }}
PUSH_ENABLED: "true"
{{- if .Values.vaultwarden.push.relayUri }}
PUSH_RELAY_URI: {{ .Values.vaultwarden.push.relayUri | quote }}
{{- end }}
{{- if .Values.vaultwarden.push.identityUri }}
PUSH_IDENTITY_URI: {{ .Values.vaultwarden.push.identityUri | quote }}
{{- end }}
{{- end }}

228
helm/vaultwarden/templates/deployment.yaml

@ -0,0 +1,228 @@
{{- /* Validation */}}
{{- if and .Values.vaultwarden.admin.enabled (not .Values.vaultwarden.admin.token) (not .Values.vaultwarden.admin.existingSecret) }}
{{- fail "vaultwarden.admin.enabled is true but neither admin.token nor admin.existingSecret is set" }}
{{- end }}
{{- if and (ne .Values.database.type "sqlite") .Values.database.host (not .Values.database.credentialsSecret) }}
{{- fail "database.host is set but database.credentialsSecret is not — provide the secret containing database credentials" }}
{{- end }}
{{- if and (ne .Values.database.type "sqlite") (not .Values.database.host) (not .Values.database.url) (not .Values.database.existingSecret) }}
{{- fail "database.type is not sqlite but no database connection is configured — set database.host (with credentialsSecret), database.url, or database.existingSecret" }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "vaultwarden.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
{{- if .Values.revisionHistoryLimit }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
{{- end }}
strategy:
type: Recreate
selector:
matchLabels:
{{- include "vaultwarden.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "vaultwarden.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
serviceAccountName: {{ include "vaultwarden.serviceAccountName" . }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- end }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
{{- with .Values.initContainers }}
initContainers:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: vaultwarden
image: "{{ .Values.image.repository }}:{{ include "vaultwarden.imageTag" . }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.vaultwarden.rocketPort }}
name: http
protocol: TCP
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
envFrom:
- configMapRef:
name: {{ include "vaultwarden.fullname" . }}
env:
{{- /* Admin token */}}
{{- if .Values.vaultwarden.admin.enabled }}
- name: ADMIN_TOKEN
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.adminSecretName" . }}
key: {{ .Values.vaultwarden.admin.existingSecretKey | default "admin-token" }}
{{- end }}
{{- /* SMTP credentials */}}
{{- if and .Values.vaultwarden.smtp.host (or .Values.vaultwarden.smtp.username .Values.vaultwarden.smtp.existingSecret) }}
- name: SMTP_USERNAME
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.smtpSecretName" . }}
key: {{ .Values.vaultwarden.smtp.existingSecretUsernameKey | default "smtp-username" }}
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.smtpSecretName" . }}
key: {{ .Values.vaultwarden.smtp.existingSecretPasswordKey | default "smtp-password" }}
{{- end }}
{{- /* SSO credentials */}}
{{- if .Values.vaultwarden.sso.enabled }}
- name: SSO_CLIENT_ID
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.ssoSecretName" . }}
key: {{ .Values.vaultwarden.sso.existingSecretClientIdKey | default "sso-client-id" }}
- name: SSO_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.ssoSecretName" . }}
key: {{ .Values.vaultwarden.sso.existingSecretClientSecretKey | default "sso-client-secret" }}
{{- end }}
{{- /* Database URL — Option 2: compose from parts */}}
{{- if and (ne .Values.database.type "sqlite") .Values.database.host }}
- name: _DB_USER
valueFrom:
secretKeyRef:
name: {{ required "database.credentialsSecret is required when database.host is set" .Values.database.credentialsSecret }}
key: {{ .Values.database.credentialsSecretUsernameKey | default "username" }}
- name: _DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.credentialsSecret }}
key: {{ .Values.database.credentialsSecretPasswordKey | default "password" }}
- name: DATABASE_URL
value: {{ .Values.database.type }}://$(_DB_USER):$(_DB_PASSWORD)@{{ .Values.database.host }}:{{ .Values.database.port }}/{{ .Values.database.dbName }}
{{- /* Database URL — Option 1: full URL from secret */}}
{{- else if ne .Values.database.type "sqlite" }}
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.databaseSecretName" . }}
key: {{ .Values.database.existingSecretKey | default "database-url" }}
{{- end }}
{{- /* Push notifications */}}
{{- if .Values.vaultwarden.push.enabled }}
- name: PUSH_INSTALLATION_ID
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.pushSecretName" . }}
key: {{ .Values.vaultwarden.push.existingSecretInstallationIdKey | default "push-installation-id" }}
- name: PUSH_INSTALLATION_KEY
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.pushSecretName" . }}
key: {{ .Values.vaultwarden.push.existingSecretInstallationKeyKey | default "push-installation-key" }}
{{- end }}
{{- /* Yubico */}}
{{- if .Values.vaultwarden.yubico.enabled }}
- name: YUBICO_CLIENT_ID
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.yubicoSecretName" . }}
key: {{ .Values.vaultwarden.yubico.existingSecretClientIdKey | default "yubico-client-id" }}
- name: YUBICO_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ include "vaultwarden.yubicoSecretName" . }}
key: {{ .Values.vaultwarden.yubico.existingSecretSecretKeyKey | default "yubico-secret-key" }}
{{- end }}
{{- /* Plain env vars from env map */}}
{{- range $name, $value := .Values.env }}
- name: {{ $name }}
value: {{ $value | quote }}
{{- end }}
{{- /* Secret env vars from secretEnv map */}}
{{- range $name, $ref := .Values.secretEnv }}
- name: {{ $name }}
valueFrom:
secretKeyRef:
name: {{ $ref.secretName }}
key: {{ $ref.secretKey }}
{{- end }}
{{- /* Raw extra env vars */}}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: data
mountPath: /data
- name: tmp
mountPath: /tmp
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.startupProbe }}
startupProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: data
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim | default (include "vaultwarden.fullname" .) }}
{{- else }}
emptyDir: {}
{{- end }}
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 64Mi
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}

45
helm/vaultwarden/templates/ingress.yaml

@ -0,0 +1,45 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "vaultwarden.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
{{- with .Values.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "vaultwarden.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}

33
helm/vaultwarden/templates/pvc.yaml

@ -0,0 +1,33 @@
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "vaultwarden.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
{{- with .Values.persistence.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
annotations:
helm.sh/resource-policy: keep
{{- with .Values.persistence.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
{{- range .Values.persistence.accessModes }}
- {{ . }}
{{- end }}
{{- $sc := .Values.persistence.storageClassName }}
{{- if not (kindIs "invalid" $sc) }}
{{- if eq (toString $sc) "-" }}
storageClassName: ""
{{- else if $sc }}
storageClassName: {{ $sc | quote }}
{{- end }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- end }}

81
helm/vaultwarden/templates/secret.yaml

@ -0,0 +1,81 @@
{{- if and .Values.vaultwarden.admin.enabled .Values.vaultwarden.admin.token (not .Values.vaultwarden.admin.existingSecret) -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-admin
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
admin-token: {{ .Values.vaultwarden.admin.token | quote }}
{{- end }}
{{- if and .Values.vaultwarden.smtp.host .Values.vaultwarden.smtp.username (not .Values.vaultwarden.smtp.existingSecret) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-smtp
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
smtp-username: {{ .Values.vaultwarden.smtp.username | quote }}
smtp-password: {{ .Values.vaultwarden.smtp.password | quote }}
{{- end }}
{{- if and .Values.vaultwarden.sso.enabled .Values.vaultwarden.sso.clientId (not .Values.vaultwarden.sso.existingSecret) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-sso
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
sso-client-id: {{ .Values.vaultwarden.sso.clientId | quote }}
sso-client-secret: {{ .Values.vaultwarden.sso.clientSecret | quote }}
{{- end }}
{{- if and .Values.vaultwarden.push.enabled .Values.vaultwarden.push.installationId (not .Values.vaultwarden.push.existingSecret) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-push
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
push-installation-id: {{ .Values.vaultwarden.push.installationId | quote }}
push-installation-key: {{ .Values.vaultwarden.push.installationKey | quote }}
{{- end }}
{{- if and .Values.vaultwarden.yubico.enabled .Values.vaultwarden.yubico.clientId (not .Values.vaultwarden.yubico.existingSecret) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-yubico
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
yubico-client-id: {{ .Values.vaultwarden.yubico.clientId | quote }}
yubico-secret-key: {{ .Values.vaultwarden.yubico.secretKey | quote }}
{{- end }}
{{- if and (ne .Values.database.type "sqlite") .Values.database.url (not .Values.database.existingSecret) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "vaultwarden.fullname" . }}-database
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
type: Opaque
stringData:
database-url: {{ .Values.database.url | quote }}
{{- end }}

32
helm/vaultwarden/templates/service.yaml

@ -0,0 +1,32 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "vaultwarden.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
{{- with .Values.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.externalTrafficPolicy }}
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }}
{{- end }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
{{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
{{- include "vaultwarden.selectorLabels" . | nindent 4 }}

14
helm/vaultwarden/templates/serviceaccount.yaml

@ -0,0 +1,14 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "vaultwarden.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
{{- end }}

16
helm/vaultwarden/templates/tests/test-connection.yaml

@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "vaultwarden.fullname" . }}-test-connection"
namespace: {{ .Release.Namespace }}
labels:
{{- include "vaultwarden.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox:stable
command: ['wget']
args: ['{{ include "vaultwarden.fullname" . }}:{{ .Values.service.port }}/alive', '-q', '-O', '-']
restartPolicy: Never

367
helm/vaultwarden/values.yaml

@ -0,0 +1,367 @@
# -- Number of replicas. Keep at 1 when using SQLite.
replicaCount: 1
image:
# -- Container image repository
repository: vaultwarden/server
# -- Image pull policy
pullPolicy: IfNotPresent
# -- Overrides the image tag (default: appVersion from Chart.yaml)
tag: ""
# -- Image pull secrets
imagePullSecrets: []
# -- Override the release name
nameOverride: ""
# -- Override the full release name
fullnameOverride: ""
# =============================================================================
# Vaultwarden configuration
# =============================================================================
vaultwarden:
# -- (required) The domain URL for your vaultwarden instance (e.g. https://vault.example.com)
domain: ""
# -- Allow new user signups
signupsAllowed: false
# -- Rocket server port. Set to non-privileged port for non-root operation.
rocketPort: 8080
# -- Enable websocket notifications
websocket:
enabled: true
# -- Logging configuration
logging:
# -- Log level (trace, debug, info, warn, error, off)
level: "info"
# -- Icon service configuration
icons:
# -- Icon service to use (internal, bitwarden, duckduckgo, google)
service: "internal"
# -- Admin panel configuration
admin:
# -- Enable the admin panel (/admin)
enabled: false
# -- Admin token (argon2 hash recommended). Ignored if existingSecret is set.
token: ""
# -- Use an existing secret for the admin token
existingSecret: ""
# -- Key within the existing secret that holds the admin token
existingSecretKey: "admin-token"
# -- SMTP email configuration
smtp:
# -- SMTP server hostname
host: ""
# -- Email address used as the sender
from: ""
# -- SMTP server port
port: 587
# -- SMTP security mode (starttls, force_tls, off)
security: "starttls"
# -- SMTP username. Ignored if existingSecret is set.
username: ""
# -- SMTP password. Ignored if existingSecret is set.
password: ""
# -- Use an existing secret for SMTP credentials
existingSecret: ""
# -- Key in existing secret for SMTP username
existingSecretUsernameKey: "smtp-username"
# -- Key in existing secret for SMTP password
existingSecretPasswordKey: "smtp-password"
# -- SSO/OpenID Connect configuration
sso:
# -- Enable SSO authentication
enabled: false
# -- Require SSO for all logins (disable password login)
only: false
# -- OpenID Connect authority URL
authority: ""
# -- OIDC client ID. Ignored if existingSecret is set.
clientId: ""
# -- OIDC client secret. Ignored if existingSecret is set.
clientSecret: ""
# -- Use an existing secret for SSO credentials
existingSecret: ""
# -- Key in existing secret for client ID
existingSecretClientIdKey: "sso-client-id"
# -- Key in existing secret for client secret
existingSecretClientSecretKey: "sso-client-secret"
# -- Push notifications configuration (requires https://bitwarden.com/host keys)
push:
# -- Enable push notifications
enabled: false
# -- Installation ID from https://bitwarden.com/host. Ignored if existingSecret is set.
installationId: ""
# -- Installation key from https://bitwarden.com/host. Ignored if existingSecret is set.
installationKey: ""
# -- Use an existing secret for push notification credentials
existingSecret: ""
# -- Key in existing secret for installation ID
existingSecretInstallationIdKey: "push-installation-id"
# -- Key in existing secret for installation key
existingSecretInstallationKeyKey: "push-installation-key"
# -- Relay URI (default uses Bitwarden US server)
relayUri: ""
# -- Identity URI (default uses Bitwarden US server)
identityUri: ""
# -- Yubico OTP configuration
yubico:
# -- Enable Yubico OTP support
enabled: false
# -- Yubico client ID. Ignored if existingSecret is set.
clientId: ""
# -- Yubico secret key. Ignored if existingSecret is set.
secretKey: ""
# -- Use an existing secret for Yubico credentials
existingSecret: ""
# -- Key in existing secret for client ID
existingSecretClientIdKey: "yubico-client-id"
# -- Key in existing secret for secret key
existingSecretSecretKeyKey: "yubico-secret-key"
# =============================================================================
# Database configuration
# =============================================================================
database:
# -- Database backend: sqlite, postgresql, or mysql
type: "sqlite"
# --- Option 1: Full connection URL ---
# -- Full database connection URL.
# Examples:
# postgresql://user:password@host:5432/vaultwarden
# mysql://user:password@host:3306/vaultwarden
url: ""
# -- Use an existing secret containing the full database URL
existingSecret: ""
# -- Key within the existing secret for the database URL
existingSecretKey: "database-url"
# --- Option 2: Compose from parts (recommended for Postgres operators) ---
# When `host` is set, the chart composes DATABASE_URL from individual fields.
# Username and password are read from a Kubernetes secret via secretKeyRef.
# This is ideal for Zalando Postgres Operator, CloudNativePG, etc.
# -- Database hostname (e.g. my-cluster.postgres-namespace)
host: ""
# -- Database port
port: 5432
# -- Database name
dbName: "vaultwarden"
# -- Secret containing database user credentials (must have username and password keys)
credentialsSecret: ""
# -- Key in credentialsSecret for the username
credentialsSecretUsernameKey: "username"
# -- Key in credentialsSecret for the password
credentialsSecretPasswordKey: "password"
# --- Common settings ---
# -- Maximum number of database connections
maxConnections: 10
# -- Enable WAL mode for SQLite (improves performance)
wal: true
# =============================================================================
# Kubernetes resources
# =============================================================================
serviceAccount:
# -- Create a service account
create: true
# -- Annotations for the service account
annotations: {}
# -- Override the service account name
name: ""
# -- Automount the service account token
automountServiceAccountToken: false
# -- Pod-level security context
podSecurityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
# -- Container-level security context
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
service:
# -- Service type (ClusterIP, NodePort, LoadBalancer)
type: ClusterIP
# -- Service port
port: 8080
# -- Node port (only used when type is NodePort)
nodePort: ""
# -- Load balancer IP (only used when type is LoadBalancer)
loadBalancerIP: ""
# -- External traffic policy (Local or Cluster, only used when type is NodePort or LoadBalancer)
externalTrafficPolicy: ""
# -- Additional service annotations (e.g. for external-dns, service meshes)
annotations: {}
# -- Additional service labels
labels: {}
ingress:
# -- Enable ingress
enabled: false
# -- Ingress class name (e.g. nginx, traefik, haproxy)
className: ""
# -- Ingress annotations (e.g. cert-manager, auth, rate-limiting)
annotations: {}
# cert-manager.io/cluster-issuer: letsencrypt-production
# cert-manager.io/private-key-algorithm: ECDSA
# cert-manager.io/private-key-size: "384"
# cert-manager.io/private-key-rotation-policy: Always
# nginx.ingress.kubernetes.io/proxy-body-size: 128m
# -- Additional ingress labels
labels: {}
# -- Ingress hosts
hosts:
- host: vault.example.com
paths:
- path: /
pathType: Prefix
# -- Ingress TLS configuration
tls: []
# - secretName: vault-tls
# hosts:
# - vault.example.com
persistence:
# -- Enable persistent storage for /data
enabled: true
# -- Storage class name.
# Set to "-" to disable dynamic provisioning.
# Leave unset or null for the cluster default storage class.
# @default -- `nil` (cluster default)
storageClassName:
# -- Access modes
accessModes:
- ReadWriteOnce
# -- Storage size
size: 5Gi
# -- Use an existing PVC instead of creating one
existingClaim: ""
# -- Additional PVC annotations
annotations: {}
# -- Additional PVC labels
labels: {}
# -- Resource requests and limits
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
# -- Liveness probe configuration
livenessProbe:
httpGet:
path: /alive
port: http
initialDelaySeconds: 5
periodSeconds: 10
# -- Readiness probe configuration
readinessProbe:
httpGet:
path: /alive
port: http
initialDelaySeconds: 5
periodSeconds: 5
# -- Startup probe configuration (useful for slow-starting instances with large databases)
startupProbe: {}
# httpGet:
# path: /alive
# port: http
# failureThreshold: 30
# periodSeconds: 5
# -- Deployment revision history limit
revisionHistoryLimit: 3
# -- Pod annotations
podAnnotations: {}
# -- Pod labels
podLabels: {}
# -- Priority class name for pod scheduling
priorityClassName: ""
# -- Termination grace period in seconds
terminationGracePeriodSeconds: 30
# -- Node selector
nodeSelector: {}
# -- Tolerations
tolerations: []
# -- Affinity rules
affinity: {}
# -- Topology spread constraints for pod scheduling
topologySpreadConstraints: []
# - maxSkew: 1
# topologyKey: kubernetes.io/hostname
# whenUnsatisfiable: DoNotSchedule
# labelSelector:
# matchLabels: ...
# -- Init containers
initContainers: []
# -- Additional environment variables (plain key-value).
# Use this to set any vaultwarden env var not covered by the structured values above.
# These are added to the container env directly.
env: {}
# SIGNUPS_ALLOWED: "false"
# INVITATION_ORG_NAME: "My Org"
# SENDS_ALLOWED: "true"
# EMERGENCY_ACCESS_ALLOWED: "true"
# -- Environment variables sourced from Kubernetes secrets (secretKeyRef shorthand).
# Each key is the env var name, value specifies the secret and key to read from.
secretEnv: {}
# ADMIN_TOKEN:
# secretName: my-admin-secret
# secretKey: admin-token
# DATABASE_URL:
# secretName: my-db-secret
# secretKey: database-url
# SMTP_PASSWORD:
# secretName: my-smtp-secret
# secretKey: password
# -- Additional environment variables (raw Kubernetes env spec).
# Use this for complex env definitions like fieldRef, resourceFieldRef, etc.
extraEnv: []
# - name: POD_IP
# valueFrom:
# fieldRef:
# fieldPath: status.podIP
# -- Additional volume mounts for the vaultwarden container
extraVolumeMounts: []
# - name: custom-certs
# mountPath: /etc/ssl/custom
# readOnly: true
# -- Additional volumes
extraVolumes: []
# - name: custom-certs
# secret:
# secretName: custom-ca-certs
Loading…
Cancel
Save