SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor

Vaultwarden su VPS: password manager self-hosted

Guida a Vaultwarden e Docker su VPS: HTTPS, token admin, Fail2ban e backup testati. Evita errori TLS e proteggi il volume con tutte le password.

Cosa stai creando

Un gestore di password che controlli completamente: Vaultwarden in un unico container di piccole dimensioni, dietro un reverse proxy che termina HTTPS, con le app ufficiali Bitwarden sul telefono, sul laptop e nel browser configurate per usarlo. Vaultwarden reimplementa in Rust l’API server di Bitwarden e usa lo stesso protocollo di bitwarden.com, quindi i client ufficiali funzionano senza modifiche, purché il server sia aggiornato. Le nuove release dei client a volte richiedono una release di Vaultwarden compatibile: per i client 2026.8.0 e successivi è richiesta la 1.37.2. Vaultwarden richiede però circa 100 MB di RAM, invece dei numerosi container dello stack ufficiale.

L’installazione richiede una dozzina di righe di Compose. Gli aspetti realmente importanti, e quelli che causano problemi, sono tre: TLS deve essere disponibile prima di aprire il web vault, le registrazioni pubbliche devono essere disabilitate non appena hai creato il tuo account e il volume dei dati deve essere sottoposto a backup e a un ripristino di prova, perché quella directory contiene tutte le password che possiedi.

Prerequisiti e aspetti critici da conoscere

  • Una VPS con Docker Engine e il plugin Compose, su un'installazione pulita di Ubuntu 24.04 su KVM, con accesso root o sudo. 512 MB di RAM sono effettivamente sufficienti; 1 GB offre un margine più confortevole. È uno dei servizi più leggeri che si possano eseguire e si trova ai primi posti della selezione dei servizi che vale la pena ospitare autonomamente. Tuttavia, dimensiona la VPS in base agli altri servizi che condivideranno la macchina: eseguire una libreria fotografica self-hosted come PhotoPrism o Immich sulla stessa VPS porta il requisito minimo di RAM nell'ordine dei gigabyte, mentre Vaultwarden incide appena. Lo stesso calcolo vale per le interfacce multimediali che aggiungerai in seguito, perché trasformare una libreria Jellyfin in un videonoleggio degli anni 90 visitabile richiede un altro container sempre attivo e memoria aggiuntiva per il transcoding, mantenendo lo stesso budget.
  • Un dominio con un record A (e un record AAAA se disponi di IPv6) che punti vault.example.com alla VPS. Il certificato TLS viene emesso per questo nome esatto, quindi il DNS deve risolverlo prima di iniziare.
  • Le porte 80 e 443 devono essere aperte verso Internet e la terminazione deve essere gestita dal reverse proxy, mai direttamente da Vaultwarden. La porta 80 viene usata esclusivamente per la challenge del certificato ACME e per il redirect da HTTP a HTTPS.
  • Il principale aspetto critico da considerare subito è il seguente: i client Bitwarden rifiutano di comunicare con un server che non usa HTTPS. Non esiste una fase di "prova iniziale su http": questo percorso non funziona, per un motivo preciso illustrato nella sezione successiva.

Perché Vaultwarden e non lo stack ufficiale di Bitwarden

Gli stessi client, con un ingombro molto inferiore. La distribuzione self-hosted ufficiale standard di Bitwarden viene fornita come un insieme di container, tra cui MSSQL Express, Identity, Api, Admin e altri, e richiede almeno 2 GB di RAM. Bitwarden offre anche Bitwarden lite, una singola immagine Docker che richiede almeno 200 MB di RAM, ma è destinata all’uso personale e ai laboratori domestici, non alle aziende, e lascia completamente a voi la gestione del database e dei relativi backup. Vaultwarden è un singolo binario che, per impostazione predefinita, archivia tutto in un database SQLite e, in inattività, usa poche decine di megabyte. Per una persona, una famiglia o un piccolo team è la scelta più pratica. Poiché implementa fedelmente l’API di Bitwarden, i dati restano trasferibili tra Vaultwarden e bitwarden.com.

Rinunciate a gran parte delle funzionalità enterprise: non è disponibile il provisioning SCIM, anche se il supporto per SSO tramite OpenID Connect è stato introdotto nella versione 1.35.0. Inoltre siete voi a gestire il servizio: applicazione delle patch, HTTPS e backup sono a vostro carico. Questa guida tratta proprio questi tre aspetti.

Perché HTTPS è obbligatorio

Il vault web di Bitwarden e le estensioni del browser derivano le chiavi di crittografia nel browser usando la Web Crypto API (window.crypto.subtle). I browser espongono crypto.subtle soltanto in un contesto sicuro, cioè tramite HTTPS, oppure nel caso speciale degli indirizzi di loopback come http://localhost e http://127.0.0.1. Su http://vault.example.com in chiaro è undefined, quindi, non appena l'applicazione deriva una chiave, genera un errore e nella console viene visualizzato:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')

La pagina resta bloccata o mostra un errore crittografico generico e nessun utente riesce ad accedere. I client desktop, mobili e del browser eseguono un controllo autonomo sull'URL self-hosted e, se l'endpoint usa http o non è raggiungibile, rifiutano la connessione con:

This is not a recognized Bitwarden server. You may need to check with your provider or update your server.

La causa è la stessa in entrambi i casi: manca un HTTPS valido. Per questo configuriamo prima TLS e non apriamo mai il vault tramite http, nemmeno una sola volta per un controllo rapido.

Passaggio 1: DNS e reverse proxy (prima TLS)

Punta il record al tuo VPS e verifica che venga risolto all'indirizzo corretto:

dig +short vault.example.com

La riga restituita deve contenere l'indirizzo IP del tuo VPS. Se è vuota o errata, correggi il DNS e attendi la scadenza del TTL: l'emissione del certificato fallisce se il nome non viene risolto.

Per il front end HTTPS, questa guida usa Traefik, che emette e rinnova automaticamente i certificati Let's Encrypt e si integra direttamente con Compose. Se non lo esegui già, segui prima la configurazione del reverse proxy Traefik e del TLS automatico; crea una rete Docker esterna (proxy qui sotto) e un resolver ACME (letsencrypt) a cui si collega il servizio Vaultwarden. Anche nginx con un certificato emesso manualmente funziona allo stesso modo dal lato Vaultwarden.

Preferisci nginx e Certbot invece di Traefik? Collega Vaultwarden a 127.0.0.1:8080 (aggiungi ports: ["127.0.0.1:8080:80"] al servizio e rimuovi le label Traefik), quindi emetti un certificato e configura il proxy verso il servizio. La parte relativa al certificato è descritta in emissione dei certificati Let's Encrypt con Certbot e nginx. L'elemento aggiuntivo fondamentale è l'upgrade WebSocket sul percorso delle notifiche:

server {
    listen 443 ssl;
    server_name vault.example.com;

    client_max_body_size 525M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Nota la riga X-Real-IP: consente a Fail2ban di identificare in seguito l'attaccante reale anziché 127.0.0.1. Tutto il resto di questa guida è identico, indipendentemente dal fatto che davanti venga utilizzato Traefik o nginx.

Passaggio 2: il file Compose

Create prima la directory del progetto. Questa guida usa /opt/vaultwarden, che rende prevedibile il nome del progetto Compose e quindi il volume dati vaultwarden_vw-data; i passaggi successivi relativi a Fail2ban e ai backup dipendono esattamente da questo nome.

sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwarden

Create un .env per il secret dell'amministratore e il file Compose in questa directory.

# .env
ADMIN_TOKEN=paste-a-strong-token-here

Generate il token con openssl rand -base64 48 e incollatelo nel file. (La forma con hash più robusto viene descritta nel passaggio successivo; per iniziare è sufficiente una stringa casuale lunga.)

# docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "true"          # closed in Step 4, keep true just to register
      ADMIN_TOKEN: "${ADMIN_TOKEN}"
      IP_HEADER: "X-Forwarded-For"     # X-Real-IP if your proxy sends that instead
      LOG_FILE: "/data/vaultwarden.log"
      LOG_LEVEL: "warn"
    volumes:
      - vw-data:/data
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.vw.rule=Host(`vault.example.com`)"
      - "traefik.http.routers.vw.entrypoints=websecure"
      - "traefik.http.routers.vw.tls.certresolver=letsencrypt"
      - "traefik.http.services.vw.loadbalancer.server.port=80"

volumes:
  vw-data:

networks:
  proxy:
    external: true

Due aspetti di questo file determinano l'intero design. Non esiste alcun mapping ports:, quindi Vaultwarden è raggiungibile soltanto tramite Traefik e la relativa terminazione TLS; pubblicare la sua porta sull'host significa esporre accidentalmente il vault tramite http. Inoltre, DOMAIN deve essere l'URL HTTPS pubblico completo: viene incorporato nei link degli allegati, nella 2FA WebAuthn e nell'endpoint delle notifiche. Un valore errato o http rompe queste funzioni anche quando il sito viene caricato. Il tag latest è un'eccezione deliberata alla consueta regola di non usare mai latest. Vaultwarden distribuisce le release stabili come un'unica immagine rolling, mentre :testing è il canale separato per le versioni preliminari. Eseguite quindi gli aggiornamenti intenzionalmente e consultate rapidamente le note di rilascio prima di eseguire il pull. L'eccezione è circoscritta: per la maggior parte dei container a lunga durata è preferibile usare un tag esatto, perché mantiene prevedibile un agent self-hosted sempre attivo sullo stesso VPS tra riavvii e pull.

Avviatelo e monitorate il log:

docker compose up -d
docker compose logs -f vaultwarden

Un avvio corretto termina con una riga come Rocket has launched from http://0.0.0.0:80. Attendete alcuni secondi affinché Traefik recuperi il certificato, quindi caricate https://vault.example.com. Dovreste visualizzare il vault web di Bitwarden con un lucchetto valido e senza avvisi relativi al certificato.

Passaggio 3: un ADMIN_TOKEN robusto e il problema di $$

ADMIN_TOKEN protegge /admin, il pannello che può leggere tutti gli utenti e tutte le impostazioni della tua istanza. Trattalo quindi come una password di root. Sono supportate due forme.

La forma semplice è la stringa casuale che hai già generato con openssl rand -base64 48. Poiché base64 non contiene mai un $, può essere inserita direttamente in .env senza alcun escaping.

La forma più sicura è un hash PHC Argon2, quindi il token in chiaro non viene mai memorizzato su disco. Generane uno usando la stessa immagine:

docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp

Il comando richiede il token due volte e stampa una stringa che inizia con $argon2id$v=19$.... Ecco il problema che può costare un'ora di lavoro: Docker Compose tratta $ come interpolazione di variabili. Se incolli l'hash direttamente sotto environment: nel file Compose, devi quindi raddoppiare ogni $ trasformandolo in $$. In quel punto puoi racchiudere il valore tra virgolette; ciò che conta è l'escaping:

    environment:
      ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$c29tZXNhbHQ$$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

Se preferisci conservare l'hash in .env, la regola cambia: lascia i singoli segni $, racchiudi l'intero valore tra apici singoli (ADMIN_TOKEN='$argon2id$v=19$...') e la riga ${ADMIN_TOKEN} già presente nel file Compose lo utilizzerà. Non raddoppiare mai $ in .env. Se lasci i segni singoli $ direttamente nel file Compose, Compose emette l'avviso The "argon2id" variable is not set e svuota il token; di conseguenza /admin rifiuta la password corretta. Esegui docker compose up -d e conserva il testo in chiaro inserito al prompt nel tuo password store.

Passaggio 4: registra l’account, quindi chiudi l’accesso

Con SIGNUPS_ALLOWED: "true", apri https://vault.example.com, fai clic su Create account e registrati con il tuo indirizzo email e una password master complessa. Questa password master non è recuperabile e non esiste una procedura di reimpostazione. Salvala prima in un luogo affidabile.

Ora chiudi l’accesso. Modifica il file Compose per disabilitare le registrazioni:

      SIGNUPS_ALLOWED: "false"

Riapplica la configurazione con docker compose up -d. Non è un’attività di hardening da rimandare. Se le registrazioni restano aperte, chiunque trovi l’URL, inclusi i crawler, può creare un account sul server. Questi utenti non possono leggere il tuo vault, ma consumano risorse e trasformano la tua istanza privata in un servizio pubblico. Il segnale che hai lasciato l’opzione attiva è che /admin elenca account che non hai mai creato.

Per aggiungere in seguito familiari o membri del team senza riaprire le registrazioni pubbliche, usa il pulsante Invite User in /admin. Questo percorso richiede la configurazione di SMTP, in modo che l’invitato riceva il relativo link.

Passaggio 5: accesso a /admin

Apri https://vault.example.com/admin e inserisci il token amministrativo in chiaro (la stringa casuale oppure la password di cui hai calcolato l’hash, non l’hash stesso). Da qui puoi elencare gli utenti, modificare le impostazioni, inviare un’email di test e creare uno snapshot del database.

Se la pagina mostra invece The admin panel is disabled, please configure the 'ADMIN_TOKEN' variable to enable it, ADMIN_TOKEN è vuota o non impostata e disabilita completamente il pannello. Questa può essere una scelta valida se non ti serve mai. Se la pagina viene caricata ma rifiuta il token, consulta il problema di escape di $$ nell’elenco degli errori riportato sotto. Hai dimenticato il token? Non esiste una procedura di recupero: modifica .env o il file Compose, impostane uno nuovo e docker compose up -d.

Passaggio 6, collegare i client Bitwarden

Ogni client ufficiale può connettersi a un server self-hosted. Installa quindi il client Bitwarden per desktop, dispositivi mobili o browser dagli store consueti. Non serve una build speciale di Vaultwarden.

Prima di accedere, apri l'icona a forma di ingranaggio delle impostazioni nella schermata di accesso, indicata come Self-hosted o Region → Self-hosted. Imposta Server URL su https://vault.example.com e salva. Accedi quindi con l'indirizzo email e la master password registrati. Il client dovrebbe connettersi immediatamente e offrire il riempimento e il salvataggio delle credenziali.

Se un client mostra This is not a recognized Bitwarden server. You may need to check with your provider or update your server., l'URL è errato, usa http oppure il certificato non è considerato attendibile. Verifica innanzitutto che https://vault.example.com venga caricato correttamente in un browser. Gli aggiornamenti lenti sugli altri dispositivi dipendono dal push tramite WebSocket, descritto di seguito.

Passaggio 7, una jail Fail2ban per l’endpoint di accesso

Vaultwarden registra ogni accesso non riuscito nel file impostato da LOG_FILE, esattamente ciò che serve a un sistema di protezione dai tentativi di forza bruta. Se Fail2ban non è già in esecuzione, le istruzioni per l’installazione e la configurazione di base sono disponibili nella guida al rafforzamento SSH con Fail2ban; qui aggiungiamo una jail per Vaultwarden.

Per prima cosa, individua il percorso del volume denominato sull’host, in modo che Fail2ban possa leggere il log:

docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}'

Il comando restituisce un risultato simile a /var/lib/docker/volumes/vaultwarden_vw-data/_data; al suo interno, il log si trova in vaultwarden.log. Crea il filtro:

# /etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =

Quindi crea la jail:

# /etc/fail2ban/jail.d/vaultwarden.local
[vaultwarden]
enabled   = true
filter    = vaultwarden
logpath   = /var/lib/docker/volumes/vaultwarden_vw-data/_data/vaultwarden.log
banaction = iptables-allports
chain     = DOCKER-USER
maxretry  = 5
findtime  = 600
bantime   = 3600

Ricarica la configurazione con sudo systemctl restart fail2ban e verifica il risultato con sudo fail2ban-client status vaultwarden.

Tre dettagli di Docker determinano se questa protezione funziona davvero. Primo: se il log mostra IP: 127.0.0.1 oppure l’indirizzo del proxy a ogni tentativo non riuscito, Vaultwarden sta bloccando il proxy. Imposta IP_HEADER sull’header inviato effettivamente dal proxy (X-Forwarded-For per Traefik, X-Real-IP per il blocco nginx precedente, CF-Connecting-IP quando il servizio è dietro Cloudflare). A partire dalla versione 1.37.4, con X-Forwarded-For Vaultwarden utilizza l’indirizzo più a destra che non appartiene a IP_HEADER_TRUSTED_PROXIES (il valore predefinito è local, che copre un proxy sullo stesso host o sulla stessa rete Docker). Se davanti al proxy è presente una CDN, aggiungi anche i relativi indirizzi.

Secondo: la catena iptables corretta dipende dal proxy. Con Traefik in esecuzione come container con porte pubblicate, il traffico attraversa il percorso FORWARD di Docker, quindi il ban deve essere applicato in DOCKER-USER, come sopra. Se invece hai scelto l’opzione host-nginx del Passaggio 1, le connessioni terminano su nginx nell’host, nella catena INPUT; un ban DOCKER-USER non le intercetta. In questo caso, elimina la riga chain = DOCKER-USER, così Fail2ban utilizza la catena predefinita INPUT.

Terzo: usa banaction = iptables-allports invece del valore predefinito basato sulla porta. Questa jail non definisce alcuna porta e un ban su tutte le porte in DOCKER-USER blocca correttamente l’autore dell’attacco da ogni servizio pubblicato sull’host.

Passaggio 8: esegui il backup del vault, quindi ripristinalo davvero

Il volume vw-data è il tuo gestore di password. Contiene db.sqlite3 (ogni voce), le directory attachments/ e sends/, i file rsa_key.* che firmano le sessioni di accesso e config.json dal pannello di amministrazione. Un backup che ne omette anche solo uno non sarà utilizzabile quando ne avrai bisogno.

La copia di db.sqlite3 mentre Vaultwarden sta scrivendo può produrre un file parzialmente scritto e corrotto. Esegui quindi uno snapshot a freddo; il downtime dura pochi secondi:

#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F)
DEST=/root/vw-backups
VOL=$(docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}')
mkdir -p "$DEST"
docker compose -f /opt/vaultwarden/docker-compose.yml stop vaultwarden
tar czf "$DEST/vw-$STAMP.tgz" -C "$VOL" .
docker compose -f /opt/vaultwarden/docker-compose.yml start vaultwarden

Esegui questa operazione ogni notte tramite cron e copia .tgz fuori dal server. Un backup presente solo sul server che stai proteggendo non è un backup. Il modo corretto per trasferirlo è un backup notturno con restic su un altro server o su uno storage a oggetti, che cifra l'archivio e deduplica automaticamente gli snapshot ripetuti. Il pulsante Backup Database del pannello di amministrazione è utile per creare uno snapshot a caldo del solo file SQLite, ma esclude gli allegati e le chiavi.

Ora esegui la procedura che distingue un backup reale da una semplice ipotesi: ripristinalo una volta e verifica che funzioni:

mkdir -p /tmp/vw-restore
tar xzf /root/vw-backups/vw-2026-07-15.tgz -C /tmp/vw-restore
docker run --rm -p 127.0.0.1:8888:80 -v /tmp/vw-restore:/data vaultwarden/server

Dal laptop, crea un tunnel verso il server con ssh -L 8888:127.0.0.1:8888 you@your-vps e apri http://localhost:8888 (oppure http://127.0.0.1:8888). Poiché gli indirizzi di loopback sono considerati un contesto sicuro, crypto.subtle è disponibile e il vault viene decifrato tramite http non cifrato in questo caso. È l'unico tipo di indirizzo per cui ciò è consentito. Accedi con la password principale e verifica che le tue voci siano presenti. Se lo sono, il database, le chiavi RSA e la password principale vengono ripristinati correttamente e puoi ricostruire l'installazione su un nuovo VPS in pochi minuti. Arresta il container con Ctrl-C ed elimina /tmp/vw-restore. Usa lo stesso approccio con tunnel per qualsiasi altra interfaccia di amministrazione sul server che non dovrebbe mai essere esposta a Internet. È anche il modo per raggiungere uno scanner di sicurezza open-kritt self-hosted sulla porta 5173.

Modalità di errore e stringhe visualizzate

Cannot read properties of undefined (reading 'importKey') nella console del browser. Il vault è stato caricato tramite http, quindi crypto.subtle non è definito. Raggiungilo solo tramite https:// e aggiungi il redirect da HTTP a HTTPS sul proxy.

This is not a recognized Bitwarden server... in un client. Il Server URL usa http, contiene un errore di digitazione oppure il certificato non è considerato attendibile. Verifica che https://vault.example.com mostri un lucchetto valido, quindi inserisci nuovamente l'URL nelle impostazioni self-hosted del client.

/admin rifiuta la password corretta. L'hash Argon2 ha perso l'escaping. Ogni $ deve essere $$ nel file Compose, ma un singolo $ deve essere usato tra virgolette singole in .env. In alternativa, potresti avere inserito l'hash invece del testo in chiaro corrispondente.

Sincronizzazione lenta tra dispositivi; la console mostra WebSocket connection to 'wss://vault.example.com/notifications/hub' failed. Il proxy non inoltra gli header Upgrade/Connection. Traefik lo fa automaticamente; nginx richiede le due righe di upgrade indicate nel Passaggio 1. Il vault continua a funzionare, ma la sincronizzazione viene eseguita solo all'apertura. La vecchia porta dedicata 3012 è stata rimossa dalla v1.31.0, quindi non è necessaria una route WebSocket separata.

Fail2ban segnala un ban, ma l'attaccante continua a connettersi. Il ban viene applicato a 127.0.0.1 perché IP_HEADER è errato, oppure è stato inserito nella catena iptables sbagliata. Imposta chain = DOCKER-USER e banaction = iptables-allports.

Aggiornamenti

Scarica la nuova immagine e ricrea il container; il volume denominato e tutti i dati persistono:

docker compose pull
docker compose up -d

Vaultwarden rilascia frequentemente nuove versioni. Consulta le note di rilascio del progetto invece di fissare una versione di patch, perché alcune release includono note sulla migrazione. Esegui un nuovo backup prima di ogni aggiornamento importante; puoi eseguire il rollback ripristinando l'archivio tar in un nuovo volume.

FAQ

Vaultwarden è la stessa cosa di Bitwarden?

È un server compatibile e indipendente, non quello ufficiale. Vaultwarden reimplementa in Rust l’API del server Bitwarden, quindi i client ufficiali desktop, mobile, browser e CLI funzionano tutti con esso, usando una frazione delle risorse richieste dallo stack ufficiale. Il formato del vault è lo stesso, quindi puoi eseguire la migrazione in entrambe le direzioni esportando e importando i dati.

Ho davvero bisogno di HTTPS o posso usare http sulla LAN?

Ti serve HTTPS per qualsiasi utilizzo diverso da un test su loopback. Il vault web e le estensioni di Bitwarden usano la Web Crypto API del browser, disponibile solo in un contesto sicuro. Su http non crittografato, quindi, il client genera Cannot read properties of undefined e non completa mai l’accesso. Gli unici indirizzi http compatibili sono quelli di loopback, come http://localhost o http://127.0.0.1. Per questo il test di ripristino nel passaggio 8 usa un tunnel SSH.

Come impedisco a utenti sconosciuti di registrarsi sul mio server?

Imposta SIGNUPS_ALLOWED: "false" nel file Compose ed esegui docker compose up -d subito dopo aver creato il tuo account. Da quel momento, aggiungi nuove persone tramite il pulsante Invita utente in /admin. Questa procedura richiede SMTP configurato, così gli utenti ricevono il link di invito. Controlla periodicamente l’elenco degli utenti amministrativi per verificare che non siano comparsi account inattesi.

Come posso eseguire il backup del mio vault Vaultwarden?

Arresta temporaneamente il container e archivia l’intero volume vw-data, db.sqlite3, attachments/, sends/, config.json e i file rsa_key.*. Poi copia l’archivio fuori dal server, idealmente tramite un cron notturno. Copiare il file SQLite mentre il server è in esecuzione può produrre uno snapshot danneggiato, quindi esegui il backup a servizio arrestato. Soprattutto, ripristinalo una volta in un container temporaneo ed esegui l’accesso. In questo modo verifichi che il backup sia valido prima di farci affidamento.

È davvero sicuro gestire autonomamente le mie password?

Sì, se esegui le tre attività descritte in questa guida: HTTPS effettivo, registrazioni disabilitate con un token amministrativo robusto e backup verificati. Il vault viene crittografato lato client con la password principale. Il server, quindi, non vede mai le password in chiaro e il furto di db.sqlite3 non espone le tue credenziali senza quella password. Il server conserva comunque gli indirizzi email degli account e un hash con salt derivato da ogni password principale. Un attaccante può tentare di violarlo offline, quindi devi proteggere il file del database e ogni sua copia. Il compromesso è che patch e backup diventano una tua responsabilità. Per questo Fail2ban e la procedura di ripristino non sono facoltativi. Dopo averli configurati, un esame più approfondito dei punti in cui un vault self-hosted può essere attaccato è il passo successivo più utile. Poiché le voci sono crittografate nel client, gli elementi da proteggere rimasti sono il token amministrativo e l’archivio di backup.