vaultwarden
| Field |
Value |
| Service |
vaultwarden |
| Purpose |
Self-hosted password manager compatible with Bitwarden clients |
| Criticality |
Tier 1 |
| Owner |
Platform / Security owner |
| Clusters |
local |
| Namespace |
vaultwarden |
| Exposure |
internet |
| Stateful |
yes |
| Backup class |
snapshot |
| RPO / RTO |
Daily backup target, 2 to 4 hours to restore |
| Last reviewed |
2026-06-29 |
1. Service Overview
Vaultwarden provides credential storage and password-management features and is therefore one of the more security-sensitive internet-facing applications in the estate. It also stores TOTP secrets and generates authenticator codes through the standard Bitwarden "authenticator key" item field; this is normal vault usage and requires no integration or API changes.
Summary
If it fails, users lose access to stored credentials and secure item synchronization until the service and data volume are restored.
Dependencies
| Dependency |
Type |
Why it matters |
| Traefik |
ingress |
External HTTPS and websocket path |
| SMTP |
notification |
Needed for mail-based account flows where enabled |
| Persistent storage |
storage |
Preserves the credential database and attachments |
2. Architecture Diagram
[Browser / Bitwarden client]
-> [Traefik]
-> [Vaultwarden]
-> [PVC-backed application data]
3. Deployment Specifications
| Item |
Value |
| Source path |
vaultwarden/base and vaultwarden/overlays/local |
| Deployment model |
Kustomize plus Fleet bundle (one shared entry point) |
| Namespace |
vaultwarden |
| Workload kind |
StatefulSet |
| Image |
vaultwarden/server:1.37.0 (pinned in base) |
| Scheduling |
edge node (node.io/ingress=true, tolerates node.io/role=edge) |
| Probes |
readiness + liveness on GET /alive:8080 |
| Pod security |
non-root (UID 33), read-only root FS, dropped capabilities, no privilege escalation |
| RBAC |
ServiceAccount only (no Role/RoleBinding) |
| Config files |
base/kustomization.yaml, overlays/local/kustomization.yaml, overlays/local/vault-config.env, fleet.yaml |
Cluster mapping
| Cluster |
Overlay path |
Notes |
| local |
vaultwarden/overlays/local |
The only overlay. Built by both kubectl apply -k locally and Fleet in Rancher; fleet.yaml points kustomize.dir at it. Secret vaultwarden-secrets is created out of band — see Secrets management |
4. Configuration Guide
Environment variables
Runtime configuration is split into a committed ConfigMap and a gitignored Secret, both loaded by the StatefulSet through envFrom.
vault-config.env mirrors the upstream .env.template for the pinned image, in the same section order. Settings this deployment relies on are active; the remaining useful knobs are present as commented lines carrying the upstream default. The active set is:
| Variable |
Source |
Purpose |
Secret? |
DOMAIN |
ConfigMap vaultwarden-config (vault-config.env, committed) |
Public URL; must match the IngressRoute host. Scopes WebAuthn credentials and email links |
no |
SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_FROM, SMTP_FROM_NAME |
ConfigMap vaultwarden-config |
SMTP transport (force_tls on 465) |
no |
DATA_FOLDER, ROCKET_PORT, ROCKET_WORKERS, WEB_VAULT_ENABLED |
ConfigMap vaultwarden-config |
Runtime wiring. ROCKET_PORT=8080 overrides the image default of 80, which UID 33 cannot bind |
no |
ENABLE_WEBSOCKET |
ConfigMap vaultwarden-config |
Live sync notifications, served on ROCKET_PORT since 1.30. Replaces the removed WEBSOCKET_ENABLED |
no |
SIGNUPS_ALLOWED, INVITATIONS_ALLOWED, SENDS_ALLOWED, EMERGENCY_ACCESS_ALLOWED, SHOW_PASSWORD_HINT |
ConfigMap vaultwarden-config |
Account and vault policy: closed instance, Send disabled, emergency access kept for break-glass |
no |
IP_HEADER, IP_HEADER_TRUSTED_PROXIES |
ConfigMap vaultwarden-config |
Real client IP behind Traefik. Login and admin rate limits key off this; a wrong value makes those limits global instead of per-client |
no |
DISABLE_ICON_DOWNLOAD, ICON_CACHE_TTL, HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS |
ConfigMap vaultwarden-config |
Outbound-request hardening. ICON_CACHE_TTL=0 is required by upstream alongside the icon disable |
no |
LOG_LEVEL, EXTENDED_LOGGING, USE_SYSLOG |
ConfigMap vaultwarden-config |
Timestamped logs on stdout/stderr for the cluster collector |
no |
PUSH_ENABLED |
ConfigMap vaultwarden-config |
Bitwarden push relay, not configured |
no |
SMTP_USERNAME, SMTP_PASSWORD |
Secret vaultwarden-secrets (.vault-secrets.env, gitignored) |
SMTP authentication |
yes |
ADMIN_TOKEN |
Secret vaultwarden-secrets |
Admin panel access; the panel is disabled entirely when unset |
yes |
Optional secret-class variables for features that are currently off (PUSH_INSTALLATION_ID/_KEY, HIBP_API_KEY, SSO_CLIENT_SECRET, YUBICO_SECRET_KEY, DUO_SKEY) are documented in vault-secrets.env.example so enabling a feature does not put a credential in the committed ConfigMap.
vault-config.env is read by Kustomize's configMapGenerator, which is neither a shell nor dotenv: it splits on the first = and takes the rest of the line literally. Inline comments, quotes, and padding all become part of the value. The failure is quiet — a malformed boolean makes get_env_bool() return None, so vaultwarden falls back to its compiled-in default and the setting only appears to be applied; a malformed string is used verbatim; a malformed LOG_LEVEL aborts startup. Settings changed via the admin panel are persisted to $DATA_FOLDER/config.json and override these variables.
ConfigMaps
| Resource |
Path |
Purpose |
vaultwarden-config |
vaultwarden/overlays/local/vault-config.env |
The single non-secret runtime config file, shared by both consumers |
Secrets management
- Secret name:
vaultwarden-secrets (namespace vaultwarden), created out of band with kubectl create secret generic ... --from-env-file=.vault-secrets.env. Nothing in Git generates it.
- Required keys:
SMTP_USERNAME, SMTP_PASSWORD, ADMIN_TOKEN. See overlays/local/vault-secrets.env.example, which also lists the optional secret-class keys for features that are currently off.
- Source of truth:
overlays/local/.vault-secrets.env is gitignored and supplied out of band. Do not commit real values.
- No
secretGenerator exists anywhere in this workload, and that is deliberate. Fleet's clone of the repo never contains the gitignored env file, so a generator on the build path made every sync fail with ErrApplied (env source files: [...] doesn't exist). The previous workaround — a duplicate overlays/local/fleet/ overlay carrying its own copy of every file — drifted and broke the Fleet path. Because out-of-band creation was already mandatory for Fleet, it is now the only path, which lets a single overlay serve both consumers. Neither Kustomize nor Fleet creates, updates, or deletes the Secret, so neither can clobber it on sync.
- The Secret must exist before the first reconcile; the pod will not start without it.
- Rotation trigger: admin changes, SMTP rotation, or incident response. Rotate by re-running the create command, then
kubectl -n vaultwarden rollout restart statefulset/vaultwarden.
- Recovery note: restore
.vault-secrets.env and recreate the Secret before redeploying the StatefulSet.
- Audit note: real
SMTP_PASSWORD and ADMIN_TOKEN values were previously committed in vault-config.env and remain in git history. History purge and rotation are tracked separately in context/progress-tracker.md.
5. Access Protocols
| Path |
URL or endpoint |
Audience |
Auth |
TLS terminates at |
| Internal |
Vaultwarden service in the namespace |
Cluster workloads |
namespace RBAC |
Traefik / Vaultwarden |
| External |
https://vault.mutana.fr |
End users |
Vaultwarden auth |
Traefik |
6. Operations and Observability
- Primary health indicators: readiness/liveness probes on
GET /alive:8080, StatefulSet healthy, PVC mounted.
- Dashboards or alerts: shared cluster monitoring and ingress health.
- Log locations: Vaultwarden pod logs.
- Known failure modes: PVC attach failure, SMTP issues, websocket routing errors, stale or missing
vaultwarden-secrets.
7. Backup and Recovery Notes
- Backup method: application data snapshot plus secret backup.
- Restore prerequisites: restored PVC and runtime secrets.
- Related runbook: ../runbooks/vaultwarden.md
8. Release and Change Notes
- Current deployed app version:
vaultwarden/server:1.37.0 (security release: fixes eight medium-severity advisories including icon-endpoint SSRF, cross-organization cipher/secret access, and organization policy bypass on directory import; also required for Bitwarden client v2026.7.0+ compatibility).
- Current chart version: N/A.
- Last significant change: re-pinned image from
latest (which had drifted to running 1.36.0) to 1.37.0 — 1.36.0 is incompatible with Bitwarden clients v2026.7.0+, which fail cipher deserialization against it (bw CLI: invalid type: JsValue(Object(...)), expected a string).
- Rollback reference: previous overlay revision in Git; snapshot the PVC before a version downgrade because vaultwarden data-format changes can make downgrades unsafe.