How Vaultwarden Icon Service Works: Internal vs External Fetching and Caching Options
Vaultwarden’s icon service fetches favicon images either internally by downloading them directly or externally by redirecting clients to third-party providers, with configurable caching TTLs, redirect HTTP codes, and Content-Security-Policy headers.
The icon service supplies favicon images for domains stored in your Vaultwarden password vault. According to the Vaultwarden source code in dani-garcia/vaultwarden, the service operates through two distinct modes—internal fetching and external redirection—controlled by configuration values defined in src/config.rs and implemented in src/api/icons.rs.
Configuring the Icon Service Mode
The icon_service configuration value defined in src/config.rs (line 670) determines which operational mode is active. When set to internal, Vaultwarden handles all icon fetching directly. Any other value—such as bitwarden, duckduckgo, google, or a custom URL template containing exactly one {} placeholder—triggers the external redirection flow.
For external services, Vaultwarden generates the target URL using _icon_service_url (line 677), which substitutes the domain name into the template. The system also generates a Content-Security-Policy source list via _icon_service_csp (line 779) to ensure browsers can load the external resource.
Request Routing and Handler Selection
The routes() function in src/api/icons.rs (lines 27-31) examines the configured icon_service at startup and registers the appropriate handler:
pub fn routes() -> Vec<Route> {
match CONFIG.icon_service().as_str() {
"internal" => routes![icon_internal],
_ => routes![icon_external],
}
}
This ensures that requests to /domain/icon.png route to either icon_internal or icon_external based on your configuration.
External Redirect Flow
When operating in external mode, the icon_external function (lines 85-108) processes requests through the following steps:
- Domain validation – Checks for malformed domains or entries in the block list, returning a negative cache response if invalid.
- URL generation – Fills the template placeholder:
CONFIG._icon_service_url().replace("{}", domain). - Redirect construction – Uses the HTTP status code defined by
icon_redirect_code(default 302). - TTL caching – Wraps the response in
Cached::ttlwithicon_cache_ttlto prevent repeated processing.
let url = CONFIG._icon_service_url().replace("{}", domain);
let redir = match CONFIG.icon_redirect_code() { ... };
Cached::ttl(redir, CONFIG.icon_cache_ttl(), true)
Internal Fetching Flow
The icon_internal function (lines 110-138) handles direct icon downloads when icon_service is set to internal:
- Validation – Performs domain and block list checks identical to the external path.
- Cache checking – Calls
get_icon(domain).await, which:- Checks for negative-cache markers (
*.miss) viaicon_is_negcached(lines 41-62). - Attempts to read positive cache entries via
get_cached_iconand verifies freshness withicon_is_expired(lines 31-38).
- Checks for negative-cache markers (
- Download – If cache misses and
disable_icon_downloadisfalse, executesdownload_iconto fetch the resource. - Storage – Saves successful downloads via
save_iconfor future requests. - Response – Returns image bytes with the correct
Content-Typewrapped inCached::ttlusingicon_cache_ttl.
Cached::ttl((ContentType::new("image", icon_type), icon), CONFIG.icon_cache_ttl(), true)
Caching Configuration
Vaultwarden implements a two-tier caching system using OpenDAL storage under PathType::IconCache. The cache behavior is controlled by three key settings in src/config.rs:
icon_cache_ttl(default 2,592,000 seconds / 30 days) – Duration that successfully downloaded icons remain valid. After expiry, Vaultwarden re-downloads the icon.icon_cache_negttl(default 259,200 seconds / 3 days) – Duration that failed download markers (*.missfiles) remain cached, preventing repeated attempts on broken domains.icon_download_timeout(default 10 seconds) – Maximum time allowed for HTTP requests during icon fetching.
Redirect Status Codes
The icon_redirect_code setting (line 81) supports four HTTP status codes for external redirects:
- 301 – Permanent redirect (legacy). Enables long-term client caching but may have compatibility issues with some Bitwarden clients.
- 302 – Temporary redirect (legacy). The default value ensuring maximum client compatibility.
- 307 – Temporary redirect with method preservation. Useful for testing new external services without breaking existing caches.
- 308 – Permanent redirect with method preservation. Preferred when the external service is permanent and you want clients to cache the redirect.
Content-Security Policy Handling
When redirecting to external providers, Vaultwarden must update the Content-Security-Policy headers to allow the browser to fetch from the third-party origin. The generate_icon_service_csp function (lines 52-66) extracts the fixed portion of the URL template to build the CSP source list. For Google specifically, the function adds *.gstatic.com to accommodate secondary redirects performed by Google's infrastructure.
Disabling Icon Downloads
Setting disable_icon_download to true (line 12) completely disables the internal fetcher. In this mode:
- Existing cached icons remain servable until their
icon_cache_ttlexpires. - New requests for uncached icons return the fallback image (
fallback-icon.png) without initiating external HTTP requests. - The service effectively behaves like the external variant with an empty URL template.
Configuration Examples
Using DuckDuckGo External Service
Configure Vaultwarden to redirect icon requests to DuckDuckGo with permanent redirect caching:
ICON_SERVICE=duckduckgo
ICON_REDIRECT_CODE=308
ICON_CACHE_TTL=2592000
ICON_CACHE_NEGTTL=86400
Vaultwarden responds with a 308 redirect to URLs like https://icons.duckduckgo.com/ip3/example.com.ico, with CSP headers allowing https://icons.duckduckgo.com.
Custom URL Template
Specify a corporate icon service with a custom template:
ICON_SERVICE="https://my-icons.mycorp.com/lookup/{}"
Requests for /example.org/icon.png receive a 302 redirect (default) to https://my-icons.mycorp.com/lookup/example.org.
Internal Fetching with Extended Timeout
Maintain internal fetching with increased timeout for slower websites:
ICON_SERVICE=internal
DISABLE_ICON_DOWNLOAD=false
ICON_DOWNLOAD_TIMEOUT=15
ICON_CACHE_TTL=2592000
Disabling Downloads to Reduce External Traffic
Prevent all external HTTP requests while serving existing cache:
DISABLE_ICON_DOWNLOAD=true
ICON_CACHE_TTL=0
Summary
- Vaultwarden’s icon service supports two operational modes:
internal(direct download) and external (HTTP redirect). - The
icon_serviceconfiguration value insrc/config.rscontrols the mode, accepting eitherinternalor a URL template for third-party providers. - Caching uses positive TTL (
icon_cache_ttl, default 30 days) for successful icons and negative TTL (icon_cache_negttl, default 3 days) for failed attempts, stored via OpenDAL. - External redirects support four HTTP status codes (301, 302, 307, 308) configurable via
icon_redirect_code. - CSP headers are automatically generated for external services to allow browser fetching, with special handling for Google's secondary redirects.
- Setting
disable_icon_downloadtotrueblocks all outbound icon traffic while continuing to serve existing cached entries.
Frequently Asked Questions
What is the default icon service mode in Vaultwarden?
The default mode is internal, configured in src/config.rs (line 670). In this mode, Vaultwarden fetches icons directly from the target websites, parses HTML for favicon links, and caches the results locally using OpenDAL storage. This eliminates reliance on third-party services but requires outbound HTTP connections from your Vaultwarden instance.
How does Vaultwarden handle icon caching?
Vaultwarden implements a dual-layer caching strategy via src/api/icons.rs. Successful downloads are stored with a positive TTL defined by icon_cache_ttl (default 2,592,000 seconds), while failed attempts create *.miss marker files cached for icon_cache_negttl (default 259,200 seconds). The get_cached_icon function checks these markers before attempting downloads, and icon_is_expired (lines 31-38) determines whether cached entries need refreshing.
Can I use a custom icon provider with Vaultwarden?
Yes. Set icon_service to any string containing exactly one {} placeholder, such as https://my-cdn.com/icons/{}.png. Vaultwarden treats this as a custom external provider, substituting the requested domain for {} and redirecting clients to the resulting URL. The generate_icon_service_csp function automatically extracts the base domain for Content-Security-Policy headers.
What happens when icon downloads are disabled?
When disable_icon_download is set to true (line 12), Vaultwarden skips the download_icon call in src/api/icons.rs. The service returns existing cached icons until they expire per icon_cache_ttl, after which requests receive the fallback icon (fallback-icon.png). This configuration ensures zero outbound HTTP traffic for icon fetching while maintaining functionality for previously cached entries.
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 →