Vaultwarden: gestionnaire de mots de passe auto-hébergé

Le bitwarden open-source

Vaultwarden: gestionnaire de mots de passe auto-hébergé
Photo by rc.xyz NFT gallery / Unsplash

Vaultwarden est une alternative open-source à Bitwarden, le célèbre gestionnaire de mots de passe.

Il permet de stocker vos mots de passe de manière sécurisée sur votre propre infrastructure, vous offrant ainsi un contrôle total sur vos données.

Petite cerise 🍒 sur le gâteau, Vaultwarden est open-source et totalement compatible avec la stack logiciel de Bitwarden.

Vous pouvez donc utiliser (vos collaborateurs / clients) le client Android, le plugin de navigateur ou l'application desktop pour accéder à vos mots de passe.

Ainsi par exemple, si vous avez vos mot de passe perso sur un compte Bitwarden et pro sur un serveur Vaultwarden, une seule application est suffisante pour accéder a tous vos identifiants...

Installation

Comme d'habitude je passerai pas un docker-compose pour déployer vaultwarden, et un .env pour la configuration :

Nous allons installer Vaultwarden, pour qui il faudra un base de données postgresql, et j'y ajouterai un backup.

APP_NAME=vaultwarden
APP_DNS=password.dns.com

APP_DB_PASSWORD=<openssl rand -hex 16>
APP_ADMIN_TOKEN=<openssl rand -hex 32>

SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_USERNAME=my@dns.com
SMTP_PASSWORD=monsupermotdepasse

SIGNUPS_ALLOWED=false
INVITATIONS_ALLOWED=true

Je vous invite évidement à lire la doc pour l'ensemble des options...

name: vaultwarden 
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: bitwarden
    hostname: bitwarden
    environment:
      DOMAIN: "https://${APP_DNS}"
      DATABASE_URL: "postgresql://bitwarden:${APP_DB_PASSWORD}@bitwarden-postgres:5432/bitwarden"
      DATA_FOLDER: "/data"
      SIGNUPS_ALLOWED: "${SIGNUPS_ALLOWED}"
      INVITATIONS_ALLOWED: "${INVITATIONS_ALLOWED}"
      SHOW_PASSWORD_HINT: "true"
      ICON_BLACKLIST_NON_GLOBAL_IPS: "true"
      WEBSOCKET_ENABLED: "true" # Important for dynamic updates
      LOG_FILE: "/var/log/bitwarden.log"
      EXTENDED_LOGGING: "true"
      ADMIN_TOKEN: "${APP_ADMIN_TOKEN}"
      SMTP_HOST: "${SMTP_HOST}"
      SMTP_PORT: "${SMTP_PORT}"
      SMTP_USERNAME: "${SMTP_USERNAME}"
      SMTP_PASSWORD: "${SMTP_PASSWORD}"
    volumes:
      - ./data/bitwarden:/data
      - ./log/bitwarden.log:/var/log/bitwarden.log
      - /etc/localtime:/etc/localtime:ro
    networks:
      - internal
      - web
    security_opt:
      - no-new-privileges=true
    healthcheck:
      test: ["CMD", "curl", "-fL", "http://127.0.0.1:80"]
      interval: 2s
      timeout: 5s
      retries: 3
      start_period: 10s
    depends_on:
      - bitwarden-postgres
    labels:
      - traefik.enable=true
      - traefik.http.routers.${APP_NAME}.entrypoints=websecure
      - traefik.http.routers.${APP_NAME}.rule=Host(`${APP_DNS}`)
      - traefik.http.routers.${APP_NAME}.tls.certresolver=letsencrypt
      - traefik.http.routers.${APP_NAME}.service=${APP_NAME}
      - traefik.http.services.${APP_NAME}.loadbalancer.server.port=80
      - traefik.http.routers.${APP_NAME}-ws.entrypoints=websecure
      - traefik.http.routers.${APP_NAME}-ws.rule=Host(`${APP_DNS}`) && Path(`/notifications/hub`)
      - traefik.http.middlewares.${APP_NAME}-ws-strip.stripprefix.prefixes=/notifications/hub
      - traefik.http.routers.${APP_NAME}-ws.middlewares=${APP_NAME}-ws-strip
      - traefik.http.routers.${APP_NAME}-ws.tls.certresolver=letsencrypt
      - traefik.http.routers.${APP_NAME}-ws.service=${APP_NAME}-ws
      - traefik.http.services.${APP_NAME}-ws.loadbalancer.server.port=3012
    restart: unless-stopped

  bitwarden-postgres:
    image: postgres:13-alpine
    container_name: bitwarden-postgres
    hostname: bitwarden-postgres
    environment:
      POSTGRES_USER: "bitwarden"
      POSTGRES_PASSWORD: "${APP_DB_PASSWORD}"
      POSTGRES_DB: "bitwarden"
    security_opt:
      - no-new-privileges:true
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
      - /etc/localtime:/etc/localtime:ro
    networks:
      - internal
    restart: unless-stopped

  bitwarden-postgres-backup:
    image: postgres:13-alpine
    container_name: bitwarden-postgres-backup
    hostname: bitwarden-postgres-backup
    environment:
      BACKUP_NUM_KEEP: 7
      BACKUP_FREQUENCY: "1d"
    volumes:
      - ./backups/databases:/dump
      - /etc/localtime:/etc/localtime:ro
    networks:
      - internal
    depends_on:
      - bitwarden-postgres
    entrypoint: |
      bash -c 'bash -s <<EOF
      trap "break;exit" SIGHUP SIGINT SIGTERM
      sleep 1s
      while /bin/true; do
        PGPASSWORD=${APP_DB_PASSWORD} pg_dump --host=bitwarden-postgres --username=bitwarden bitwarden | gzip -c > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.sql.gz
        (ls -t /dump/dump*.sql.gz|head -n $$BACKUP_NUM_KEEP;ls /dump/dump*.sql.gz)|sort|uniq -u|xargs rm -- {}
        sleep $$BACKUP_FREQUENCY
      done
      EOF'
    restart: unless-stopped

networks:
  internal:
  web:
    external: true

Il n'y a plus qu'a démarrer tout ça et vous rendre sur l'URL pour créer les premiers comptes.

J'utilise aussi vividboarder/vaultwarden_ldap qui permet, comme son nom l'indique de synchroniser les comptes (invitations) avec Vaultwarden.