Self-Hosted Guide
This page is only relevant to you if you need to test self-hosted features. It is not required for most development work. If you just need a local server, go to the Server Setup Guide instead.
This page explains how to configure and run a self-hosted development server alongside a cloud development server. This is useful if:
- you need to test how a self-hosted instance communicates with the cloud
- you need to develop self-hosted features without upsetting your normal development environment
In the most common configuration, both the cloud and self-hosted development servers will be running with similar configuration:
- Services running on
http://localhost:{port}
(using different port numbers for cloud vs. self-hosted) - Local SQL database (although using a different database for each server)
Requirements
This guide assumes you have completed and are familiar with the techniques in Server Setup Guide. Please make sure you have a working development environment for a cloud-configured server before worrying about getting a self-hosted instance connected to it.
Generate Installation Id and Key
Every self-hosted instance is defined by an Installation Id and Key. These will be stored two places:
- As user secrets in your self-hosted instance, and
- In the
Installations
table of your cloud-configured instance, so that it can authenticate requests from your self-hosted server
To get an Id and Key, it’s fine to either
- request a host installation ID, or
- generate a Guid (Id) and random alphanumeric string (key)
Record these for use in the next steps.
Self-Hosted Secrets Configuration
If you’re struggling to remember about user secrets, review User Secrets.
The Dev:SelfHostOverride:GlobalSettings
section of the user secrets specifies setting overrides
for local self-hosted development instances. Anything in the override section will apply instead of
the value given in GlobalSettings
. This allows you to have a separate configuration (such as the
database connection string) for your cloud and self-hosted development servers.
We configure these settings in the user secrets because we need to be able to define setting values that true self-hosted instances are specifying in environment variables in their Docker containers. We are using the secrets file do this instead of setting environment variables on our machine and letting the build in .NET Core configuration build our settings for us.
Currently, we only override GlobalSettings
. Any other user secret that needs overriding will
require a code change to do so. Check out ServiceCollectionExtension.AddGlobalSettingsServices
in
the server repository to see how we’re doing it today
(fragile link to the code).
The internal user secrets contains a minimum override example. You will need
to update the following values in the Dev:SelfHostOverride:GlobalSettings
section:
- Installation Id and Key, using the values you just generated
- A SQL Server password for a new SQL database we will be creating below. It can be copied from the
cloud-configured settings already in your
secrets.json
(i.e. use the same password as your cloud-configured server) or a new one can be generated. - any other blank values
After saving your changes to secrets.json
, apply your changes by running the following command:
pwsh setup_secrets.ps1 -clear
You have now updated the user secrets for your self-hosted instance.
Database Configuration
Be sure that your Docker container is running before setting up the database.
We will now create a second database for our self-hosted configuration, so that the self-hosted instance can have an independent data set for development.
If you followed Server Setup Guide when creating your
cloud-configured database, you just need to run the same PowerShell migration script with an
argument of -selfhost
:
pwsh migrate.ps1 -selfhost
This will create a new database called vault_dev_self_host
and/or run unknown migrations against
it.
You must call migrate.ps1
with the -selfhost
option in the future to keep your self-host
database up-to-date with any migrations.
Define Installation Id and Key for Your Cloud Database
You need to manually add the Installation key to your cloud-configured instance, so that it knows about your self-hosted instance and will allow access when API calls need to be made between the two. Feel free to do this with any tool you like (e.g. Azure Data Studio) or the below script:
/opt/mssql-tools/bin/sqlcmd -S mssql -d vault_dev -U sa -P <<SA_PASSWORD>> -I -i <<SCRIPT_FILE>>
where <<SA_PASSWORD>>
is your SQL SA password for your cloud database and <<SCRIPT_FILE>>
points to a file containing:
INSERT INTO [vault_dev].[dbo].[Installation]
(
[Id]
,[Email]
,[Key]
,[Enabled]
,[CreationDate]
)
VALUES
(
'<<YOUR_ID>>'
,'<<YOUR_DEV_EMAIL>>'
,'<<YOUR_KEY>>'
,1
,GETUTCDATE()
)
where <<YOUR_ID>>
is your installation id, <<YOUR_DEV_EMAIL>>
is your email address, and
<<YOUR_KEY>>
is your installation key.
Running
Server
When running in a self-hosted configuration, services will by default be at +1 to the port number at which they run in a cloud-configured instance.
Above, we set up a series of user secret overrides that will allow us to run our self-hosted instance. We need to be sure we start up our server to use these settings. The server code will use these settings if the following two conditions are met:
- Environment is Development
developSelfHosted
istrue
We do this differently based on how you will be running the server. In your environment, the
self-hosted launch configurations (e.g. "Api-SelfHost") will set the Environment and
developSelfHosted
flag for you.
- Visual Studio Code
- Visual Studio / Rider
- Terminal
We have a number of launch configurations as well as combined configurations to make launching the
services easy. By default, the individual self-host launches are hidden. Navigate to launch.json
to un-hide them.
Run configurations have been provided to start a given service in a self-hosted mode.
To run self-hosted from the CLI, you will need to:
-
Open a new terminal window in the root of the server repository.
-
Restore the nuget packages required for the Identity service:
cd src/Identity
dotnet restore -
Start the Identity service:
dotnet run --launch-profile Identity-SelfHost
-
Test that the Identity service is alive by navigating to http://localhost:33657/.well-known/openid-configuration
-
In another terminal window, restore the nuget packages required for the Api service:
cd src/Api
dotnet restore -
Start the Api Service:
dotnet run --launch-profile Api-SelfHost
-
Test that the Api service is alive by navigating to http://localhost:4001/alive
To start any other services, follow the same format, including --launch-profile
with the
appropriate self-hosted launch configuration.
If you cannot connect to the Api or Identity projects, check the terminal output to confirm the ports they are running on.
Web Client
From the clients-selfhost/apps/web
directory, you can execute
npm run build:bit:selfhost:watch
npm run build:oss:selfhost:watch
to spin up a Bitwarden-licensed or OSS web server. The default port will be 8081
, so you can run
both a cloud-configured and self-hosted-configured web client at once. It is also configured to
point at the default *-SelfHost
ports for the various server projects.
How the configuration sausage is made
Our web configurations live in config/
. Each has a sub-object called dev
. For this, the config
object have had the dev
object re-defined to dev: {cloud: {}, selfHosted: {}}
. In our webpack
config file, we are updating proxy and port settings based on these value.
This of the dev
object as containing both the configuration for cloud and selfHosted development
environments.
Licensed Features
If you need to develop against licensed features on your self-hosted instance, you will need to unlock them with a license file that is registered in your cloud-configured instance.
To do this, you should first start both your local cloud-configured and self-hosted web clients, as both environments will be necessary to acquire and apply the license.
You can now choose which type of license you would like to apply. The instructions vary for each, but the best resource is the Bitwarden Help Center documentation: