Skip to main content

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.

info

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​

  1. Configure Git to ignore the Prettier revision:

    git config blame.ignoreRevsFile .git-blame-ignore-revs
  2. (Optional) Set up the pre-commit dotnet format hook:

    git config --local core.hooksPath .git-hooks

    Formatting requires a full build, which may be too slow to do every commit. As an alternative, you can run dotnet format from 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.

  1. Get a template secrets.json. We need to get an initial version of secrets.json, which you will modify for your own secrets values.

    Navigate to the dev folder in your server repo and copy the example secrets.json file.

    cd dev
    cp secrets.json.example secrets.json
  2. Choose a password for your local SQL Server. You will use it for the SQL Server sa account.

    caution

    Your 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 (%).
  3. Update secrets.json with your own values:

    • sqlServer > connectionString: insert your SQL Server password where indicated
  4. Once you have your secrets.json complete, run the below command from the dev folder 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
note

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.json to every project by running setup_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​

  1. 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 dev folder, run:

    docker compose --profile cloud --profile mail --profile idp down
    note

    Aspire creates its own SQL Server data volume. Data in your Docker Compose database is not carried over.

  2. Install the PowerShell Az module, 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"
  3. Trust the ASP.NET Core development certificate, which the Aspire dashboard uses for HTTPS:

    dotnet dev-certs https --trust
  4. From the dev folder, navigate to the AppHost folder and store your SQL Server password in the AppHost's user secrets. This must be the same password you put in the sqlServer connection string in secrets.json.

    cd ../AppHost
    dotnet user-secrets set "Database:Password" "<your SQL Server password>"
    warning

    Keep passwords and tokens in user secrets. Don't add them to AppHost/appsettings.Development.json, which is checked in.

Start the server​

  1. From the AppHost folder, run:

    dotnet run
    tip

    If you have the Aspire CLI installed, you can run aspire run from the root of the repository instead.

  2. The Aspire dashboard opens in your browser at https://localhost:17271. It shows the status, logs, traces, and environment variables of every resource.

  3. Wait for setup-secrets and run-db-migrations to finish. The services wait for both and then start.

  4. Test that the Identity service is alive by navigating to http://localhost:33656/.well-known/openid-configuration

  5. 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-frontend runs the web vault from a sibling clients checkout. You still need to complete the web vault setup, including npm ci.
  • idp runs 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:

SettingPurpose
Services:<name>:BasePortPort for a service, if the default conflicts with something on your machine
ClientsPathPath to the clients repository's apps folder for web-frontend
SelfHostRun in a self-hosted configuration
AdditionalProjects:<name>:PathAdd another project to the orchestration without changing code
AdditionalProjects:<name>:ReferencedBy:0Give 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​

note

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.

info

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.

note

We recommend continuing with the Web Vault afterwards, since many administrative operations can only be performed in it.