Linux Offline Deployment
This article will walk you through the procedure to install and deploy Bitwarden to your own server in an offline or air-gapped environment. Please review Bitwarden
warning
Manual installations should be conducted by advanced users only. Only proceed if you are very familiar with Docker technologies and desire more control over your Bitwarden installation.
Manual installations lack the ability to automatically update certain dependencies of the Bitwarden installation. As you upgrade from one version of Bitwarden to the next you will be responsible for changes to required environment variables, changes to nginx default.conf, changes to docker-compose.yml, and so on.
We will try to highlight these in the
Requirements
Minimum | Recommended | |
|---|---|---|
Processor | x64, 1.4GHz | x64, 2GHz dual core |
Memory | 2GB RAM | 4GB RAM |
Storage | 12GB | 25GB |
Docker Version | Engine 26+ and Compose | Engine 26+ and Compose |
ª - Docker Compose is automatically installed as a plugin when you download Docker Engine.
Additionally, ensure the following requirements are met:
Using a machine with internet access, you have downloaded the latest
docker-stub-US.zipordocker-stub-EU.zipfile from the Bitwarden Server repository'sreleases pageand transferred this file to your server.An offline SMTP Server is setup and active in your environment.
The server your Bitwarden deployment runs on will not be required to allow outbound traffic to any addresses outside of your network, however client applications must be configured to access the server's fully qualified domain name (FQDN) on, by default, ports 80 and 443. You may opt to choose different ports during installation, but whichever ports you choose these must be opened for client access.
Installation procedure
Configure your domain
By default, Bitwarden will be served through ports 80 (http) and 443 (https) on the host machine. Open these ports so that Bitwarden can be accessed from within and/or outside of the network. You may opt to choose different ports during installation.
We recommend configuring a domain name with DNS records that point to your host machine (for example, server.example.com), especially if you are serving Bitwarden over the internet. We recommend not including Bitwarden in your hostname to keep the server identity or type concealed.
Create Bitwarden local user and directory
Configure your Linux server with a dedicated bitwarden service account, from which to install and run Bitwarden. Doing so will isolate your Bitwarden instance from other applications running on your server. For more information, see Docker's
Create a bitwarden user:
Bashsudo adduser bitwardenSet a password for the bitwarden user:
Bashsudo passwd bitwardenCreate a docker group (if it doesn't already exist):
Bashsudo groupadd dockerAdd the bitwarden user to the docker group:
Bashsudo usermod -aG docker bitwardenCreate a bitwarden directory:
Bashsudo mkdir /opt/bitwardenSet permissions for the
/opt/bitwardendirectory:Bashsudo chmod -R 700 /opt/bitwardenSet the bitwarden user ownership of the
/opt/bitwardendirectory:Bashsudo chown -R bitwarden:bitwarden /opt/bitwarden
Configure your machine
warning
Once you have bitwarden user from the /opt/bitwarden directory. Do not install Bitwarden as root, as you will encounter issues during installation.
To configure your machine with the assets required for your Bitwarden server:
Create a new directory named
bwdataand extractdocker-stub-US.zip(ordocker-stub-EU.zip) to it, for example:Bashunzip docker-stub-US.zip -d bwdataOnce unzipped, the
bwdatadirectory will match what thedocker-compose.ymlfile's volume mapping expects. You may, if you wish, change the location of these mappings on the host machine.In
./bwdata/env/global.override.env, edit the following environment variables:globalSettings__baseServiceUri__vault=: Enter the domain of your Bitwarden instance.globalSettings__sqlServer__ConnectionString=: Replace theRANDOM_DATABASE_PASSWORDwith a secure password for use in a later step.globalSettings__identityServer__certificatePassword: Set a secure certificate password for use in a later step.globalSettings__internalIdentityKey=: ReplaceRANDOM_IDENTITY_KEYwith a random alphanumeric string.globalSettings__oidcIdentityClientKey=: ReplaceRANDOM_IDENTITY_KEYwith a random alphanumeric string.globalSettings__duo__aKey=: ReplaceRANDOM_DUO_AKEYwith a random alphanumeric string.globalSettings__installation__id=: Enter an installation id retrieved fromhttps://bitwarden.com/host.globalSettings__installation__key=: Enter an installation key retrieved fromhttps://bitwarden.com/host.globalSettings__pushRelayBaseUri=: This variable should be blank. SeeConfigure Push Relayfor more information.tip
At this time, consider also setting values for all
globalSettings__mail__smtp__variables and foradminSettings__admins. Doing so will configure the SMTP mail server used to send invitations to new organization members and provision access to theSystem Administrator Portal.
From
./bwdata, generate a.pfxcertificate file for the identity container and move it to the mapped volume directory (by default,./bwdata/identity/). For example, run the following commands:Bashopenssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout identity.key -out identity.crt -subj "/CN=Bitwarden IdentityServer" -days 10950and
Bashopenssl pkcs12 -export -out ./identity/identity.pfx -inkey identity.key -in identity.crt -passout pass:IDENTITY_CERT_PASSWORDIn the above command, replace
IDENTITY_CERT_PASSWORDwith the certificate password created and used in Step 2.Create a subdirectory in
./bwdata/sslnamed for your domain, for example:Bashmkdir ./ssl/bitwarden.example.comProvide a trusted SSL certificate and private key in the newly created
./bwdata/ssl/bitwarden.example.comsubdirectory.note
This directory is mapped to the NGINX container at
/etc/ssl. If you can't provide a trusted SSL certificate, front the installation with a proxy that provides an HTTPS endpoint to Bitwarden client applications.In
./bwdata/nginx/default.conf:Replace all instances of
bitwarden.example.comwith your domain, including in theContent-Security-Policyheader.Set the
ssl_certificateandssl_certificate_keyvariables to the paths of the certificate and private key provided in Step 6.Take one of the following actions, depending on your certificate setup:
If using a trusted SSL certificate, set the
ssl_trusted_certificatevariable to the path to your certificate.If using a self-signed certificate, comment out the
ssl_trusted_certificatevariable.
In
./bwdata/env/mssql.override.env, replaceRANDOM_DATABASE_PASSWORDwith the password created in Step 2.In
./bwdata/web/app-id.json, replacebitwarden.example.comwith your domain.In
./bwdata/env/uid.env, set the UID and GID of thebitwardenusers and group youcreated earlierso the containers run under them, for example:BashLOCAL_UID=1001 LOCAL_GID=1001
Download and transfer images
To get docker images for use on your offline machine:
From an internet-connected machine, download all
ghcr.io/bitwarden/image_name:latestdocker images, as listed in thedocker-compose.ymlfile indocker-stub.zip. For example:Plain Textdocker image pull ghcr.io/bitwarden/mssql:latestSave each image to a
.imgfile, for example:Bashdocker image save -o mssql.img ghcr.io/bitwarden/mssql:latestTransfer all
.imgfiles to your offline machine.On your offline machine, load each
.imgfile to create your local docker images, for example:Bashdocker image load -i mssql.img
Start your server
Start your Bitwarden server with the following command:
Bashdocker compose -f ./docker/docker-compose.yml up -d
Verify that all containers are running correctly:
Bashdocker ps
Congratulations! Bitwarden is now up and running at https://your.domain.com. Visit the web vault in your browser to confirm that it's working.
You may now register a new account and log in. Your will need to have configured SMTP environment variables (see
Next Steps:
If you are planning to self-host a Bitwarden organization, see
self-host an organizationto get started.For additional information see
self hosting FAQs.
Update your server
Updating a self-hosted server that has been installed and deployed manually is different from the
Download the latest
docker-stub.ziparchive from thereleases pages on GitHub.Unzip the new
docker-stub.ziparchive and compare its contents with what's currently in yourbwdatadirectory, copying anything new to the pre-existing files inbwdata.
Do not overwrite your pre-existingbwdatadirectory with the contents of the newerdocker-stub.ziparchive, as this would overwrite any custom configuration work you've done.Download the latest container images and transfer them to your offline machine
as documented above.Run the following command to restart your server with your updated configuration and the latest containers:
Bashdocker compose -f ./docker/docker-compose.yml down && docker compose -f ./docker/docker-compose.yml up -d