Setup Guide
This page will show you how to set up a local Bitwarden server for development purposes.
The Bitwarden server is comprised of several services that can run independently. For a basic development setup, you will need the Api and Identity services.
This guide runs the server with .NET Aspire. The AppHost project in the
server repository starts the supporting containers, applies your user secrets, migrates the
database, and runs every server service from a single command. If you can't use Aspire, follow the
Manual Setup after you configure your user secrets.
Before you start: make sure you’ve installed the recommended Tools and Libraries, including:
- Docker Desktop
- Visual Studio 2022
- Powershell
- .NET 10 SDK
- Rust latest stable version - (preferably installed via rustup)
- Your preferred database management tool
Clone the repository
Clone the Bitwarden Server project and navigate to the root of the cloned repository:
git clone https://github.com/bitwarden/server.git
cd server
Configure Git
-
Configure Git to ignore the Prettier revision:
git config blame.ignoreRevsFile .git-blame-ignore-revs -
(Optional) Set up the pre-commit
dotnet formathook:git config --local core.hooksPath .git-hooksFormatting requires a full build, which may be too slow to do every commit. As an alternative, you can run
dotnet formatfrom the command line when convenient (e.g. before requesting a PR review).
Configure user secrets
User secrets
are a method for managing application settings on a per-developer basis. They override the settings
in appSettings.json of each project. Your user secrets file should match the structure of the
appSettings.json file for the settings you intend to override.
We provide a helper script which simplifies setting user secrets for all projects in the server repository.
-
Get a template
secrets.json. We need to get an initial version ofsecrets.json, which you will modify for your own secrets values.Navigate to the
devfolder in your server repo and copy the examplesecrets.jsonfile.cd devcp secrets.json.example secrets.json -
Choose a password for your local SQL Server. You will use it for the SQL Server
saaccount.cautionYour MSSQL password must comply with the following password complexity guidelines
- It must be at least eight characters long.
- It must contain characters from three of the following four categories:
- Latin uppercase letters (A through Z)
- Latin lowercase letters (a through z)
- Base 10 digits (0 through 9)
- Non-alphanumeric characters such as: exclamation point (!), dollar sign ($), number sign (#), or percent (%).
-
Update
secrets.jsonwith your own values:sqlServer>connectionString: insert your SQL Server password where indicated
installation>idandkey: request a hosting installation Id and Key and insert them herelicenseDirectory: set this to an empty directory, this is where uploaded license files will be stored.
-
Once you have your
secrets.jsoncomplete, run the below command from thedevfolder to add the secrets to each Bitwarden server project. Aspire also does this each time it starts.pwsh setup_secrets.ps1
The helper script also supports an optional -clear switch which removes all existing settings
before re-applying them:
pwsh setup_secrets.ps1 -clear
Aspire runs setup_secrets.ps1 -clear every time it starts. If you use Aspire, make your changes in
dev/secrets.json rather than with dotnet user-secrets set on an individual project, because
per-project changes are cleared on the next run.
Run with Aspire
The AppHost project orchestrates the whole local environment. When you start it, Aspire:
- starts SQL Server, Azurite, MailCatcher, and Redis containers
- applies
dev/secrets.jsonto every project by runningsetup_secrets.ps1 -clear - creates and migrates the database by running
migrate.ps1 - bootstraps Azurite by running
setup_azurite.ps1 - starts the Admin, Api, Billing, Events, EventsProcessor, Icons, Identity, Notifications, Scim, and Sso services once their dependencies are ready
The AppHost README contains the full configuration reference.
Set up Aspire
-
Stop any Docker Compose containers from a previous manual setup. Aspire uses the same host ports (for example 1433 for SQL Server and 1080 for MailCatcher) and won't start while they are in use. From the
devfolder, run:docker compose --profile cloud --profile mail --profile idp downnoteAspire creates its own SQL Server data volume. Data in your Docker Compose database is not carried over.
-
Install the PowerShell
Azmodule, which the Azurite setup script needs. This may take a few minutes to complete without providing any user feedback (it may appear frozen).pwsh -Command "Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force" -
Trust the ASP.NET Core development certificate, which the Aspire dashboard uses for HTTPS:
dotnet dev-certs https --trust -
From the
devfolder, navigate to theAppHostfolder and store your SQL Server password in the AppHost's user secrets. This must be the same password you put in thesqlServerconnection string insecrets.json.cd ../AppHostdotnet user-secrets set "Database:Password" "<your SQL Server password>"warningKeep passwords and tokens in user secrets. Don't add them to
AppHost/appsettings.Development.json, which is checked in.
Start the server
-
From the
AppHostfolder, run:dotnet runtipIf you have the Aspire CLI installed, you can run
aspire runfrom the root of the repository instead. -
The Aspire dashboard opens in your browser at https://localhost:17271. It shows the status, logs, traces, and environment variables of every resource.
-
Wait for
setup-secretsandrun-db-migrationsto finish. The services wait for both and then start. -
Test that the Identity service is alive by navigating to http://localhost:33656/.well-known/openid-configuration
-
Test that the Api service is alive by navigating to http://localhost:4000/alive
Aspire runs the database migrations and re-applies dev/secrets.json on every start. After you pull
changes or edit secrets.json, restart the AppHost, or restart the setup-secrets or
run-db-migrations resource from the dashboard.
To stop the server, press Ctrl+C in the terminal running the AppHost. The SQL Server, Azurite,
MailCatcher, and Redis containers are persistent and keep running between sessions, so later starts
are faster.
Optional resources
Some resources don't start automatically. Start them from the Aspire dashboard when you need them:
web-frontendruns the web vault from a siblingclientscheckout. You still need to complete the web vault setup, includingnpm ci.idpruns a SAML identity provider for SSO development.
To tunnel the Billing service through ngrok for Stripe webhooks, see Ingress Tunnels.
Change Aspire settings
Override AppHost settings with user secrets from the AppHost folder. For example, to move the Api
service to another port:
dotnet user-secrets set "Services:api:BasePort" "4001"
Common settings include:
| Setting | Purpose |
|---|---|
Services:<name>:BasePort | Port for a service, if the default conflicts with something on your machine |
ClientsPath | Path to the clients repository's apps folder for web-frontend |
SelfHost | Run in a self-hosted configuration |
AdditionalProjects:<name>:Path | Add another project to the orchestration without changing code |
AdditionalProjects:<name>:ReferencedBy:0 | Give an existing service a reference to the additional project |
Restart the AppHost to apply changes. Path settings are relative to the AppHost folder, so use
absolute paths if you work from a Git worktree.
Debug with Aspire
Debug the AppHost project from your IDE. Visual Studio and Rider attach the debugger to each
service that the AppHost starts, so breakpoints in Api, Identity, and the other services work
without launching them separately. Rider requires the Aspire plugin.
Local services
Aspire and the manual setup both provide the following local services.
SQL Server
You can connect to the Microsoft SQL Server using your preferred database management tool with the following credentials:
- Server: localhost
- Port: 1433
- Username: sa
- Password: the SQL Server password you chose when you configured user secrets
Mailcatcher
The server uses emails for many user interactions. We provide a pre-configured instance of MailCatcher, which catches any outbound email and prevents it from being sent to real email addresses. You can open its web interface at http://localhost:1080.
Redis
Redis provides distributed caching capabilities. Available caching configurations have specific fallbacks including process-scoped, in-memory caching, or database store for self-hosted configurations.
For details on which features can take advantage of Redis and available configurations, including
connection string setting in secrets.json, see
CACHING.md.
(Optional) Monitor Redis activity using the Redis
CLI. With Aspire, open the redis resource in the dashboard to find its container, then use
docker exec with that container name. With the manual setup, run this from the dev folder:
docker compose exec redis redis-cli
Azurite
This section applies to Bitwarden developers only.
Azurite is an emulator for Azure Storage API and supports Blob, Queues and Table storage. We use it to minimize the online dependencies required for developing in a cloud environment.
Aspire bootstraps Azurite for you with its azurite-setup resource. With the manual setup, follow
Bootstrap Azurite.
Client connection
Connect a client to your local server by configuring the client’s Api and Identity endpoints. Refer to https://bitwarden.com/help/article/change-client-environment/ and the instructions for each client in the Contributing Documentation.
Now that the client is configured to use your local development server, you can proceed to use the client to create an account and validate your local server changes.
If you cannot connect to the Api or Identity projects, check the terminal output or the Aspire dashboard to confirm the ports they are running on.
We recommend continuing with the Web Vault afterwards, since many administrative operations can only be performed in it.