Host your own password manager smart and safe

Most technical people know that the best way to manage your passwords is to have a different password for every application, preferable a random string and the longer the better. But nobody can remember all those different passwords. You could of course save your passwords locally on your device. Nowadays everyone have at least 1 smart phone and beside that probably 1 computer at a minimum. To keep everything in sync is a difficult job. That’s where password managers come in. I’ve also used those services, but was concerned with the messages of data breaches. You are giving a commercial company the keys to everything in your life and you have to trust that company to keep it safe.

My preferred solution would be to host the password manager myself and the software in question is in my case Vaultwarden. This comes of course with a number of caveats:

  1. How to arrange access. You preferably don’t want to give everybody access, but you also want to keep access for the people that use it as easy as possible.
  2. How do you backup your data
  3. How do you easily access your backup in case you lose your production environment.

Access

This is very much dictated by your preference. What works for one person is not workable for another one and what is secure enough for one person is not secure enough for the other. I prefer to have the services reachable by anyone on the Internet, due to several private reasons. If you want to make it even more secure you could require a vpn connection to reach the vaultwarden application. I would suggest you fix the following as an SSL certificate on a password manager is required.

  • Certificates. This is a very important one especially with a password manager. You do want your (web) application to have valid SSL certificates. I personally find it easy to use a reverse proxy for this. It will handle the entire request and renewal process.
  • FQDN. In order to request certificates with LetsEncrypt, you definately need your own domain name, but you also either need to make your application reachable to the Internet (LetsEncrypt) or you need to use the LetsEncrypt DNS challenge. I prefer the latter one as you don’t have to expose your application too much to the Internet, but still can get a valid certificate. Here reverse proxies also help me out as they can do the certification process including automatic renewals, without me having to actively intervene.

Backup

I’ve been thinking on ways to backup my vaultwarden data. I’ve been a fan of rsnapshot for years. Recently I encountered Syncthing and I’m really charmed by the combination of the two. So what I setup is that with Syncthing I create a live copy off-site. Next I use rsnapshot to backup this off-site copy and create an archive off-site. This way I always have the opportunity to revert back to an older version of my password vault.

Recovery

The ease of recovery was very important for me especially when it pertains my passwords. I’m running vaultwarden in a docker environment. So it’s easy to spin up a similar docker container off-site. I did not want the off-site application to directly influence the live copy, so that’s why i weekly make a filesystem copy of the in-sync data. Then I automaticly restart the container and beside that the backup docker container will have no reference to old data. This results in a live restored copy that I can access at any time, but any changes made to that version will be gone after a new copy is made.

Implementation

First of all in my docker environment I use ipvlan layer2 in order for my containers to have their own IP address in the same network my docker host is in. This results in the following docker-compose file, that I normally paste as a stack config in my portainer environment. User specific information is enclosed within <>.

version: '3'

services:
  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    restart: unless-stopped
    environment:
      - ADMIN_TOKEN=<ADMIN LOGIN STRING>
    volumes:
      - <PATH TO NON VOLATILE DATA>:/data/
    networks:
      <NAME IPVLAN NETWORK:
        ipv4_address: '<IP>'
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "traefik.enable=true"
      - "traefik.http.routers.vaultwarden.rule=Host(`<FQDN>`)"
      - "traefik.http.routers.vaultwarden.entrypoints=https"
      - "traefik.http.routers.vaultwarden.tls.certresolver=<DNS-CHALLENGE-SCRIPT>"
      - "traefik.http.services.vaultwarden.loadbalancer.server.port=80"

networks:
  <NAME IPVLAN NETWORK>:
    external: true 

A portion of this configuration is part of my already setup framework. I’ve already setup traefik with a script to pass the DNS-challenge to my DNS server. You will need a specific script depending on where you manage the DNS of your domain. I also use watchtower to automaticly update the container. This results in nearly no periodical maintenance that I need to do to keep everything running.

Since I use virtualmin as dns server and as proxy for my backup solution and I don’t use ipvlan l2 here, the config of the backup solution is slightly different

version: '3'

services:
  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    restart: unless-stopped
    environment:
      - ADMIN_TOKEN=<ADMIN LOGIN STRING>
    volumes:
      - <PATH TO NON VOLATILE DATA>:/data/
    ports:
      - 6666:80
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

You could use either configuration for your production or your backup solution.