Skip to content

vaultwarden

Metadata

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.

Env file format

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.