This is how I installed the Rust implementation of bitwarden into a Proxmox Debian 10 LXC Container. It should work on any Debian 10 install (virtual or metal). I dislike running docker inside LXC containers for obvious reasons, so this is how I did it.
- https://www.reddit.com/r/Bitwarden/comments/dg78bi/building_selfhosted_bitwarden_via_bitwarden_rs/
- https://github.com/dani-garcia/bitwarden_rs/wiki/Building-binary
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install git nano curl wget htop pkg-config openssl libssl1.1 libssl-dev
$ sudo apt install build-essentials # not necessary??
Do not use your distribution's Rust and Node packages.
Install Rust and Node from their own sites.
You can install either/both globally to the entire system, or just localized within a user's home directory. In the example below I install Rust/Cargo to a user directory and Node globally, in /opt/node
$ curl https://sh.rustup.rs -sSf | sh
$ echo 'export PATH=~/.cargo/bin:$PATH' >> ~/.bashrc
$ export PATH=~/.cargo/bin:$PATH
$ which rustc
/home/bitwarden/.cargo/bin/cargo
$ wget https://nodejs.org/dist/latest-v9.x/node-v9.11.2-linux-x64.tar.xz
$ tar -xvf node-v9.11.2-linux-x64.tar.xz
$ sudo mv node-v9.11.2-linux-x64 /opt/
$ sudo ln -sf /opt/node-v9.11.2-linux-x64 /opt/node
$ echo 'export PATH=/opt/node/bin:$PATH' >> ~/.bashrc
$ export PATH=/opt/node/bin:$PATH
$ which npm
/opt/node/bin/npm
$ npm i npm@latest -g
Now you're all set to do the bitwarden_rs installation. Start by cloning the bitwarden_rs repository and using cargo to build. This assumes you are doing a small-scale installation using sqlite as your backend database. This keeps things simple as you won't need to set up MySQL/MariaDB
$ git clone https://github.com/dani-garcia/bitwarden_rs && pushd bitwarden_rs
$ cargo clean && cargo build --features sqlite --release
$ file target/release/bitwarden_rs
target/release/bitwarden_rs: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked ...
Almost done now, just build the web-vault
component, available from the BitWarden project
NOTE You can now avoid patching and simply use one of these prepatched branches
If you don’t want to use a prepatched build, follow these steps..
$ pushd target/release/
$ git clone https://github.com/bitwarden/web.git web-vault.git && cd web-vault.git
Now you need to apply a patch from bitwarden_rs. You can see the available patches here. Pick one that is recent, for example, v2.15.1.patch
. Then use the following to set the current branch of web-vault.git to match that of the patch you chose. Then apply the patch and build
MAKE SURE YOU HAVE AT LEAST 2GB RAM TO BUILD
This is only needed to BUILD, NOT to RUN
$ git checkout v2.15.1
$ wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.15.1.patch
$ git apply v2.15.1.patch
$ npm run sub:init && npm install && npm run dist
Pretty much done now, just copy the build/
directory into the bitwarden_rs release/
directory as web-vault
$ cp -a build ../web-vault
Now we can test-run or compilation
$ cd ..
$ mkdir data
$ ./bitwarden_rs
/--------------------------------------------------------------------\
| Starting Bitwarden_RS |
| Version 1.16.3-7167e443 |
|--------------------------------------------------------------------|
| This is an *unofficial* Bitwarden implementation, DO NOT use the |
| official channels to report bugs/features, regardless of client. |
| Send usage/configuration questions or feature requests to: |
| https://bitwardenrs.discourse.group/ |
| Report suspected bugs/issues in the software itself at: |
| https://github.com/dani-garcia/bitwarden_rs/issues/new |
\--------------------------------------------------------------------/
[2020-08-27 09:22:05.121][bitwarden_rs][INFO] JWT keys don't exist, checking if OpenSSL is available...
OpenSSL 1.1.1d 10 Sep 2019
[2020-08-27 09:22:05.124][bitwarden_rs][INFO] OpenSSL detected, creating keys...
Generating RSA private key, 2048 bit long modulus (2 primes)
.......................................+++++
..+++++
e is 65537 (0x010001)
writing RSA key
writing RSA key
[2020-08-27 09:22:05.178][bitwarden_rs][INFO] Keys created correctly.
Running migration 20180114171611
Running migration 20180217205753
Running migration 20180427155151
Running migration 20180508161616
Running migration 20180525232323
Running migration 20180601112529
Running migration 20180711181453
Running migration 20180827172114
Running migration 20180910111213
Running migration 20180919144557
Running migration 20181127152651
Running migration 20190526216651
Running migration 20191010083032
Running migration 20191117011009
Running migration 20200313205045
Running migration 20200409235005
Running migration 20200701214531
Running migration 20200802025025
[2020-08-27 09:22:05.226][start][INFO] Rocket has launched from http://0.0.0.0:8000
Go ahead and browse to localhost on port 8000 and create a new user to confirm it is working. If you didn't encounter any errors throughout this process it should "just work"
Take a look at the .env
or .env.template
file for how you might do some basic or advanced settings changes, such as the ports the service will use, etc. This is a file that is essentially sourced by the shell before executing the bitwarden_rs
process. When it runs, bitwarden_rs
consults the environment variables for certain things
Use Ctrl - C
to close the bitwarden server
If you use the same names as defined below, there is no need to change the service file. It should just work without any modifications.
$ sudo cp ../../.env.template /etc/bitwarden_rs.env
$ sudo cp bitwarden_rs /usr/bin/bitwarden_rs
$ sudo chmod +x /usr/bin/bitwarden_rs
$ sudo useradd -m -d /var/lib/bitwarden_rs bitwarden_rs
$ sudo cp -R data /var/lib/bitwarden_rs/ # MOVE DATA OR
# $ sudo mkdir /var/lib/bitwarden_rs/data # CREATE NEW
$ sudo cp -R web-vault /var/lib/bitwarden_rs/
$ sudo chown -R bitwarden_rs:bitwarden_rs /var/lib/bitwarden_rs
Create Service File
$ sudo nano /etc/systemd/system/bitwarden_rs.service
With the content
[Unit]
Description=Bitwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/bitwarden_rs
# If you use a database like mariadb,mysql or postgresql,
# you have to add them like the following and uncomment them
# by removing the `# ` before it. This makes sure that your
# database server is started before bitwarden_rs ("After") and has
# started successfully before starting bitwarden_rs ("Requires").
# Only sqlite
After=network.target
# MariaDB
# After=network.target mariadb.service
# Requires=mariadb.service
# Mysql
# After=network.target mysqld.service
# Requires=mysqld.service
# PostgreSQL
# After=network.target postgresql.service
# Requires=postgresql.service
[Service]
# The user/group bitwarden_rs is run under. the working directory (see below) should allow write and read access to this user/group
User=bitwarden_rs
Group=bitwarden_rs
# The location of the .env file for configuration
EnvironmentFile=/etc/bitwarden_rs.env
# The location of the compiled binary
ExecStart=/usr/bin/bitwarden_rs
# Set reasonable connection and process limits
LimitNOFILE=1048576
LimitNPROC=64
# Isolate bitwarden_rs from the rest of the system
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)
WorkingDirectory=/var/lib/bitwarden_rs
ReadWriteDirectories=/var/lib/bitwarden_rs
# Allow bitwarden_rs to bind ports in the range of 0-1024
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
Reload systemd
$ sudo systemctl daemon-reload
Start
$ sudo systemctl start bitwarden_rs.service
Enable autostart on boot
$ sudo systemctl enable bitwarden_rs.service
Other options are: stop
, restart
and disable
the service.
After compiling the new version of bitwarden_rs, you can copy the compiled (new) binary and replace the existing (old) binary and then restart the service:
$ sudo systemctl restart bitwarden_rs.service
Before doing anything else, you should stop and disable the service:
$ sudo systemctl disable --now bitwarden_rs.service
Then you can delete the binary, the .env
file, the web-vault folder (if installed) and the user data (if necessary). Remember to also remove specially created users,groups and firewall rules (if needed) and the systemd file.
After removing the systemd file you should make systemd aware of it via:
$ sudo systemctl daemon-reload
If you want to see the logging output, run
$ journalctl -u bitwarden_rs.service
or to see a more concise state of the service, run
$ systemctl status bitwarden_rs.service
In RHEL 7 (and debian 8), the used systemd does not support some of the used isolation options. (#445,#363) This can result in one of the following errors:
Failed at step NAMESPACE spawning /home/bitwarden_rs/bitwarden_rs: Permission denied
or
Failed to parse protect system value
To work around this you can comment out some or all of these settings by putting a # in front of the lines containing PrivateTmp, PrivateDevices, ProtectHome, ProtectSystem and ReadWriteDirectories. While commenting out all of them will probably work, it's not recommended as these are security measures which are good to have. To see which options your systemd supports, look at the output of
$ systemctl --version
to determine your systemd version and compare with systemd/NEWS.md.
After editing your .service file, don't forget to
$ sudo systemctl daemon-reload
before (re-)starting your service.
In this example I use acme.sh with Dynu as a DNS provider to generate the certificates. I like to use the DNS method because it requires zero network configuration. Acme.sh
just needs outbound access to the internet and nothing else.
You should adjust the instructions to your provider/method of choice.
Check out acme.sh's Wiki for more info (browse the 40+ pages there).
My proxy usually runs in a separate VM/CT, if you are running nginx locally, you can change the destination IP to 127.0.0.1
(localhost).
To install, you can use git or curl/wget. I prefer installing as root.
$ sudo su -
# git clone https://github.com/acmesh-official/acme.sh.git
# cd acme.sh
Possible install parameters
./acme.sh --install \
--home ~/myacme \
--config-home ~/myacme/data \
--certhome ~/mycerts \
--accountemail "[email protected]" \
--accountkey ~/myaccount.key \
--accountconf ~/myaccount.conf \
--useragent "this is my client."
I usually just add the email
./acme.sh --install --accountemail "[email protected]"
You now have two folders at /root
/root/acme.sh
- git clone with the installer (can be deleted after install, but I usually leave it there)./root/.acme.sh
- installed program and data (certs, methods, etc)
To use Dynu, you need to add an access token to the installed config file.
# cd ../.acme.sh
# nano account.conf
Add your DNS provider ID/Secret or other authentication method below your e-mail.
Web mode does not need this (but needs external access to internal port 80).
ACCOUNT_EMAIL='[email protected]'
Dynu_ClientId='245gb9ff-d5gh-7227-b656-4c63e2356df2'
Dynu_Secret='SADwerbnsdi23412ASDa294'
Now we can generate and install any certs we need.
JUST NEED THE DOMAIN/SUBDOMAIN/ALIAS CREATED IN DYNU FIRST
You can test-run on staging if you want (single or multiple domains)
# acme.sh --test --debug --debug --issue --dns dns_dynu -d bitwarden.mydomain.com
If you tested, you need to use --force
to run again for real
# acme.sh --debug --debug --issue --dns dns_dynu -d bitwarden.mydomain.com --force
I prefer to create a separate folder for my certs
# mkdir /etc/ssl/localcerts/
Now we can tell acme.sh
to install and to reload the webserver (or whatever is gonna use the certs).
# acme.sh --debug --installcert -d bitwarden.mydomain.com --certpath /etc/ssl/localcerts/bitwarden.mydomain.com.pem --keypath /etc/ssl/localcerts/bitwarden.mydomain.com.key --fullchainpath /etc/ssl/localcerts/bitwarden.mydomain.com-fullchain.cer --reloadcmd "systemctl reload nginx"
This completes the acme.sh
part.
The script will regenerate certs automagically from cron, based on how you first generated your certs.
Depending on your distro and how you installed nginx, the main configuration and each website configuration locations will vary. The example below shows a Debian-based install with the folders sites-enabled
and sites-available
inside /etc/nginx
.
I usually install nginx from nginx.org instead of using the distro package.
Install the prerequisites:
$ sudo apt install curl gnupg2 ca-certificates lsb-release
To set up the apt repository for stable nginx packages, run the following command:
$ echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
If you would like to use mainline nginx packages, run the following command instead:
$ echo "deb http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
Next, import an official nginx signing key so apt could verify the packages authenticity:
$ curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
Verify that you now have the proper key:
$ sudo apt-key fingerprint ABF5BD827BD9BF62
The output should contain the full fingerprint 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62 as follows:
pub rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
uid [ unknown] nginx signing key <[email protected]>
To install nginx, run the following commands:
$ sudo apt update
$ sudo apt install nginx
So, let's create a proxy that uses or generated certificates and redirects to our bitwarden instance.
$ sudo su -
# cd /etc/nginx/sites-available
# nano bitwarden.mydomain.com.config
The content I use
- Change all
bitwarden.mydomain.com
toyour bitwarden domain
- Change the IP in
proxy_pass
andproxy_redirect
to your bitwarden's IP
server {
listen 80;
listen [::]:80;
server_name bitwarden.mydomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name bitwarden.mydomain.com;
ssl_certificate /etc/ssl/localcerts/bitwarden.mydomain.com-fullchain.cer;
ssl_certificate_key /etc/ssl/localcerts/bitwarden.mydomain.com.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/bitwarden.mydomain.com.access.log;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Fix the "It appears that your reverse proxy set up is broken" error.
# THE IP/PORT OF YOU BITWARDEN INSTALL, OR USE 127.0.0.1 FOR LOCALHOST
proxy_pass http://10.0.10.50:8000;
proxy_read_timeout 200;
proxy_redirect http://10.0.10.50:8000 https://bitwarden.mydomain.com;
}
}
Create the symlink at sites-enabled
# cd ../sites-enabled
# ln -s ../sites-available/bitwarden.mydomain.com bitwarden.mydomain.com
Then you can restart or reload your nginx server
# systemctl restart nginx.service
# systemctl status nginx.service # Ctrl+C to close
Now you can test/troubleshoot the HTTPS connection to you bitwarden instance.
To enable the admin interface you need to set a valid token into your ENV file. You can find more info here
As they mention, you should probably enable this only after enabling SSL, to avoid MITM (man in the middle) attacks.
Generate a new token with openssl
$ openssl rand -base64 48
+sEY1rzwi+XNEcaXU1pI3Xiz4tiQ31SaD/9lQqgwPnOJhK5spz+VNhs72g3xkvbq
Save this! It will be the admin password
Copy the key created to paste into the config file
$ sudo nano /etc/bitwarden_rs.env
Uncomment or add
ADMIN_TOKEN=+sEY1rzwi+XNEcaXU1pI3Xiz4tiQ31SaD/9lQqgwPnOJhK5spz+VNhs72g3xkvbq
Restart bitwarden service
$ sudo systemctl restart bitwarden_rs.service
Open the admin page and login with the token https://bitwarden.mydomain.com/admin