Use Docker and Traefik to Deploy BitWarden on VPS
I can’t remember what was the reason I started using password management software but it has become such an important tool over the years that I can’t live without. After trying so many different tools, initially I settled down with KeePass which is open source. However, the lacking of software and plugins support made we switch to SafeInCloud. I had been using it for quite a while until I found BitWarden from reading a post on Reddit. After the initial testing, I immediately made my jump, especially its self-hosting solutions ignited my passion in learning docker. However, Bitwarden’s official docker image consumes a lot of resources which my tiny VPS can’t afford. Luckily someone made Bitwarden_rs which is perfect for personal use. After several years of using BitWarden on my own VPS, I think it is time to write an article to not just for my own study but also in hopes of helping others to start using this great tool.
Let’s get started, shall we?
Installation of Docker
By default I will assume you’ve installed docker and docker compose already. If you don’t know how to, please refer back to the official documents below:
Configuration of Traefik 2
In the following I will be presenting 3 files for Traefik 2 configurations, docker compose file, static and dynamic configuration files. In my example, I would be separating the Traefik and BitWarden into two docker-compose file in their own folder. We would have better control of when we want the container to be created. I also gave up using external GitHub gist for my code as it is not well supported by some Hexo themes.
Docker Compose - docker-compose.yml
I will explain my configurations in detail in case I can reference back in my future blog posts. Please note as I am learning all this by my self in my free time, please excuses my mistakes…
Attributes | Name | Information |
---|---|---|
Image | traefik:latest | I am using the latest traefik image here |
container_name | traefik | I am naming this container as traefik |
security_opt | no-new-privileges:true | To prevent containers getting unnecessary privileges |
ports | 80:80 | Open http Port 80 |
443:443 | Open https Port 443 | |
volumes | /etc/localtime:/etc/localtime:ro | Resolve the potentially mismatch of the host time and container time |
/etc/timezone:/etc/timezone:ro | Resolve the potentially mismatch of the host time and container time | |
/var/run/docker.sock:/var/run/docker.sock:ro | Monitor Docker daemon | |
./data/traefik.yml:/traefik.yml:ro | Attachstatic configuration file traefik.yml to the container |
|
./data/acme.json:/acme.json | Attachacme.json file to the container for storing SSL certificates |
|
./data/configurations:/configurations | Attachconfiguration folder, our dynamic configuration file stores in this folder |
|
networks | proxy | Add Traefik to an external Docker bridge Network name proxy |
labels | traefik.enable=true | Allowed Traefik to access this container |
traefik.http.routers.traefik.entrypoints=http | Define http entry point. In my static configuration I defined http access port 80 |
|
traefik.http.routers.traefik.rule=Host(traefik.yourdomain ) |
Define host name on http access | |
traefik.http.routers.traefik.middlewares=https-redirect@file | Used https-redirect middleware which provide redirect the http traffic to https. We will define our middlewares in dynamic configuration |
|
traefik.http.routers.traefik-secure.entrypoints=https | Define https entry point. In my static configuration I defined https access port 443 |
|
traefik.http.routers.traefik-secure.rule=Host(traefik.yourdomain ) |
Define host name on https access | |
traefik.http.routers.traefik-secure.middlewares=user-auth@file | Used user-auth middleware which provide basic auth to protect Traefik Dashboard. We will define our middlewares in dynamic configuration |
|
traefik.http.routers.traefik-secure.tls=true | We will be using TLS (SSL) | |
traefik.http.routers.traefik-secure.tls.certresolver=letsencrypt | Define which provider you want to use to serve the certificate. We will define our certificate provider in static configuration |
|
traefik.http.routers.traefik-secure.service=api@internal | We connect our https access to Traefik Dashboard | |
networks: | Proxy: external: true | Define network proxy |
1 | version: '3.3' |
It looks very complicated but all you need to do is to copy my code, change the host name and it should be good to go. ✌
Static Configuration - traefik.yml
This configuration is pretty straight forward. We declare that we will be using docker and file provider. As we are using docker so I don’t need to explain why we need to use docker provider, file provider will attach our Dynamic configuration to Traefik.
I’ve also defined two certificate providers here. One is Let’s Encrypt, the other one is BuyPass from Norway. Both providers provide free SSLs. The former one provide 3 months validity DV SSL and you can combine whatever you want on the certificate (single domain, wildcard, multiple domain, multiple wildcard). BuyPass only provides single domain DV SSL valid for 6 months. Although it is more than enough for personal use, BuyPass does have rate limits. for more information, please go to their official website。
1 | api: |
Dynamic Configuration - dynamic.yml
We defines our middlewares and SSL options in Dynamic configuration. These middleware are quite easy to under.
Attributes | Name | Information |
---|---|---|
middleware | https-redirect | Used to redirect http to https |
secureHeaders | We used this to boost our SSLLabs rating from A to A+… |
|
bw-stripPrefix | This is required by BitWarden WebSocket if you use it | |
user-auth | Basic auth for Traefik Dashboard | |
tls | cipherSuites | Defines what cipher suites we want to use, turn off some weak ciphers |
minVersion | Defines the minimum TLS version to 1.2 |
1 | # Dynamic configuration |
Docker Compose of BitWarden - docker-compose.yml
This docker-compose file is similar to Traefik’s. I only include extra lines for WebSocket.
Frankly speaking I am not using WebSocket for my own BitWarden setup. However most tutorials include WebSocket in their conguration, so as the official examples. You don’t have to use it.
1 | version: '3' |
At Last
After we save all these files, we need to run
docker network create proxy
to create the bridge network.docker-compose up -d
in each folders to create containers
Please note these two docker compose files need to be stored in different folders. For instance, store Traefik’s file at~/docker-compose.yml
,stores BitWarden’s to let’s say~/bitwarden/docker-compose.yml
.
Do I have a single file to deploy both containers? Yes, I have😁
Create Traefik and BitWarden at the same time
1 | version: '3' |
I hope this tutorial will help people start using password management software or even host their own instances on their server.
Thanks for your time.