committed by
GitHub
14 changed files with 1508 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||
# Patterns to ignore when building packages. |
|||
.DS_Store |
|||
*.swp |
|||
*.bak |
|||
*.tmp |
|||
*~ |
|||
.git |
|||
.gitignore |
|||
.project |
|||
.idea |
|||
*.tmproj |
|||
.vscode |
|||
@ -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 |
|||
@ -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 |
|||
``` |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 }} |
|||
@ -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 |
|||
@ -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…
Reference in new issue