SSD Nodes Learn Hosting plans →
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-27

Vaultwarden VPS Yedekleme ve Geri Yükleme Rehberi

Vaultwarden verilerinizi sqlite3 .backup komutu ile güvenli şekilde yedekleyin. attachments, config.json ve rsa_key dosyalarını dahil ederek tam geri yükleme yapın.

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

Vaultwarden yedeğinin içermesi gerekenler

Vaultwarden yedeği, tüm veri klasörünün bir kopyasıdır ve içindeki veritabanının doğru yöntemle kopyalanması gerekir. Veritabanına yazma işlemi sürerken alınan düz bir kopya, açılmayacak bir dosya oluşturabileceği için cp yerine sqlite3 db.sqlite3 ".backup out.sqlite3" komutunu çalıştırın. Ardından, insanların genellikle unuttuğu kısım olan, veritabanının yanındaki dosyaları da muhafaza edin.

Docker kurulumunda veri klasörü, /data konumuna bağladığınız (mount) dizindir. Bu, ana makine üzerindeki bir yol veya adlandırılmış bir volume olabilir; bind mount ile adlandırılmış volume arasındaki fark, kasanızın disk üzerinde tam olarak nerede bulunduğunu belirler. Klasörün içeriği şöyledir:

  • db.sqlite3: tüm hesaplar, tüm kasa öğeleri, tüm klasörler ve tüm organizasyonlar. Bu dosyanın kaybedilmesi, kasanın kaybedilmesi anlamına gelir.
  • db.sqlite3-wal ve db.sqlite3-shm: write-ahead log (WAL) ve paylaşımlı bellek dizini. SQLite bunları ana dosyaya işleyene kadar en son yazılan veriler burada tutulur.
  • attachments/: kullanıcıların kasa öğelerine eklediği, öğe başına bir dizinde tutulan şifreli dosyalar.
  • sends/: Bitwarden Send bağlantılarının arkasındaki dosyalar.
  • config.json: yönetici sayfasından kaydettiğiniz tüm ayarlar.
  • rsa_key.pem ve eski kurulumlarda buna ek olarak rsa_key.der ve rsa_key.pub.der: giriş token'larını imzalayan anahtar.
  • icon_cache/: indirilen web sitesi simgeleri. Vaultwarden bunları talep üzerine tekrar indirebildiği için yedeklemekten vazgeçebileceğiniz tek dizin budur.

Vaultwarden veritabanım güvende mi? Dosya gerçekte ne içeriyor?

Bu sorunun cevabını iki komut verir ve her ikisini de hemen şimdi çalıştırabilirsiniz.

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;"

İlk komut, kullanıcılarınızın e-posta adreslerini düz metin olarak yazdırır. İkinci komut ise bir öğe adını yazdırır ve şu şekilde görünür:

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

Öğe adları, kullanıcı adları, parolalar ve notlar, sunucuya gönderilmeden önce istemci tarafından şifrelenir; dolayısıyla sunucu, içeriğini okuyamadığı şifreli metinleri (ciphertext) saklar. 2. ön eki Bitwarden'ın şifreleme türüdür; bunu bir başlatma vektörü (IV), şifreli metin ve her biri base64 formatında olan ve | ile ayrılmış bir MAC (mesaj kimlik doğrulama kodu) takip eder. Şifreyi çözen anahtar, hesabın ana parolasından türetilir ve bu parola hiçbir zaman sunucuya kullanılabilir bir biçimde ulaşmaz. Vaultwarden ve kendi kendine barındırılan Bitwarden karşılaştırması bölümünde de belirtildiği üzere, bu kısım Vaultwarden veya resmi sunucuyu çalıştırmanızdan bağımsız olarak aynıdır.

Veritabanının geri kalanı şifreli değildir. E-posta adresleri, hesap adları, parola ipuçları ve iki faktörlü kurtarma kodları; oluşturulma zamanları ve bir öğenin hangi organizasyona ait olduğu gibi meta verilerle birlikte düz metin olarak saklanır. Bu nedenle yedekleme dosyasının kendisi bir sırdır. Dosyayı ele geçiren herkes kullanıcılarınızın kim olduğunu öğrenir ve şifreli bloklara, donanımlarının izin verdiği hızda çevrimdışı saldırı düzenleyebilir. Bu tek gerçek, aşağıda yer alan depolama kurallarını zorunlu kılar: kopya, sunucudan ayrılmadan önce şifrelenmelidir. Yönetici belirteci (admin token) aynı sorunun diğer yarısıdır ve kendi kendine barındırılan Vaultwarden için güvenlik sıkılaştırma rehberi her iki konuyu da ele alır.

Vaultwarden çalışırken db.sqlite3 dosyasını kopyalamanın neden yedekleme sayılmadığı

Vaultwarden, varsayılan olarak SQLite'ı WAL modunda çalıştırır (ENABLE_DB_WAL=true). Bir yazma işlemi önce db.sqlite3-wal dosyasına kaydedilir ve yalnızca bir kontrol noktası (checkpoint) işlemi bu veriyi db.sqlite3 dosyasına aktarır. Sadece db.sqlite3 dosyasını kopyalarsanız, veritabanının son kontrol noktasındaki halini alırsınız; bu da on dakika önce kaydedilen bir parolanın arşivinizde bulunmayabileceği ve sizi uyaracak hiçbir mekanizmanın olmadığı anlamına gelir.

Üç dosyanın tamamını cp ile kopyalamak da bir çözüm değildir. Kopyalar birbirinden çok kısa sürelerle farklı anlarda alınır; bu nedenle kaydettiğiniz WAL dosyası, ana dosyada artık karşılığı olmayan sayfa sürümlerini tanımlıyor olabilir. SQLite daha sonra bu iki dosyayı birbirine göre kurtarmaya çalışır ve sonuç hatalı olur. Bu durumu çok daha sonra fark edersiniz:

Error: database disk image is malformed

.backup bu sorunu önler çünkü SQLite'ın aktif kullanımda olan bir veritabanını kopyalamak için önerdiği yöntem olan Online Backup API'sini kullanır. Sayfaları bir okuma kilidi altında okur ve eğer bir yazma işlemi alttaki dosyayı değiştirirse işleme baştan başlar; böylece diske yazılan veri, tek ve tutarlı bir ana ait olur.

sqlite3 .backup ile veritabanı kopyasını alma

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;"

Son komut, kendi satırında ok çıktısını verir. Bunun dışındaki herhangi bir çıktı, kopyanın kullanılamaz olduğu anlamına gelir; bu durumda kopyayı saklamayın ve önceki kopyayı silmeyin. Tüm süreç canlı bir sunucu üzerinde çalıştığından, kullanıcıların oturumu kapatılmaz ve hiçbir container yeniden başlatılmaz.

sqlite3 aracı Vaultwarden container'ı içerisinde bulunmaz. İmaj debian:trixie-slim üzerinde ca-certificates, curl, libmariadb3, libpq5 ve openssl kullanılarak oluşturulmuştur, bu nedenle docker exec vaultwarden sqlite3 ... şu hata ile başarısız olur:

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

Bunun yerine, yukarıdaki komutların yaptığı gibi, mount edilmiş yol üzerinden ana makinede (host) çalıştırın. Veri bir named volume içerisinde bulunuyorsa, docker volume inspect <name> komutu /var/lib/docker/volumes/ altındaki ana makine yolunu yazdırır.

Vaultwarden, 1.32.1 sürümünden bu yana kendi yedekleme komutunu da sunmaktadır. Sunucunuzda şu komutu çalıştırın:

docker exec -it vaultwarden /vaultwarden backup

Bu komut VACUUM INTO sürecini çalıştırır ve db_YYYYMMDD_HHMMSS.sqlite3 dosyasını veri klasörüne yazar. Burada iki husus dikkate alınmalıdır. Kopya, orijinal dosyanın yanında aynı disk üzerine kaydedilir; dolayısıyla bu bir yedekleme değil, hazırlık aşamasıdır. Ayrıca bu özellik yalnızca SQLite için geçerlidir: MariaDB veya PostgreSQL kullanılıyorsa The database type is not SQLite. Backups only works for SQLite databases hatası ile durur.

İnsanların unuttuğu dosyalar

attachments/ şifreli metinleri opak isimler altında tutar. Her bir ek için veritabanı satırı, şifrelenmiş dosya adını ve istemcinin dosyayı şifresini çözmek için ihtiyaç duyduğu anahtar materyalini taşır. Veritabanı olmayan ekler okunamaz gürültüdür; ekleri olmayan bir veritabanı ise kullanıcılara indirme işlemi başarısız olan öğeler sunar. Her ikisini de aynı yedekleme sürecinde alın.

config.json yönetici sayfasından kaydettiğiniz her şeyi tutar ve buradaki değerler, eşleşen ortam değişkenlerine göre önceliklidir. Bu durum iki ucu keskin bir bıçaktır: eski bir config.json dosyasını geri yüklemek, compose dosyanızdaki ayarları sessizce geçersiz kılar ve dosyanın kendisi SMTP parolanızı ve yönetici jetonunuzu (token) tutabildiği için hassastır. Bu jetonu düz metin yerine bir Argon2id PHC (password hashing competition) dizisi olarak saklayın. docker run --rm -it vaultwarden/server /vaultwarden hash sizin için bir tane oluşturur.

rsa_key.pem istemcilerin oturumunu açık tutan JSON web token (JWT) verilerini imzalar. Dosya başlangıçta eksikse, Vaultwarden yeni bir anahtar oluşturur; bu durumda eski anahtarla imzalanmış tüm jetonların geçerliliği biter ve tüm istemcilerin oturumu kapatılır. Vault içerikleri, ana paroladan türetilen anahtarlarla şifrelendiği için bu durumdan etkilenmez. Anahtar dosyasını geri yüklemek, toplu oturum kapatma sorununu önler.

sends/ Send bağlantılarının arkasındaki dosyaları tutar. Bunların eksik olması, yalnızca ilgili indirme işlemlerinin başarısız olmasına neden olur, başka bir şeyi etkilemez.

Tüm işlemleri tek bir betikte toplama

#!/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"

Dosyayı /usr/local/sbin/vw-backup.sh olarak kaydedin, chmod 700 komutuyla çalıştırılabilir hale getirin ve root yetkileriyle çalıştırın. test satırı asıl işi yapan kısımdır: PRAGMA integrity_check bozulma bildirdiğinde dahi sqlite3 komutu 0 çıkış kodu döndürdüğü için, çıktıyı ok ile karşılaştırmak hatalı bir kopyanın betiği başarısız kılmasına neden olur. set -euo pipefail komutu, tar aracının bozuk bir veritabanı üzerinde düzgün bir arşiv oluşturmasına izin vermek yerine tüm süreci durdurur.

Son aşamadaki tar -tzf komutu, gerçekte nelerin yedeklendiğini listeler. Bu listeyi ilk seferinde mutlaka inceleyin. ./db.sqlite3, ./rsa_key.pem, ./config.json ve ./attachments/ dosyalarının varlığını, ./db.sqlite3-wal dosyasının ise yokluğunu kontrol edin. Eğer journalctl çıktısı almak ve hata durumunda raporlama yapan bir birim kullanmak istiyorsanız, cron yerine systemd servisi ve zamanlayıcısı ile her gece otomatik çalışacak şekilde yapılandırın.

Yedeği bir geçici dizine geri yükleyerek doğrulayın

Test edilmemiş bir yedek, sadece bir tahmindir. Bir yedeği geçici bir dizine geri yüklemek yalnızca bir dakika sürer ve canlı sistemdeki hiçbir şeye dokunmaz.

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

Dört sonuç önemlidir. integrity_check komutu ok çıktısını verir. Kullanıcı sayısı, bildiğiniz hesapların sayısıyla eşleşmelidir. Şifreleme (cipher) sayısı, sudo sqlite3 /opt/vaultwarden/data/db.sqlite3 "select count(*) from ciphers;" üzerinden alınan canlı değerle yakındır ve kullanımda olan bir kasada asla sıfır olmamalıdır. Ekler dizini beklediğiniz boyuta yakındır; kimse dosya yüklemiyorsa bu adımı atlayabilirsiniz. Ardından sudo rm -rf /tmp/vw-check komutunu çalıştırın, çünkü bu dizin artık her şeyin ikinci bir kopyasını barındırmaktadır.

Elle kopyalanan herhangi bir veri klasörünü geri yüklerken uyulması gereken bir kural vardır: sunucuyu başlatmadan önce db.sqlite3-wal ve db.sqlite3-shm dosyalarını silin. Aksi takdirde SQLite, geri yüklenen veritabanını, veritabanının farklı bir kopyasına ait olan bir günlük (log) dosyasını kullanarak kurtarmaya çalışır; bu da sağlam gelen bir veritabanının bozulmasına yol açar. Yukarıdaki betik tarafından oluşturulan arşivler bu dosyaları asla içermez, çünkü .backup tek bir tam veritabanı yazar.

Sunucuya geri yükleme

Bu işlemler, container durdurulmuş haldeyken kendi sunucunuz üzerinde gerçekleştirilir. Veri klasörü alttan değiştirilirken Vaultwarden yazma işlemi yapmamalıdır.

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

chown, container'ın hangi kullanıcı yetkisiyle çalıştığını belirtmelidir. Standart imaj root yetkisiyle çalışır; bu nedenle compose dosyanızda user: değerini değiştirmediyseniz root:root kullanımı doğrudur. Eğer değiştirdiyseniz, ilgili uid ve gid değerlerini kullanın. Sunucunun yazma yetkisinin olmadığı bir veri klasörü, tüm isteklerin başarısız olduğu bir giriş sayfasına neden olur ve bu durum log kayıtlarına yansır.

Sağlıklı bir başlatma işlemi, Rocket satırı ile sona erer:

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

Ardından tarayıcı üzerinden giriş yapın, bir öğeyi açın ve bir ek dosyayı indirin. Giriş işleminin başarılı olup ek dosyaların indirilemediği bir durum, arşivin veritabanını taşıdığını ancak attachments/ dizinini taşımadığını gösterir. Her şeyin doğruluğundan emin olana kadar data.old.* yedeğini saklayın, ardından silin. Geri alma işlemi, dizinlerin yerlerinin değiştirilmesiyle aynı üç adımı içerir.

Yollarınız buradakilerle eşleşmiyorsa, VPS için Vaultwarden kurulum kılavuzu, bu komutların temel aldığı compose dosyasını göstermektedir.

Yedeğin konulmaması gereken yerler

  • Veri klasörü ile aynı disk üzerinde olmamalıdır. Tek bir birim hatası her iki kopyayı da yok eder; yanlış yola uygulanan bir rm -rf de aynı sonucu doğurur.
  • İkinci bir birimde olsa dahi aynı sunucu üzerinde olmamalıdır. root yetkisine ulaşan bir saldırgan, aynı oturumda yedeklerinize de erişebilir.
  • Şifrelenmeden nesne depolama (object storage) üzerinde tutulmamalıdır; çünkü arşiv; e-posta adreslerini, parola ipuçlarını, kurtarma kodlarını ve çevrimdışı saldırıya açık kasa şifreli metinlerini (vault ciphertext) içerir.
  • Sadece sağlayıcınızın sunduğu snapshot'lar ile yetinilmemelidir. Hızlı geri yükleme sağladıkları için kullanışlıdırlar ancak sunucu ile aynı hesapta barındırıldıklarından, bir hesap sorunu yedeği de beraberinde yok eder.

Sunucu dışı bir kopya için restic uygundur; çünkü bir restic deposu, herhangi bir yükleme yapılmadan önce makine üzerinde şifrelenir. Sunucunuzda:

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

restic'i canlı veri klasörüne değil, arşiv dizinine yönlendirin; böylece yüklenen veri, halihazırda kontrol ettiğiniz tutarlı kopyadır. Depo parolasını, koruduğu sunucudan başka bir yerde saklayın: bu parolayı kaybederseniz, tasarım gereği snapshot'lar okunamaz hale gelir. Depolama alanı destekliyorsa, sunucuya sadece yazma yetkisi olan ancak silme yetkisi olmayan kimlik bilgileri tanımlayın; böylece sunucunun ele geçirilmesi durumunda geçmiş veriler silinemez. VPS üzerinde restic yedeklerini yapılandırma rehberi, depo ve zamanlama ayarlarını detaylıca ele almaktadır; henüz karar vermediyseniz restic ve BorgBackup karşılaştırması bölümü tercih yapmanıza yardımcı olacaktır.

Yedek geri yükleme işlemini bir takvime bağlayın

Ayda bir gün belirleyin. En güncel snapshot dosyasını restic restore latest --tag vaultwarden --target /tmp/vw-check ile bir geçici dizine çekin, aynı PRAGMA integrity_check komutunu çalıştırın, satır sayılarını kontrol edin ve ardından tarih ile satır sayılarını not edin. Altı aydır geri yüklenmemiş bir yedek, durumu bilinmeyen bir yedektir; bu durumun ne olduğunu bir kesinti anında öğrenmek, öğrenilebilecek en kötü zamandır.

Yılda bir kez tam kapsamlı testi gerçekleştirin. Geri yüklenen veri klasörüyle ikinci bir Vaultwarden container'ını boş bir port üzerinde başlatın ve gerçek bir hesapla giriş yapın. Bu işlem, hiçbir satır sayımı işleminin kanıtlayamayacağı şekilde, ana parola yolunun uçtan uca çalıştığını doğrular. Aynı takvim dahilinde restic check --read-data-subset=10% komutunu çalıştırmak, depolanan verilerin yalnızca listelenmekle kalmayıp aynı zamanda okunabilir olduğunu da doğrular.

FAQ

Vaultwarden çalışırken db.sqlite3 dosyasını cp ile kopyalayabilir miyim?

Hayır. Vaultwarden, SQLite'ı WAL modunda çalıştırır; bu nedenle son yazma işlemleri db.sqlite3-wal içinde tutulur ve henüz db.sqlite3 dosyasına aktarılmamıştır. Sadece ana dosyanın cp alınması bu verilerin sessizce kaybolmasına neden olur. İki dosyayı ayrı ayrı kopyalamak ise daha sonra Error: database disk image is malformed hatası olarak ortaya çıkabilecek uyumsuz bir çift oluşturabilir. Bunun yerine sqlite3 /path/db.sqlite3 ".backup '/path/out.sqlite3'" kullanın. Bu araç, SQLite'ın Online Backup API'sini kullanır ve sunucu hizmet vermeye devam ederken tutarlı tek bir dosya üretir.

Yedek almak için Vaultwarden container'ını durdurmam gerekir mi?

Hayır, .backup kullanımının amacı da budur. Veritabanı kopyası, çalışan bir sunucuda güvenlidir. Ekler ve gönderilen dosyalar kullanıcı yükleme yaptığında yazılır; bu nedenle veritabanı kopyası ile tar işlemi arasında eklenen bir dosya o gecenin arşivinde yer almayabilir. Bu durum en kötü ihtimalle bir ekin eksik kalmasına neden olur. Birkaç saniyelik kesinti sizin için sorun değilse, betikten önce docker compose stop ve sonrasında docker compose start komutlarını çalıştırmak bu riski de ortadan kaldırır.

rsa_key dosyaları olmadan geri yükleme yaparsam ne olur?

Vaultwarden başlangıçta yeni bir anahtar oluşturur. Bu anahtar, oturumları canlı tutan JSON web token (JWT) verilerini imzalar; bu nedenle mevcut tüm token'ların geçerliliği biter, tüm istemcilerin oturumu kapatılır ve tekrar giriş yapmaları gerekir. Kasa içerikleri etkilenmez çünkü bunlar RSA anahtarı ile değil, her kullanıcının ana parolasından türetilen anahtarlarla şifrelenmiştir. rsa_key.pem dosyalarını veri klasörünün geri kalanıyla birlikte geri yüklerseniz, kimse geri yükleme yapıldığını fark etmez.

Yedek arşivini olduğu gibi nesne depolama alanına yüklemek güvenli midir?

Hayır. Öğe adları, parolalar ve notlar şifreli metin halindedir; ancak e-posta adresleri, hesap adları, parola ipuçları ve iki faktörlü kurtarma kodları veritabanında düz metin olarak bulunur. Çevrimdışı bir saldırgan, şifreli metni kendi hızında kırmaya çalışabilir. Arşivi sunucudan çıkarmadan önce şifreleyin. Bir restic deposu bunu sizin yerinize yapar; gpg --symmetric --cipher-algo AES256 vw-20260805-030000.tar.gz ise herhangi bir depolama alanına gönderebileceğiniz tek bir şifreli dosya üretir.

PostgreSQL veya MariaDB üzerinde çalışan Vaultwarden'ı nasıl yedeklerim?

SQLite adımları burada geçerli değildir ve yerleşik komut The database type is not SQLite. Backups only works for SQLite databases hatası vererek çalışmayı reddeder. Veritabanını kendi yerel aracı olan pg_dump veya mysqldump ile döküm (dump) alarak yedekleyin ve diğer tüm kuralları aynı şekilde uygulayın. Döküm dosyası; attachments/, sends/, config.json ve rsa_key dosyalarıyla aynı arşiv içinde, aynı çalışma zamanında alınmalı, şifrelenmeli ve oluşturulduğu sunucudan farklı bir yerde saklanmalıdır.