Open-Source Wikis

/

Bitwarden Server

/

Systems

/

Configuration & secrets

bitwarden/server

Configuration & secrets

Active contributors: platform team.

Purpose

Every Bitwarden service reads its configuration from the same strongly-typed object: GlobalSettings (src/Core/Settings/GlobalSettings.cs). It is built by services.AddGlobalSettingsServices(Configuration, Environment) and bound from the standard ASP.NET Core configuration sources — appsettings.json, appsettings.<Environment>.json, environment variables, user-secrets, and (in cloud) Azure Key Vault.

Directory layout

src/Core/Settings/
├── GlobalSettings.cs                # Root object. Sub-objects for SqlServer, Stripe, Notifications, Mail, ...
├── ConfigurationExtensions.cs       # Helpers for binding nested sections
├── DataProtectionSettings.cs
├── DistributedCacheSettings.cs
├── ServiceBusSettings.cs
├── ...
└── (one file per logical config section)

src/Core/Auth/Settings/
└── PasswordlessAuthSettings.cs       # Auth-team-owned overrides

src/Identity/IdentityServerSettings.cs
src/Billing/BillingSettings.cs
src/Notifications/  (no separate settings file — uses GlobalSettings)
src/Admin/AdminSettings.cs

How it's bound

SharedWeb.Utilities.ServiceCollectionExtensions.AddGlobalSettingsServices:

public static GlobalSettings AddGlobalSettingsServices(
    this IServiceCollection services,
    IConfiguration configuration,
    IWebHostEnvironment env)
{
    var globalSettings = new GlobalSettings();
    ConfigurationBinder.Bind(configuration.GetSection("globalSettings"), globalSettings);
    services.AddSingleton(globalSettings);
    services.AddSingleton<IGlobalSettings>(globalSettings);
    return globalSettings;
}

Sub-objects are bound automatically; e.g. globalSettings.Stripe.ApiKey comes from globalSettings:stripe:apiKey in the configuration.

The configuration sources are layered (later sources override earlier):

  1. appsettings.json — defaults checked into the repo.
  2. appsettings.<Environment>.json — environment-specific overrides (Development, Production, QA, SelfHosted).
  3. Environment variables — used heavily by the self-host Docker stack (the Setup utility writes them to global.override.env).
  4. User secrets — for local dev.
  5. Azure Key Vault (cloud only) — read via the Azure provider when globalSettings.Vault.AzureKeyvaultUri is set.

Self-host: the Setup utility

util/Setup/ is a small console app that runs once on the operator's host before the stack comes up. It collects an installation id / installation key (issued by the Bitwarden cloud installation API), generates an Identity signing certificate, and writes global.override.env with everything the rest of the stack needs:

  • DB connection strings (one per provider, with the right host/user/db).
  • Azure Storage connection strings (for Azurite or remote storage).
  • Push relay credentials.
  • License-server pointer.
  • Reverse-proxy URLs.

The compose file generated by Setup mounts global.override.env into every service container.

Per-app appsettings.*.json

Each deployable service has its own appsettings.json that fills in defaults specific to that service (port numbers, log levels, the IpRateLimit policy table). Look at src/Api/appsettings.json, src/Identity/appsettings.json, etc.

The appsettings.SelfHosted.json variants are loaded when the BWS_ENABLE_SELF_HOST env var (or the equivalent settings flag) is set, and override the cloud defaults that don't apply on-prem.

Sensitive values

Never hardcode secrets:

  • Cloud — secrets land in Key Vault and are bound at boot via the Azure config provider.
  • Self-host — secrets are written to global.override.env by the Setup utility (encrypted at rest using OS-level mechanisms).
  • Dev — dev/setup_secrets.ps1 populates dotnet user-secrets for each project.

Key fields (Stripe.ApiKey, Mail.Smtp.Password, SqlServer.ConnectionString, OidcIdentityClientKey) must always be supplied via secrets, never appsettings.*.json.

Hot reload

Most settings are bound once at boot. A few — feature flags via IFeatureService, application-cache invalidation via the Service Bus topic — are refreshed at runtime. If you change a config value that's used inside a singleton, you need to restart the service.

Entry points for modification

  • New top-level config section → add a property to GlobalSettings and a sub-object class under src/Core/Settings/.
  • Read it from a service → inject GlobalSettings (or a typed sub-object) rather than IConfiguration.
  • Change Setup behaviour → edit util/Setup/. Be aware that self-hosted operators will not re-run Setup automatically; they must run bitwarden.sh updateself.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Configuration & secrets – Bitwarden Server wiki | Factory