Motivation
Since the 2015 LastPass breach and the other security incidents had happened, I always wanted to have a secure storage solution that would not require my passwords be stored on third party servers.
I have a strong fascination with CLI tools and when I stumbled upon pass(https://www.passwordstore.org/), I quickly transferred all my accounts over to that.
Just one teeny problem. There's no web UI (obviously, duh). The mobile app would have satisfied me....if only it worked for me, which it never did.
My stubbornness to stick to my guns led me to use it for quite a while. One awesome thing about that setup is that the passwords are stored in a Git repository. In practice, this means that all changes to my passwords are version-controlled. Admittedly, this is not all that useful, but VCS is cool and anything that has versioning has my love. But I digress.
As a Developer, my hands were itching to build a website based on pass to attend to my needs. I firmly stopped that desire as I was not a security expert and building/maintaining this would be a time drain in the future.
In a moment of serendipity, I found https://bitwarden.com, a self-hosted password manager. With Docker, no less. This is my perfect solution.
My Needs
- Simple setup on my server. (Should have an up-to-date docker image)
- Have a storage mechanism that is easily backed up
- Should have a decent web UI
- Should have extensions on Firefox
- Should have an Android app
BitWarden handily satisfied all these constraints. In the rest of this post, I will describe in detail, how to get a server, put docker on it, put bitwarden on it, and finally, get your own self-hosted password manager server up and running.
Will make another post in the future that tackles point 2-5.
Process
Buy a server
- DigitalOcean is the one that I used
- Choose the smallest sized droplet($5 one) with the following settings
- Ubuntu 20.04 LTS (Choose the latest LTS version)
- Shared CPU -> Basic,$5/Month
- Data center, choose the one nearest to your location.
- Ignore VPC Network, Select additional options
- In Authentication, Its preferable to use SSH, if you don't know how to do that, the Password option is also cool. Never lose the SSH private key if you do choose SSH.
- Scroll to the end and enable Backups. This will save your ass someday.
Get a domain name
You can use any registrar to do this, I used google domains (https://domains.google/)as it has a super convenient UI. I will be making a post in the near future that tells how to setup a multi-subdomain SSL certificate(if your server has multiple services like a website) but for now a simple A record is enough. It Looks like this(Choose DNS on the sidebar to get to the page and scroll down to get to this section)
It would take anywhere between 15 mins to a day for this mapping to propagate to all DNS servers. Proceed to the next step after ensuring that your server is up and you can ssh into it. Command for Linux would be.
ssh root@serverdomain.com
For Windows, you can use an app like Putty to connect to the server and check.
Create SSL certificates
This is a necessary step considering that we are building a password manager. Not using HTTP would send the passwords across the internet in plain text. A very BAD idea.
- You can use letsencrypt to create Free SSL certificate.
- Follow the instructions on https://certbot.eff.org/lets-encrypt/ubuntufocal-other to get the SSL cert and key files.
- The key files will be present in
/etc/letsencrypt/live/website.com
(Replacewebsite.com
with the domain name that you purchased). - You can go through the README for a explanation of the key files. Here is a webpage that goes into further detail.
- In essence you need
privkey.pem
andfullchain.pem
for your server to function correctly.
Install Docker & Docker Compose on the Machine
Install Docker
You can look here for the official install docker docs for Ubuntu, or follow along in this short, sweet version.
Update Ubuntu software repositories.
sudo apt-get update
Install some prerequisites for Docker.
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
Add Docker’s official GPG key(This is used so that the Ubuntu installer can verify the author of the docker executable).
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Add the docker binary repository to your install able sources.
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
Run apt update to get the package information of the newly added repository.
sudo apt-get update
Finally, install the docker packages.
sudo apt-get install docker-ce docker-ce-cli containerd.io
Install Docker Compose
Download the docker-compose script and save it to /usr/local/bin/docker-compose
.
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Change the permissions of the script so that it can be executed.
sudo chmod +x /usr/local/bin/docker-compose
Create Project Configuration Dir
For ease of maintenance, we are gonna set up a Git repo to backup and version the code.
- You should be in an SSH session from the previous step.
- Go to home directory
cd ~
You can either clone the config from my Github Repo(edwinclement08/bitwarden-nginx-docker) with the following command or follow the steps outlined below.
git clone https://github.com/edwinclement08/bitwarden-nginx-docker
Create a empty Git repository
git init bitwarden-server
Create and open a file named docker-compose.yml
version: "3"
services:
nginx:
image: nginx:1.19.2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx:/etc/nginx/conf.d
- ./logs/nginx:/var/log/nginx
- ./certs:/etc/certs:ro
bitwarden:
image: bitwardenrs/server:1.16.3-alpine
restart: unless-stopped
volumes:
- ./passdata:/data/
In this config, we are volume-mounting 3 folders into the Nginx container and a single folder which holds the password store to the bitwarden container. So lets go ahead and create those 3 folders.
mkdir -p nginx logs/nginx certs passdata
Now we need to copy over those certificates into the certs dir. You will need to use sudo
to copy over the certs and then change the owner if you are not running this as the root
user.
cp /etc/letsencrypt/live/website.com/{privkey.pem,fullchain.pem} ./certs
The last step is adding the nginx configuration to enable make the service visible outside the server, to the internet.
Create a file bitwarden.conf
in the directory nginx
with the following contents.
P.S. Change all the occurrences of website.com
with your purchased domain name.
server {
listen 80;
listen [::]:80;
server_name website.com;
return 301 https://website.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/certs/fullchain.pem;
ssl_certificate_key /etc/certs/privkey.pem;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name website.com;
location / {
proxy_pass http://bitwarden;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
The directory structure should be like
├── certs │ ├── fullchain.pem │ └── privkey.pem ├── docker-compose.yml ├── logs │ └── nginx ├── nginx │ └── bitwarden.conf └── passdata
Committing everything to git
Create a file .gitignore
in the app root-level folder with the below contents.
certs/*
passdata/*
logs/*
Run the following command in the project root to stage all the files
git add . -A
then run the following to commit
git commit -m 'initial commit'
P.S. note that if this is your first time using Git, you will be prompted to set your username and email, follow the instructions and repeat the above steps.
You may follow up this with connecting to Github by following instructions they give on a new repo creation.
How to start/stop the server(s)
Go to the root level folder of project
The following command will start the server and run in the background(-d or daemon is a flag that runs the services in the background)
docker-compose up -d
The following command will stop the server.
docker-compose down
The Bitwarden server will be available on website.com, well, whatever you bought.
Closing thoughts
That's all for this post, Padawan. Be open to learning and sharing the knowledge that you receive. Go forth, and learn the spread the Open Source Gospel.
Thanks Joshua Noronha and Bhanu Nadar for creative input. Do checkout their blogs as well. 🙂
Would you like a Docker Compose series? If so please comment below.