How the Vaultwarden Web Vault Works: Static Asset Serving and Experimental Client Feature Flags
Vaultwarden bundles a self-contained Web Vault that serves the Bitwarden-compatible UI from the same binary, controlled by WEB_VAULT_ENABLED and WEB_VAULT_FOLDER environment variables, while experimental client feature flags enable incremental rollouts via a comma-separated list parsed into a HashMap exposed through the /api/config endpoint.
The Vaultwarden project (dani-garcia/vaultwarden) ships a lightweight, Rust-powered server that replaces Bitwarden's heavy dependencies with a single binary. Understanding how the Vaultwarden Web Vault serves static assets and how experimental client feature flags unlock beta functionality is essential for administrators customizing their deployment.
Enabling and Serving the Vaultwarden Web Vault
Configuration Parameters
In src/config.rs, the make_config! macro generates two critical settings for the Web Vault. The web_vault_enabled boolean defaults to true and reads from the WEB_VAULT_ENABLED environment variable. The web_vault_folder string defaults to web-vault/ and maps to WEB_VAULT_FOLDER. These values determine whether the UI activates and where the server looks for static files.
Startup Validation
Before accepting connections, the check_web_vault() function in src/main.rs verifies that index.html exists inside the configured folder. If the file is missing, the process aborts immediately with an error message directing administrators to the project wiki for build instructions.
Routing and Static Asset Delivery
All HTTP routes for the UI are assembled in src/api/web.rs. When web_vault_enabled is true, the router registers handlers including web_index (serves index.html), web_files (serves CSS, JS, and images), and vaultwarden_css (serves compiled styles). Both web_index and web_files wrap their responses in the Cached utility to set HTTP cache headers.
Dynamic CSS Generation
The server generates CSS on-the-fly from scss/vaultwarden.scss, injecting runtime configuration values such as signup availability and WebAuthn support. This templating approach allows the Web Vault UI to adapt to server settings without requiring a rebuild of the static JavaScript bundle.
Cache Control Strategy
The Cached wrapper in src/util.rs stores handler results for a configurable TTL. The Web Vault uses a short TTL for index.html to ensure configuration changes reflect quickly, while the compiled CSS receives a one-day TTL for optimal performance.
Experimental Client Feature Flags
Configuration and Parsing
The raw flag string is stored in experimental_client_feature_flags (default empty) in src/config.rs, populated from the EXPERIMENTAL_CLIENT_FEATURE_FLAGS environment variable. The helper parse_experimental_client_feature_flags in src/util.rs converts the comma-separated string into a HashMap<String,bool>. This parser silently drops deprecated flags like autofill-overlay to prevent legacy configurations from breaking.
Validation and API Exposure
The API core layer in src/api/core/mod.rs calls the parser to validate that only recognized flags are present, emitting an error if an unknown flag is supplied. The parsed map is exposed through the /api/config endpoint and injected into template contexts, enabling both API consumers and the Web Vault UI to detect enabled features.
Client-Side Usage
Clients can check for flags such as enable-new-login-flow or new-sync-algorithm. The server automatically makes these flags available to Handlebars templates and API responses, allowing feature-gated rollouts without deploying a new server version.
Practical Configuration Examples
Enable the Web Vault in a Docker Compose file:
services:
vaultwarden:
image: vaultwarden/server:latest
environment:
- WEB_VAULT_ENABLED=true
- WEB_VAULT_FOLDER=/custom/vault
volumes:
- ./custom-vault:/custom/vault
Activate experimental flags before starting the server:
export EXPERIMENTAL_CLIENT_FEATURE_FLAGS="new-sync-algorithm,quick-unlock"
./vaultwarden
Query the current flag state via the API:
curl -s https://vault.example.com/api/config | jq '.experimental_client_feature_flags'
Summary
- The Web Vault is controlled by
WEB_VAULT_ENABLEDand serves files fromWEB_VAULT_FOLDER, with startup validation insrc/main.rsviacheck_web_vault(). - Static assets are routed through handlers in
src/api/web.rsusing theCachedwrapper fromsrc/util.rsto optimize delivery. - Experimental client feature flags are parsed from comma-separated strings in
src/util.rsbyparse_experimental_client_feature_flagsand validated insrc/api/core/mod.rs. - Flags are exposed via
/api/configand template contexts to enable gradual feature rollouts without binary updates.
Frequently Asked Questions
What happens if the Web Vault folder is missing at startup?
The server calls check_web_vault() in src/main.rs, detects the missing index.html, and aborts with a clear error message pointing to the build documentation. This ensures administrators cannot accidentally run a broken UI.
Can I disable the Web Vault and use only the API?
Yes. Set WEB_VAULT_ENABLED=false to run Vaultwarden as a headless API server. This configuration is useful for mobile-only deployments or when serving the UI through a separate reverse proxy or CDN.
How do I know which experimental flags are available?
Check the official Vaultwarden documentation or review the validation logic in src/api/core/mod.rs and the parser in src/util.rs. The server maintains a known list of valid flags and rejects unknown entries with an error on startup.
Do experimental flags persist across restarts?
Yes, because they are read from the EXPERIMENTAL_CLIENT_FEATURE_FLAGS environment variable each time the server initializes. The parsed HashMap is rebuilt on every launch, ensuring consistent behavior until you modify the environment variable.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →