Skip to content

Vaultarden

Installation des dépendances

sudo apt install pkg-config libssl-dev build-essential
sudo apt install npm

Installation de Rust

Installation de rustup, qui nous fournira le compilateur Rust :

curl https://sh.rustup.rs -sSf > rustup.sh
  • On n'exécute pas direct un script tiré du web ! On regarde d'abord s'il ne va pas faire de saloperies :
vi rustup.sh

On le rend exécutable :

chmod +x rustup.sh

On installe le compilateur Rust (il sera dans notre $HOME) :

./rustup.sh --default-host x86_64-unknown-linux-gnu --default-toolchain nightly

On source un fichier qui nous permet de l'appeler

source $HOME/.cargo/env

Mise à jour de Rust (si vous l'avez déjà installé via rustup)

rustup update

Compilation

git clone https://github.com/dani-garcia/vaultwarden
cd vaultwarden
git checkout -b "v$(git tag --sort=v:refname | tail -n1)" "$(git tag --sort=v:refname | tail -n1)"
cargo build --release --features postgresql # ou sqlite, ou mysql, selon la bdd que vous souhaitez utiliser
cd -

Le résultat de la compilation est dans vaultwarden/target/release/.

Récupération de l’interface web déjà patché !

wget https://github.com/dani-garcia/bw_web_builds/releases/download/v2.26.1/bw_web_v2.26.1.tar.gz
tar xvf bw_web_v2.26.1.tar.gz
  • Si vous faites une mise à jour, supprimez l’ancienne version de l’interface web :
rm -rf vaultwarden/target/release/web-vault/
  • Et on déplace l’interface web dans le dossier où attend le résultat de la compilation de vaultwarden :
mv web-vault/ vaultwarden/target/release/web-vault/

Pour une mise à jour

Allez dans votre dossier vaultwarden et faites un git fetch avant le git checkout ….

Ensuite suivez le tuto d’installation avec ces précautions préalables :

coupez le service vaultwarden
faites des sauvegardes de votre installation (fichiers, données de la base de données) avant de faire le rsync.

Installation

On va installer Vaultwarden dans /opt/vaultwarden et on le fera tourner avec l'utilisateur www-data :

cd ..
sudo rsync -a --info=progress2 vaultwarden/target/release/ /opt/vaultwarden/
sudo chown -R www-data: /opt/vaultwarden
  • Puis on va créer un service systemd, /etc/systemd/system/vaultwarden.service :
[Unit]
Description=Vaultwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/vaultwarden
After=network.target

[Service]
# The user/group vaultwarden is run under. the working directory (see below) should allow write and read access to this user/group
User=www-data
Group=www-data
# The location of the .env file for configuration
EnvironmentFile=/etc/vaultwarden.env
# The location of the compiled binary
ExecStart=/opt/vaultwarden/vaultwarden
# Set reasonable connection and process limits
LimitNOFILE=1048576
LimitNPROC=64
# Isolate vaultwarden from the rest of the system
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)
WorkingDirectory=/opt/vaultwarden/
ReadWriteDirectories=/opt/vaultwarden/

[Install]
WantedBy=multi-user.target

Dans un container LXC, vous commenterez LimitNPROC

Pour l'interface d'administration, on va créer un token avec :

openssl rand -base64 48

La configuration se fait via des variables d'environnement qu'on va mettre dans /etc/vaultwarden.env :

SIGNUPS_ALLOWED=false
WEBSOCKET_ENABLED=true
ADMIN_TOKEN=Un token généré avec `openssl rand -base64 48`
ROCKET_ADDRESS=127.0.0.1
WEBSOCKET_ADDRESS=127.0.0.1
SMTP_HOST=127.0.0.1
SMTP_FROM=bitwarden@example.org
SMTP_PORT=25
SMTP_SSL=false
  • pour ROCKET_ADDRESS et WEBSOCKET_ADDRESS, faire correspondre les IP sur l'IP du host

Puis :

sudo systemctl daemon-reload
sudo systemctl enable --now vaultwarden
sudo systemctl status vaultwarden

Vhost NGINX

  • Remplacer URL et IP
server {

    listen 443 ssl http2;
    server_name URL;

    # Let's Encrypt:

    ssl_certificate     /etc/letsencrypt/live/URL/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/URL/privkey.pem;
    ssl_trusted_certificate     /etc/letsencrypt/live/URL/chain.pem;

    # https://mozilla.github.io/server-side-tls/ssl-config-generator/

    # Disabling serveur signature-  Only display "nginx" instead of "nginx/1.14.2"
    server_tokens off;

    # drop SSLv3 (POODLE vulnerability)
    ssl_protocols         TLSv1.2;

    # enables server-side protection from BEAST attacks
    ssl_prefer_server_ciphers on;

    # Recommanded ciphers
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;


    # enable session resumption to improve https performance
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # force timeouts if one of backend is died ##
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

    # Set headers
    proxy_set_header        Accept-Encoding   "";
    proxy_set_header        Host            $host;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

    # Most PHP, Python, Rails, Java App can use this header
    proxy_set_header        X-Forwarded-Proto $scheme;
    add_header              Front-End-Https   on;

    # We expect the downsteam servers to redirect to the right hostname, so don't do any rewrites here.
    proxy_redirect     off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP Stapling - fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 30s;

    # Enable Proxy Intercept Errors
    # http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
    proxy_intercept_errors on;

    # LOGS

    gzip on;
    access_log /var/log/nginx/URL_access.log;
    error_log  /var/log/nginx/URL_error.log;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://IP:8000;
    }

    location /notifications/hub {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://IP:3012;
    }
    location /notifications/hub/negotiate {
        proxy_pass http://IP:8000;
    }

}

server {
    listen 80;
    server_name URL;
    return 301  https://URL$request_uri;
}

Sauvegarde

#!/bin/bash
function bwbackup {
    DATE=$(date '+%a%H')

    # Database
    if [[ ! -d /opt/backup_bitwarden/sqlite-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/sqlite-backup/
    fi
    echo ".backup /opt/backup_bitwarden/sqlite-backup/db.${DATE}.sqlite3" | sqlite3 /opt/bitwarden/data/db.sqlite3 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden database backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden database backup" youraddress@mail.example.org
        bwbackup
    fi

    # Files
    if [[ ! -d /opt/backup_bitwarden/files-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/files-backup/
    fi
    rsync -a --delete --exclude db.sqlite3 /opt/bitwarden/data/ /opt/backup_bitwarden/files-backup/$DATE/ 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden files backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden files backup" youraddress@mail.example.org
        bwbackup
    fi
}
bwbackup

puis

sudo chmod +x /opt/backup_bitwarden.sh
sudo mkdir /opt/backup_bitwarden
sudo chown www-data: /opt/backup_bitwarden
sudo apt install sqlite3

Puis, dans le cron de l’utilisateur www-data :

42 4 * * * /opt/backup_bitwarden.sh

logs

  • vi /etc/rsyslog.d/bitwarden.conf
if $programname == 'bitwarden_rs' then /var/log/bitwarden/bitwarden.log
if $programname == 'bitwarden_rs' then ~
  • vi /etc/logrotate.d/bitwarden
/var/log/bitwarden/bitwarden.log
{
        rotate 52
        dateext
        weekly
        missingok
        notifempty
        compress
        sharedscripts
        postrotate
                invoke-rc.d rsyslog rotate > /dev/null
        endscript
}

puis

sudo mkdir /var/log/bitwarden
sudo chown root:adm /var/log/bitwarden
sudo service rsyslog restart

FAIL2BAN

Un fail2ban qui surveille les logs, ça permet de bloquer les petits malins qui font du bruteforce

sudo apt install fail2ban
  • Dans /etc/fail2ban/filter.d/bitwarden.conf :
[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$
ignoreregex =
  • Dans /etc/fail2ban/jail.d/bitwarden.local :
[bitwarden]
enabled = true
port = 80,443
filter = bitwarden
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
  • Pour la page d’admin, dans /etc/fail2ban/filter.d/bitwarden-admin.conf :
[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Unauthorized Error: Invalid admin token\. IP: <HOST>.*$
ignoreregex =
  • Dans /etc/fail2ban/jail.d/bitwarden-admin.local :
[bitwarden-admin]
enabled = true
port = 80,443
filter = bitwarden-admin
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Finalement :

sudo service fail2ban restart