Have a server lying around? Install a password manager there.

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

  1. Simple setup on my server. (Should have an up-to-date docker image)
  2. Have a storage mechanism that is easily backed up
  3. Should have a decent web UI
  4. Should have extensions on Firefox
  5. 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 (Replace website.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 and fullchain.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.

Related Posts

One thought on “Have a server lying around? Install a password manager there.

Leave a Reply

%d bloggers like this: