SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-09-01

Paano Mag-backup at Mag-restore ng Vaultwarden sa VPS

Gamitin ang sqlite3 .backup para sa live Vaultwarden vault, isama ang attachments, config.json at rsa_key files, at subukan ang restore bago kailanganin.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 5, 2026.

Mga dapat laman ng Vaultwarden backup

Ang Vaultwarden backup ay kopya ng buong data folder. Dapat ding tama ang paraan ng pagkopya sa database na nasa loob nito. Patakbuhin ang sqlite3 db.sqlite3 ".backup out.sqlite3" sa halip na cp, dahil maaaring hindi mabuksan ang plain copy ng database habang sinusulatan ito. Itago rin ang mga file na nasa tabi nito. Ito ang bahaging madalas nakakalimutan.

Sa Docker installation, ang data folder ay ang anumang directory na ni-mount mo sa /data. Maaari itong path sa host o named volume. Tinutukoy ng pagkakaiba ng bind mounts at named volumes kung saan talaga nasa disk ang vault mo. Narito ang laman nito.

  • db.sqlite3: lahat ng account, vault item, folder, at organisation. Kapag nawala ang file na ito, mawawala ang vault.
  • db.sqlite3-wal at db.sqlite3-shm: ang write-ahead log (WAL) at shared memory index nito. Nananatili rito ang mga bagong write hanggang maisama ng SQLite ang mga ito sa pangunahing file.
  • attachments/: mga file na naka-attach ng mga user sa vault item, naka-encrypt at nasa tig-isang directory para sa bawat item.
  • sends/: mga file sa likod ng Bitwarden Send links.
  • config.json: lahat ng setting na sine-save mo mula sa admin page.
  • rsa_key.pem, pati rsa_key.der at rsa_key.pub.der sa mga mas lumang installation: ang key na ginagamit para mag-sign ng login token.
  • icon_cache/: mga na-download na website icon. Ito ang isang directory na maaari mong laktawan, dahil dina-download muli ng Vaultwarden ang mga icon kapag kinakailangan.

Ligtas ba ang Vaultwarden database ko? Ano talaga ang laman ng file

Dalawang command ang makakasagot dito, at maaari mong patakbuhin ang mga ito ngayon.

sudo apt update && sudo apt install -y sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select email from users;"
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select name from ciphers limit 1;"

Inililimbag ng una ang mga email address ng iyong mga user bilang cleartext. Inililimbag naman ng pangalawa ang pangalan ng isang item, na ganito ang hitsura:

2.k9Qw1nQ0y7Yy2Xw==|E1r0J3l5s7d9f1g3h5j7k9==|Lm4nOp6qRs8tUv0wXy2zAb4cDe6fGh8i=

Ini-encrypt ng client ang mga pangalan ng item, username, password, at note bago ipadala ang mga ito. Kaya ciphertext ang ini-store ng server at hindi nito mababasa. Ang prefix na 2. ay encryption type ng Bitwarden. Sinusundan ito ng initialization vector (IV), ciphertext, at MAC (message authentication code). Naka-base64 ang bawat isa at pinaghihiwalay ng |. Ang key na nagde-decrypt nito ay dine-derive mula sa master password ng account. Hindi kailanman nakakarating sa server ang master password sa usable na anyo. Pareho ang bahaging ito kahit Vaultwarden o ang official server ang pinapatakbo mo, gaya ng ipinapaliwanag sa paghahambing ng Vaultwarden at self-hosted Bitwarden.

Hindi encrypted ang natitirang bahagi ng database. Naka-store bilang plain text ang mga email address, pangalan ng account, password hint, at two-factor recovery code, kasama ng metadata gaya ng mga oras ng paglikha at kung aling organization ang nagmamay-ari ng isang item. Kaya secret mismo ang backup file. Malalaman ng sinumang may hawak nito kung sinu-sino ang iyong mga user, at maaari nilang atakehin offline ang mga encrypted blob sa bilis na kaya ng kanilang hardware. Dahil dito, kailangang i-encrypt ang kopya bago ito umalis sa server. Ang admin token ang kabilang bahagi ng parehong problema, at tinatalakay ng hardening pass para sa self-hosted Vaultwarden ang dalawang ito.

Bakit hindi backup ang pagkopya ng db.sqlite3 habang tumatakbo ang Vaultwarden

Ginagamit ng Vaultwarden ang SQLite sa WAL mode bilang default (ENABLE_DB_WAL=true). Sa db.sqlite3-wal muna napupunta ang isang write, at inililipat lamang ito sa db.sqlite3 kapag may checkpoint. Kapag db.sqlite3 lang ang kinopya mo, makukuha mo ang database sa oras ng huling checkpoint. Dahil dito, maaaring wala sa archive mo ang password na na-save sampung minuto na ang nakalipas, nang walang anumang babala.

Hindi rin solusyon ang pagkopya sa tatlong file gamit ang cp. Kinokopya ang mga ito sa bahagyang magkakaibang oras. Dahil dito, maaaring naglalarawan ang na-save mong WAL ng mga bersyon ng page na hindi na tumutugma sa na-save mong main file. Susubukan ng SQLite na i-recover ang isa mula sa isa pa, at magiging mali ang resulta. Maaaring matuklasan mo ito makalipas pa ang mahabang panahon:

Error: database disk image is malformed

Iniiwasan ito ng .backup dahil ginagamit nito ang SQLite Online Backup API. Itinuturing ito ng SQLite na tamang paraan para kumopya ng database na aktibong ginagamit. Binabasa nito ang mga page habang may read lock. Magsisimula itong muli kung may writer na magbabago sa file habang isinasagawa ang pagkopya. Kaya ang naisusulat sa disk ay isang magkakaugnay na snapshot mula sa iisang oras.

Kunin ang database copy gamit ang sqlite3 .backup

sudo apt update && sudo apt install -y sqlite3
sudo install -d -m 700 /var/backups/vaultwarden
OUT=/var/backups/vaultwarden/db-$(date '+%Y%m%d-%H%M').sqlite3
sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 ".backup '$OUT'"
sudo sqlite3 "$OUT" "PRAGMA integrity_check;"

Ipinapakita ng huling command ang ok sa sarili nitong linya. Kapag iba ang lumabas, hindi magagamit ang copy. Huwag itong itago at huwag burahin ang naunang copy. Isinasagawa ang buong sequence habang live ang server. Walang user na mai-log out at walang container na magre-restart.

Wala sa loob ng Vaultwarden container ang tool na sqlite3. Binuo ang image gamit ang debian:trixie-slim, ca-certificates, curl, libmariadb3, libpq5, at openssl. Dahil dito, mabibigo ang docker exec vaultwarden sqlite3 ... at lalabas ang:

exec: "sqlite3": executable file not found in $PATH

Patakbuhin ito sa host laban sa naka-mount na path. Ito ang ginagawa ng mga command sa itaas. Kung nasa named volume ang data, ipinapakita ng docker volume inspect <name> ang host path sa ilalim ng /var/lib/docker/volumes/.

May sarili ring backup command ang Vaultwarden mula noong version 1.32.1. Sa iyong server:

docker exec -it vaultwarden /vaultwarden backup

Pinapatakbo nito ang VACUUM INTO at isinusulat ang db_YYYYMMDD_HHMMSS.sqlite3 sa data folder. Dalawang bagay ang dapat tandaan. Napupunta ang copy sa tabi ng original sa parehong disk. Staging step lamang ito at hindi pa backup. SQLite lamang ang sinusuportahan nito. Sa MariaDB o PostgreSQL, hihinto ito na may The database type is not SQLite. Backups only works for SQLite databases.

Ang mga file na madalas makalimutan

attachments/ ang naglalaman ng ciphertext sa ilalim ng mga hindi pamilyar na pangalan. Ang database row para sa bawat attachment ay naglalaman ng encrypted file name nito at ng key material na kailangan ng client para ma-decrypt ang file. Kapag wala ang attachments, hindi mababasa ang laman ng database. Kapag wala naman ang database, magkakaroon ang mga user ng mga item na magfa-fail ang download. Isama ang dalawang ito sa iisang run.

config.json ang naglalaman ng lahat ng sine-save mo mula sa admin page, at mas mataas ang priority ng mga value nito kaysa sa katugmang environment variables. May dalawang epekto ito: kapag nag-restore ka ng lumang config.json, tahimik nitong ino-override ang mga setting sa compose file mo. Sensitive rin ang file mismo dahil maaaring naglalaman ito ng SMTP password at admin token. I-store ang token bilang Argon2id PHC (password hashing competition) string, hindi bilang plain text. Ang docker run --rm -it vaultwarden/server /vaultwarden hash ang magpi-print nito para sa iyo.

rsa_key.pem ang pumipirma sa JSON web tokens (JWT) na nagpapanatiling naka-log in ang mga client. Kapag nawawala ang file sa startup, gumagawa ang Vaultwarden ng bagong key. Dahil dito, hindi na mabe-validate ang bawat token na pinirmahan gamit ang lumang key, at mala-log out ang lahat ng client. Mananatili ang laman ng vault dahil naka-encrypt ito gamit ang mga key na dine-derive mula sa master password. Maiiwasan ang mass logout kapag na-restore ang key file.

sends/ ang naglalaman ng mga file sa likod ng Send links. Kapag nawawala ang mga ito, masisira ang downloads na iyon at wala nang iba.

Ilagay ang buong proseso sa isang script

#!/bin/bash
set -euo pipefail

DATA=/opt/vaultwarden/data
DEST=/var/backups/vaultwarden
STAMP=$(date '+%Y%m%d-%H%M%S')
STAGE=$(mktemp -d /tmp/vw-stage.XXXXXX)

install -d -m 700 "$DEST"
sqlite3 "$DATA/db.sqlite3" ".backup '$STAGE/db.sqlite3'"
test "$(sqlite3 "$STAGE/db.sqlite3" 'PRAGMA integrity_check;')" = "ok"
cp -a "$DATA"/rsa_key* "$STAGE/"
for extra in config.json attachments sends; do
  if [ -e "$DATA/$extra" ]; then cp -a "$DATA/$extra" "$STAGE/"; fi
done
tar -C "$STAGE" -czf "$DEST/vw-$STAMP.tar.gz" .
chmod 600 "$DEST/vw-$STAMP.tar.gz"
rm -rf "$STAGE"
tar -tzf "$DEST/vw-$STAMP.tar.gz"

I-save ito bilang /usr/local/sbin/vw-backup.sh, gawin itong executable gamit ang chmod 700, at patakbuhin bilang root. May mahalagang ginagawa ang linyang test: nag-e-exit ang sqlite3 na may exit status 0 kahit mag-ulat ang PRAGMA integrity_check ng corruption. Kaya ang paghahambing ng output sa ok ang nagiging sanhi upang mabigo ang script kapag may maling kopya. Pagkatapos, ihihinto ng set -euo pipefail ang lahat, sa halip na hayaan ang tar na bumuo ng maayos na archive mula sa sirang database.

Inililista ng huling tar -tzf ang aktuwal na nakuhang data. Basahin ito sa unang pagpapatakbo. Hanapin ang ./db.sqlite3, ./rsa_key.pem, ./config.json, at ./attachments/, pati ang kawalan ng ./db.sqlite3-wal. Patakbuhin ito gabi-gabi gamit ang systemd service at timer sa halip na cron kung gusto mo ng journalctl output at unit na nag-uulat kapag nabigo.

I-verify ang backup sa pamamagitan ng pag-restore nito sa scratch directory

Ang backup na hindi nasusubukan ay hula lamang. Isang minuto lang ang pag-restore sa scratch directory at wala itong binabago sa live environment.

sudo install -d -m 700 /tmp/vw-check
sudo tar -C /tmp/vw-check -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
ls -l /tmp/vw-check
sudo sqlite3 /tmp/vw-check/db.sqlite3 "PRAGMA integrity_check;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from users;"
sudo sqlite3 /tmp/vw-check/db.sqlite3 "select count(*) from ciphers;"
sudo du -sh /tmp/vw-check/attachments

Mahalaga ang apat na result. Ipi-print ng integrity_check ang ok. Dapat tumugma ang bilang ng user sa bilang ng mga account na alam mo. Dapat malapit ang bilang ng cipher sa live na value mula sa sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select count(*) from ciphers;", at hindi ito dapat maging zero sa vault na ginagamit. Dapat humigit-kumulang tumugma ang laki ng attachments directory sa inaasahan mo. Maaari mong laktawan ito kung walang nag-a-upload ng attachment. Pagkatapos, patakbuhin ang sudo rm -rf /tmp/vw-check, dahil may pangalawang kopya na ngayon ng lahat ang directory na iyon.

May isang tuntunin kapag nag-restore ng anumang data folder na mano-manong kinopya: i-delete ang db.sqlite3-wal at db.sqlite3-shm bago simulan ang server. Kung hindi, susubukan ng SQLite na i-recover ang na-restore na database gamit ang log na kabilang sa ibang kopya nito. Masisira nito ang database kahit buo itong dumating. Hindi kailanman naglalaman ang mga archive na ginawa ng script sa itaas ng mga file na iyon, dahil nagsusulat ang .backup ng isang kumpletong database.

Ibalik sa server

Isagawa ang mga ito sa sarili mong server habang naka-stop ang container. Hindi dapat sumusulat ang Vaultwarden habang binabago ang data folder nito.

cd /opt/vaultwarden
docker compose stop vaultwarden
sudo mv data data.old.$(date '+%Y%m%d-%H%M%S')
sudo install -d -m 700 data
sudo tar -C data -xzf /var/backups/vaultwarden/vw-20260805-030000.tar.gz
sudo chown -R root:root data
docker compose start vaultwarden
docker compose logs --tail 20 vaultwarden

Dapat tukuyin ng chown ang user na ginagamit ng container. Bilang default, root ang ginagamit ng image, kaya tama ang root:root maliban kung itinakda mo ang user: sa compose file. Kung ganoon, gamitin ang uid at gid na iyon. Kapag hindi maisulat ng server ang data folder, magpapakita ito ng login page pero mabibigo ang bawat request. Makikita ito sa logs.

Matagumpay ang pagsisimula kapag lumabas ang Rocket line:

[INFO] Rocket has launched from http://0.0.0.0:80

Pagkatapos, mag-log in mula sa browser, magbukas ng item, at mag-download ng isang attachment. Kung gumagana ang login pero nabibigo ang pag-download ng attachment, ibig sabihin ay naisama sa archive ang database pero hindi ang attachments/. Panatilihin ang data.old.* hanggang makumpirma ang lahat ng ito, saka ito tanggalin. Pareho ang tatlong hakbang sa pag-rollback, ngunit pagpapalitin ang mga directory sa kabilang direksiyon.

Kung hindi tugma ang iyong mga path sa mga nasa itaas, ipinapakita sa guide sa pag-install ng Vaultwarden para sa VPS ang compose file na ipinapalagay ng mga command na ito.

Saan hindi dapat ilagay ang backup

  • Huwag sa parehong disk kung nasaan ang data folder. Kapag nag-fail ang isang volume, mawawala ang dalawang kopya. Ganoon din ang mangyayari sa isang rm -rf na maling path.
  • Huwag sa parehong server, kahit nasa pangalawang volume. Kapag nakarating ang attacker sa root, maaabot din nito ang iyong mga backup sa parehong session.
  • Huwag sa object storage nang walang encryption, dahil naglalaman ang archive ng mga email address, password hint, recovery code, at vault ciphertext na maaaring atakihin offline.
  • Huwag umasa lamang sa snapshots ng iyong provider. Mabilis ang restore ng mga ito, kaya kapaki-pakinabang ang mga ito. Gayunman, nasa parehong account sila ng server, kaya kapag nagkaproblema ang account, kasama rin silang maaapektuhan.

Dito pumapasok ang offsite copy at restic, dahil naka-encrypt ang restic repository sa machine bago i-upload ang kahit ano. Sa iyong server:

sudo apt install -y restic
export RESTIC_REPOSITORY=s3:https://s3.example.com/vaultwarden-backups
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic init
restic backup /var/backups/vaultwarden --tag vaultwarden
restic snapshots --tag vaultwarden
restic forget --tag vaultwarden --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Ituro ang restic sa archive directory at hindi sa live data folder, upang ang ma-upload nito ay ang consistent na kopyang nasuri mo na. Itago ang repository password sa ibang lugar, hindi sa server na pinoprotektahan nito: kapag nawala ang password na iyon, hindi na mababasa ang snapshots, ayon sa disenyo. Kung sinusuportahan ito ng storage, bigyan ang server ng credentials na maaaring magsulat ngunit hindi mag-delete, upang hindi mabura ng isang breached na machine ang sarili nitong history. Sinasaklaw nang buo ng Pag-set up ng restic backups sa isang VPS ang repository at schedule, at ipinapaliwanag ng Paghahambing ng restic at BorgBackup ang pagpili kung hindi ka pa nakapagpasya.

Subukan ang restore ayon sa iskedyul

Pumili ng isang araw bawat buwan. I-download ang pinakabagong snapshot sa isang scratch directory gamit ang restic restore latest --tag vaultwarden --target /tmp/vw-check, patakbuhin ang parehong PRAGMA integrity_check, patakbuhin ang parehong row counts, at itala ang petsa at mga bilang. Ang backup na walang nag-restore sa loob ng anim na buwan ay may hindi tiyak na estado. Malalaman mo lamang ang estado nito kapag may outage, na siyang pinakamasamang oras para ito malaman.

Minsan bawat taon, isagawa ang buong bersyon. Mag-start ng pangalawang Vaultwarden container sa isang bakanteng port gamit ang na-restore na data folder, at mag-log in gamit ang isang aktuwal na account. Pinatutunayan nito ang master password path mula simula hanggang dulo, na hindi kayang patunayan ng anumang row count. Ang restic check --read-data-subset=10% ayon sa parehong iskedyul ay nagbe-verify na nababasa ang nakaimbak na data, sa halip na naililista lamang.

FAQ

Maaari ko bang kopyahin ang db.sqlite3 gamit ang cp habang tumatakbo ang Vaultwarden?

Hindi. Gumagamit ang Vaultwarden ng SQLite sa WAL mode, kaya ang mga bagong write ay nasa db.sqlite3-wal pa at wala pa sa db.sqlite3. Kapag cp lamang ng pangunahing file ang ginawa, tahimik na mawawala ang mga ito. Kapag magkahiwalay na kinopya ang dalawang file, maaaring magkaroon ng hindi nagtutugmang pares na lalabas lamang kalaunan bilang Error: database disk image is malformed. Gamitin sa halip ang sqlite3 /path/db.sqlite3 ".backup '/path/out.sqlite3'". Ginagamit nito ang SQLite Online Backup API at gumagawa ito ng isang consistent na file habang patuloy na naghahatid ng serbisyo ang server.

Kailangan ko bang ihinto ang Vaultwarden container para gumawa ng backup?

Hindi, at iyon ang layunin ng .backup. Ligtas kopyahin ang database habang tumatakbo ang server. Isinusulat ang attachments at Send files kapag nag-upload ang user ng file. Kaya maaaring hindi maisama sa archive ng gabing iyon ang file na naidagdag sa pagitan ng pagkopya ng database at ng tar. Sa pinakamasamang kaso, isang attachment lang ang mawawala. Kung hindi problema sa iyo ang ilang segundo ng downtime, ang docker compose stop bago ang script at docker compose start pagkatapos nito ay nag-aalis pati ng panganib na iyon.

Ano ang mangyayari kung mag-restore ako nang walang rsa_key files?

Gagawa ang Vaultwarden ng bagong key sa startup. Nilalagdaan ng key na iyon ang JSON web tokens (JWT) na nagpapanatili sa mga session. Dahil dito, hindi na mavalidate ang lahat ng kasalukuyang token, at mali-log out ang lahat ng client at kailangang mag-sign in muli. Hindi maaapektuhan ang laman ng vault dahil ine-encrypt ito gamit ang mga key na hinango mula sa master password ng bawat user, hindi gamit ang RSA key. I-restore ang rsa_key.pem kasama ng iba pang laman ng data folder upang walang makapansin sa restore.

Ligtas bang i-upload nang walang pagbabago ang backup archive sa object storage?

Hindi. Ciphertext ang mga item name, password, at note, ngunit plain text sa database ang mga email address, account name, password hint, at two-factor recovery code. Maaari ring subukan ng offline attacker ang ciphertext sa sarili nitong bilis. I-encrypt ang archive bago ito umalis sa machine. Awtomatikong ginagawa iyon ng restic repository, at gumagawa ang gpg --symmetric --cipher-algo AES256 vw-20260805-030000.tar.gz ng isang encrypted file na maaari mong ibigay sa anumang storage.

Paano ko ibina-back up ang Vaultwarden sa PostgreSQL o MariaDB?

Hindi naaangkop ang mga hakbang para sa SQLite, at tumatanggi ang built-in command gamit ang The database type is not SQLite. Backups only works for SQLite databases. I-dump ang database gamit ang native tool nito, pg_dump o mysqldump, at panatilihin ang lahat ng iba pang panuntunan. Dapat mapunta ang dump sa isang archive kasama ng attachments/, sends/, config.json, at mga rsa_key file. Gawin ang mga ito sa iisang run, i-encrypt ang archive, at itago ito sa ibang lokasyon kaysa sa server na gumawa nito.