Safeguard
Supply Chain Security•

Self-Hosted Password Managers: Encryption, Sync, Backups and Risks

A self-hosted password manager keeps the encrypted vault on your server. How vault encryption and sync work, what you now own, and how to run one safely.

Safeguard Security Team
Updated 45 min read

A self-hosted password manager is one where the sync server, or the vault file itself, lives on hardware you control instead of a vendor's cloud. The cryptography barely changes: your devices still derive a key from your master password with a slow function such as PBKDF2 or Argon2id and encrypt the vault before it leaves them. What changes is who runs the server, and with it who owns TLS, updates, backups, uptime and the admin page.

That trade is worth making for some people and a bad idea for others. This post explains how vault encryption actually works, how a self-hosted sync server differs from a hosted service and from an offline file vault, what NIST SP 800-63B rev 4 says about password managers and synced passkeys, what the new FIDO Credential Exchange specifications promise for moving your data, and how to stand up a sync server behind a reverse proxy with automatic updates, tested backups and an emergency plan. It goes one level deeper than our guides on replacing Google services one by one, whether it is safe to self-host apps on the internet and choosing between a browser password manager and a standalone one.

Key takeaways

  • The vault is encrypted on your device, not on the server. Hosted, self-hosted and file based managers all derive a key from the master password with a slow, salted function and encrypt locally. The server sees ciphertext plus metadata.
  • KDF settings matter more than the hosting model. RFC 9106 (September 2021) recommends Argon2id with 2 GiB and one pass, or 64 MiB and three passes for constrained devices. OWASP's floor is Argon2id with 19 MiB, two passes and one lane, or PBKDF2-HMAC-SHA256 with 600,000 iterations where FIPS-140 is required.
  • Self-hosting moves operational risk to you. TLS, image updates, the reverse proxy, the admin page, backups, restore tests and uptime are now yours. A stale image or an exposed admin page is a bigger day to day risk than the cipher.
  • Your server also serves the web vault code. A compromised server can alter the JavaScript it sends to browsers. Native apps and store-installed extensions do not load code from your server.
  • NIST SP 800-63B-4 (July 2025) is pro password manager. Verifiers "SHALL allow the use of password managers and autofill functionality". Synced passkeys are allowed up to AAL2 if the sync fabric encrypts keys and requires AAL2 equivalent multi-factor authentication, never at AAL3.
  • Passkeys are just another encrypted vault item. Support depends on the client apps, not the server. WebAuthn Level 3 became a W3C Recommendation on 25 August 2026.
  • Portability is getting a standard. The FIDO Credential Exchange Format (CXF) is a Proposed Standard (errata dated 9 March 2026); the Credential Exchange Protocol (CXP) was still a Working Draft dated 3 October 2024 when we checked.
  • Backups are the whole game. Use SQLite's online backup method, keep attachments, keep an encrypted copy off the server, and rehearse restores.

How does a password manager encrypt a vault?

Every serious password manager, whatever the hosting model, follows the same broad pattern. The details differ by product, so treat this as the architecture to look for in the documentation of whatever you use.

Step 1: stretch the master password into a key

A master password is a low entropy secret. Even a good one carries far fewer bits than a 256-bit AES key. So the client never uses it directly. It runs it through a password based key derivation function (KDF) with a random salt and a cost setting.

RFC 8018, the January 2017 PKCS #5 v2.1 document that defines PBKDF2, puts the point of the iteration count plainly: an iteration count of c "will increase the security strength of a password by log2(c) bits against trial-based attacks like brute force or dictionary attacks." It quotes NIST SP 800-132 (December 2010), which recommends choosing the iteration count "as large as possible, as long as the time required to generate the key using the entered password is acceptable for the users", with a minimum of 1,000 and up to 10,000,000 for especially critical keys.

PBKDF2 is cheap in memory. That is its weakness against attackers with GPUs or custom hardware, who can run thousands of PBKDF2 instances in parallel. Argon2, the winner of the Password Hashing Competition and standardised as RFC 9106 by the IRTF's Crypto Forum Research Group in September 2021, adds a memory cost. Each guess has to fill and revisit a large block of memory, so parallel hardware runs out of memory long before it runs out of compute.

RFC 9106 defines three variants. Argon2d uses data dependent memory access and gives the best resistance to GPU cracking. Argon2i uses data independent access to resist side channels. Argon2id mixes the two. The RFC's recommendation section says Argon2id with t=1 and 2 GiB of memory is the "FIRST RECOMMENDED option", and Argon2id with t=3 and 64 MiB is the "SECOND RECOMMENDED option" for memory constrained environments, both with four lanes, a 128-bit salt and a 256-bit tag.

Step 2: derive separate keys for separate jobs

From the stretched key, a sync based client typically derives two things:

  1. An encryption key (or a key that unwraps one) that never leaves the device.
  2. An authentication value, a hash derived from the stretched key, that the client sends to the server to prove it knows the master password without sending the password itself.

The server then hashes that authentication value again before storing it, so a stolen server database does not hand an attacker a login token directly. Vaultwarden's configuration template shows this server side layer: its PASSWORD_ITERATIONS setting is the "number of server-side passwords hashing iterations for the password hash", with a default of 600,000.

Step 3: encrypt the vault with a random key

The vault itself is usually encrypted with a random symmetric key, generated on the device from a cryptographically secure random number generator, and that random key is then wrapped (encrypted) with the key derived from the master password. Changing the master password only rewraps the vault key; it does not re-encrypt every item. If you want to understand why the random number generator matters so much here, our explainers on CSPRNGs and /dev/random versus /dev/urandom cover it.

File vaults do the same thing in a single file. KeePass documents its scheme in detail: the components of the master key (a master password, a key file, a Windows user account key or a plugin provided key) are compressed with SHA-256 into a 256-bit key, which is then transformed with a KDF and a random salt. The vault is encrypted with AES-256 or ChaCha20 (RFC 8439) in KeePass 2.x, a fresh initialisation vector is generated every time the database is saved, and integrity is protected with HMAC-SHA-256 over the ciphertext, an encrypt then MAC design.

What "zero knowledge" really means

In password manager marketing, "zero knowledge" is not the cryptographic term of art. It means the provider never sees your master password or vault key, so it cannot decrypt your items. The server can still see your account email, login times, IP addresses, device names, item counts and sizes, and in some designs fields such as website URLs if the product leaves them unencrypted. Look for an explicit list of encrypted fields in your client's security documentation. When you self-host, the question becomes who else can read your server's logs and backups.

The KDF table you actually need

KDF and settingMemory per guessWhere it comes fromNotes
PBKDF2-HMAC-SHA256, 600,000 iterationsNegligibleOWASP Password Storage Cheat SheetOWASP's figure when FIPS-140 compliance is required
PBKDF2-HMAC-SHA512, 220,000 iterationsNegligibleOWASPEquivalent cost target with SHA-512
PBKDF2-HMAC-SHA1, 1,400,000 iterationsNegligibleOWASPOWASP labels this legacy only
Argon2id, m=19 MiB, t=2, p=119 MiBOWASP minimumThe floor, not a target
Argon2id, m=64 MiB, t=3, p=464 MiBRFC 9106 second recommended optionVaultwarden's docs give these as the compatible clients' defaults
Argon2id, m=2 GiB, t=1, p=42 GiBRFC 9106 first recommended optionToo heavy for most phones and browser extensions
Argon2d, min(M/2, 1 GB), t=2 or moreUp to 1 GBKeePass security pageKeePass recommends Argon2d for local files
AES-KDF, iterations tuned to about 1 secondNegligibleKeePass and KeePassXCOnly KDF in KDBX 3.1; prefer Argon2 in KDBX 4

Worked example 1: how much a good master passphrase buys you

Suppose you generate a master passphrase of six words, each picked at random from a list of 7,776 words (six to the fifth power, so five dice rolls choose a word). Each word adds log2(7,776), about 12.92 bits. Six words give about 77.5 bits, or roughly 2.1 × 10^23 possible passphrases.

Assume, purely for illustration, that an attacker with your encrypted vault can test 10,000 guesses per second against a memory hard Argon2id setting. The whole space takes about 2.1 × 10^19 seconds, roughly 6.7 × 10^11 years. Even a thousand times faster, it is still about 670 million years.

An eight character lowercase password has 26^8, about 2.1 × 10^11, possibilities. At the same assumed rate the full space falls in about 2.1 × 10^7 seconds, about 242 days, and much sooner at GPU speeds against a cheap KDF.

The KDF multiplies the cost of each guess; the passphrase sets the number of guesses. You need both. KeePassXC's command line tool can generate one for you with keepassxc-cli diceware, whose default is seven words.

Worked example 2: what an iteration count is worth in bits

RFC 8018's rule of thumb gives a simple way to compare PBKDF2 settings. log2(600,000) is about 19.2, so 600,000 iterations add roughly 19 bits of work to every guess compared with a single hash. The old SP 800-132 minimum of 1,000 iterations adds about 10 bits. Going from 100,000 to 600,000 iterations adds only log2(6), about 2.6 bits.

That is why raising an iteration count gives diminishing returns and why memory hard functions exist. Memory cost hurts the attacker more than the defender: a GPU card with 24 GiB of memory can hold at most 384 simultaneous Argon2id instances at 64 MiB each, while it could run vastly more PBKDF2 instances at once.

Hosted, self-hosted or offline file: what changes?

There are three common models.

  1. Hosted sync service. A company runs the sync server, web vault and accounts, and handles uptime, TLS, backups and server security.
  2. Self-hosted sync server. You run a server that speaks the same sync protocol, and point the official or compatible clients at your domain. Vaultwarden is the best known open source example: its README describes it as an alternative server implementation of a widely used commercial manager's client API, written in Rust and licensed under AGPL-3.0, and states that it is not associated with that company. Some commercial managers also offer their own self-hostable server.
  3. Offline file vault. There is no sync server at all. The vault is one encrypted file, such as a KeePass KDBX file, and you move it between devices yourself or with a file sync tool. KeePassXC's guide says you "can safely store your database file in the cloud" because the file is always fully encrypted.
QuestionHosted sync serviceSelf-hosted sync serverOffline file vault (KDBX)
Who holds the ciphertextThe providerYouYou, plus whatever file sync you use
Who runs TLS and the web vaultThe providerYouNot applicable
Who patches the serverThe providerYouNot applicable; you patch the desktop and mobile apps
Account recovery if you forget the master passwordUsually none for the vault itself; some offer admin or trusted contact recoverySame client features, if your server supports themNone
Sharing with family or a teamBuilt inBuilt in if the server implements organisationsLimited; KeePassXC KeeShare shares groups as separate files
Conflict handlingServer resolves per itemServer resolves per itemFile level; you merge copies
Metadata exposureTo the providerTo you and your hostTo your file sync provider (file size, timestamps)
EffortLowestHighestLow to medium
Biggest operational riskProvider breach or outageYour patching, backups and exposureSync conflicts and lost copies

When self-hosting is the right call

Self-hosting a sync server makes sense when you already run a small server reliably, when you want family or team sharing without a subscription, when data residency rules require the ciphertext to stay on your hardware, or when you want to keep the server reachable only on a private network or VPN. It also suits people replacing other cloud services at the same time, as in our guide to exporting your data from Google and Apple.

It is the wrong call if nobody will notice when backups stop or the server will sit unpatched for months. A file vault is then often the better self-managed option: there is no server to attack.

The web vault problem

There is one risk that is easy to miss. A sync server usually also serves a browser based web vault. Vaultwarden's README notes that the web vault needs HTTPS and a secure context for the Web Crypto API, and Vaultwarden bundles a modified web vault in its containers. When you log into a web vault, the decryption code your browser runs was just delivered by the server.

That means server compromise is not only a ciphertext leak. An attacker who controls your server, or your reverse proxy, could serve altered JavaScript that captures the master password the next time someone logs in through the browser. Native desktop and mobile apps and browser extensions installed from their official stores do not take their code from your server, so they are not exposed to that specific attack. Use them for daily work, treat the web vault as an occasional tool, and protect the server as if it held the passwords, because in practice it can get them.

What do you now own when you self-host?

Self-hosting replaces one provider's security team with you. Here is the full list, with the controls the Vaultwarden documentation itself recommends.

TLS and the reverse proxy

You need HTTPS. Vaultwarden's hardening guide advises against its built-in Rocket TLS for public instances and quotes Rocket's own warning that its built-in TLS "is not considered ready for production use". The project recommends a reverse proxy such as Caddy or nginx. Caddy's automatic HTTPS provisions certificates for public DNS names from an ACME certificate authority such as Let's Encrypt, keeps them renewed, and redirects port 80 to 443 automatically, which removes a whole class of expired certificate outages.

The hardening guide also notes a log hygiene issue: real time notifications use a WebSocket request that carries the user's JWT in an access_token query parameter, so if your proxy writes access logs or ships them to a log service, redact that parameter.

The admin page

Vaultwarden's /admin page can view and delete all users and organisations, invite users even when registration is off, and change configuration. It is enabled by setting ADMIN_TOKEN, which the project says to hash with Argon2id as a PHC string and to use only over HTTPS. An admin session is a JWT lasting 20 minutes by default, and changing the token does not end existing sessions; you rotate rsa_key.pem and restart for that. The wiki's Caddy example includes an optional rule allowing /admin only from private address ranges.

Registration, hints and brute force

By default, anyone who can reach a Vaultwarden instance can register. The hardening guide recommends SIGNUPS_ALLOWED=false once your users exist, and warns that showing password hints on the login page, which happens when SMTP is not configured, could help password guessing; SHOW_PASSWORD_HINT=false stops it. The configuration template includes login and admin rate limits (by default an average of one login attempt every 60 seconds with bursts of 10, and one admin attempt every 300 seconds with bursts of 3), and the wiki documents a fail2ban setup. Rate limits key on the client IP, so IP_HEADER and IP_HEADER_TRUSTED_PROXIES must match your proxy or every request will appear to come from the proxy.

Updates and image hygiene

The Vaultwarden container image tags explain the trade-off. latest tracks released versions and is "recommended for most users"; testing tracks the latest commits; versioned tags such as 1.37.4 pin a release. The project also warns that because upstream controls the client releases, and mobile apps and browser extensions update themselves, Vaultwarden users need to keep up with server releases or risk incompatibilities. The latest release when we checked on 23 October 2026 was 1.37.4, published on 5 October 2026.

So you need an update process, not just an install. More on that in the walkthrough.

Backups, restore tests and uptime

The Vaultwarden backup guide is specific about what matters:

ItemBackupWhy
db.sqlite3 (or a MySQL or PostgreSQL dump)RequiredHolds almost all vault data and user, organisation and device metadata
attachments/RequiredFile attachments are stored outside the database
config.jsonRecommendedSettings made in the admin page; contains plaintext secrets such as the admin token and SMTP credentials, so encrypt the backup
rsa_key* filesRecommendedSign login tokens; losing them logs everyone out and invalidates open invitations
sends/OptionalEphemeral Send attachments
icon_cache/OptionalWebsite icons, refetched as needed

The guide recommends at least one remote copy, a daily automated job, and warns against relying on filesystem or VM snapshots alone. For the database it recommends SQLite's .backup command, which uses the SQLite Online Backup API, or VACUUM INTO, and since version 1.32.1 Vaultwarden has a built in backup command.

Uptime matters less than people expect, and more at the worst moment. Many sync clients keep an encrypted local copy, so a short outage usually blocks syncing and new device logins rather than all access. Test how your clients behave offline; the day you need a new device login is often the day your old device was lost.

How do passkeys fit in a self-hosted manager?

A passkey is a WebAuthn credential: a key pair created by an authenticator for one website, where the site stores only the public key. WebAuthn Level 3, which became a W3C Recommendation on 25 August 2026, defines the vocabulary. A credential source that is allowed to be backed up is "backup eligible", and the spec calls it a multi-device credential, "commonly referred to as synced passkeys". One that cannot be backed up is a single-device credential, commonly a device-bound passkey. Backup eligibility is fixed when the credential is created; the separate backup state flag can change over time. The FIDO Alliance's passkeys page describes the same split: passkeys "can be securely synced across a user's devices, or bound to a particular device". For the protocol itself, see our explainer on how passkeys work and why they resist phishing.

In a sync based password manager, a synced passkey is just another vault item. The private key is stored inside the encrypted vault, and the client performs the WebAuthn signature on your device. That has three consequences for self-hosting:

  1. Support comes from the clients, not the server. The sync server stores an encrypted blob. Whether you can create, use or export passkeys depends on the apps and extensions you install. Vaultwarden lists FIDO2 WebAuthn as a supported two-factor method for logging into the vault itself, which is a different feature from storing passkeys inside it.
  2. Your server becomes a sync fabric in NIST's terms. That raises the bar for how you protect access to it, covered in the NIST section below.
  3. File vaults can do it too. KeePassXC supports passkeys through its browser extension and a connected database, stored inside the KDBX file.

What CXP and CXF promise for portability

Until recently, moving a vault between managers meant an unencrypted CSV or JSON export, and passkeys often could not be exported at all. KeePassXC's own guide warns that its exports store everything "in an unencrypted format". The FIDO Alliance is standardising a better path in two documents:

  • Credential Exchange Format (CXF). It "defines the data structures and format of credentials" passed between two applications. Version 1.0 is a FIDO Proposed Standard, with an errata version dated 9 March 2026. Its credential types go well beyond passwords: addresses, API keys, basic username and password pairs, credit cards, custom fields, driver's licences, files, generated passwords, identity documents, notes, passkeys (with FIDO2 extensions such as hmac-secret credentials and large blobs), passports, person names, SSH keys, TOTP seeds and Wi-Fi passphrases.
  • Credential Exchange Protocol (CXP). It "defines a protocol to securely move one or more credentials between two credential providing applications" on the same or separate devices. The importer supplies a public key, the exporter encrypts the payload to it using HPKE with Diffie-Hellman key agreement, so the data is never written out in the clear. The version published on the FIDO download page is a Working Draft dated 3 October 2024.

The FIDO download page still says both specifications are "currently in early review draft", which is out of step with CXF's Proposed Standard status. Treat CXF as close to stable and CXP as still moving. Once your clients support CXP, you should be able to move every credential type, passkeys included, between hosted, self-hosted and file vaults without a plaintext file touching disk. Until then, any export is the most sensitive file on your computer.

What did NIST SP 800-63B rev 4 say about password managers and passkeys?

NIST published SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management, in July 2025 (the CSRC record lists the final on 31 July 2025). It supersedes SP 800-63B. It is written for US federal agencies, but its rules on passwords have shaped practice far beyond government. The parts relevant to password managers:

TopicWhat SP 800-63B-4 says
Password managersVerifiers "SHALL allow the use of password managers and autofill functionality" and "SHOULD permit" paste
WhyPassword managers "have been shown to increase the likelihood that subscribers will choose stronger passwords", especially with generators
Minimum length15 characters when a password is the only factor; at least 8 when it is part of multi-factor authentication
Maximum lengthVerifiers SHOULD permit at least 64 characters
Composition rulesSHALL NOT be imposed beyond the blocklist
Periodic changesSHALL NOT be required; a change SHALL be forced on evidence of compromise
BlocklistNew passwords SHALL be checked against commonly used, expected or compromised values
StorageSalted and hashed with a suitable scheme; salt of at least 32 bits; cost factor as high as practical and raised over time
Evaluating managersAgencies "should carefully evaluate password managers" before recommending or mandating them
Threat noted"A vulnerability in an insufficiently secure password manager is exploited" is listed as a threat to password authenticators

Syncable authenticators (Appendix B)

Appendix B is new territory for NIST. It treats synced passkeys as "syncable authenticators" and the place they sync through as a "sync fabric", for example a cloud provider. The requirements:

  • Keys exported to a sync fabric SHALL be stored only in encrypted form, with a key of at least 112 bits of security strength (the SP 800-131A minimum as of publication), and SHOULD be encrypted with a method that uses a user-controlled secret.
  • All private key operations SHALL happen on the local device.
  • Keys in the sync fabric SHALL be protected so that only the authenticated user can reach them, and user access to the sync fabric SHALL be protected by AAL2 equivalent multi-factor authentication.
  • Syncable authenticators SHALL NOT be used at AAL3, because their keys are exportable by design.
  • Authenticators that sync SHOULD offer a UI showing which services have a syncable key and where it has been synced, without exposing the key.
  • Verifiers SHOULD check the WebAuthn User Present flag, SHALL prefer and check User Verified, and MAY use Backup Eligible to restrict synced credentials.

For a self-hoster, the practical reading is clear. Your self-hosted vault server is a sync fabric if it holds passkeys or TOTP seeds. Turn on two-factor authentication for every account on it, prefer a phishing resistant second factor, and keep the master password as the user-controlled secret that encrypts the vault. NIST also lets a software OTP authenticator's secret be moved to a new device through a sync fabric that meets Appendix B.2, which is effectively what a password manager holding your TOTP seeds does.

Local versus central verification

NIST's Appendix A notes that central verifiers are attractive targets because one breach exposes everyone, while local verifiers "depend on the physical security of the authenticator and the integrity of its associated endpoint". A file vault removes the central target; no model protects you from a compromised laptop.

How do you set up a self-hosted sync server, step by step?

This walkthrough runs Vaultwarden rootless under Podman with a systemd Quadlet unit, Caddy on the host as the TLS reverse proxy, automatic image updates, and encrypted off-site backups with restic. It assumes a small Linux server or VM (Debian or Ubuntu style package names), a DNS name such as vault.example.com pointing at it, and ports 80 and 443 open to Caddy. Adapt names and paths to your setup. If you prefer Docker Compose, the same environment variables apply; the Vaultwarden wiki notes that every $ in an Argon2 PHC string must be written as $$ in a Compose file.

Step 1: decide who can reach it

Decide first whether the vault should be on the public internet at all. If every user is on known devices, a VPN or private overlay network removes the public login page entirely, the most effective single hardening step.

Step 2: install Podman, Caddy and the tools

sudo apt update
sudo apt install -y podman caddy sqlite3 restic argon2
podman --version
caddy version

Create an unprivileged user to own the service, and let its user services run without an active login:

sudo useradd --create-home --shell /bin/bash vault
sudo loginctl enable-linger vault
sudo -iu vault
mkdir -p ~/vw-data ~/.config/containers/systemd ~/.config/vaultwarden

Step 3: create a hashed admin token, or skip the admin page

If you do not need the admin page, do not set an admin token at all; Vaultwarden disables /admin when neither ADMIN_TOKEN nor DISABLE_ADMIN_TOKEN is set. If you do want it, generate a long random password, store it in your vault, and hash it with Argon2id. The Vaultwarden docs show the argon2 command line tool with the 64 MiB, three pass, four lane settings:

# Generate a random admin password and keep it in your password manager
openssl rand -base64 32
# Hash it (type the password between the quotes; leading space keeps it out of shell history in many shells)
 echo -n 'PASTE-THE-RANDOM-PASSWORD' | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4

The output is a PHC string starting with $argon2id$v=19$m=65540,t=3,p=4$. Alternatively, run podman run --rm -it docker.io/vaultwarden/server:1.37.4 /vaultwarden hash, which prompts twice and prints the same kind of string.

Step 4: write the environment file

An environment file avoids shell and systemd quoting problems with the $ characters in the PHC string.

cat > ~/.config/vaultwarden/vaultwarden.env <<'EOF'
DOMAIN=https://vault.example.com
SIGNUPS_ALLOWED=true
SHOW_PASSWORD_HINT=false
ADMIN_TOKEN=$argon2id$v=19$m=65540,t=3,p=4$REPLACE-WITH-YOUR-PHC-STRING
IP_HEADER=X-Real-IP
IP_HEADER_TRUSTED_PROXIES=local
LOGIN_RATELIMIT_SECONDS=60
LOGIN_RATELIMIT_MAX_BURST=10
EOF
chmod 600 ~/.config/vaultwarden/vaultwarden.env

SIGNUPS_ALLOWED=true is only for the first few minutes, while you create accounts. You will turn it off in Step 8.

Step 5: define the container as a Quadlet unit with automatic updates

# ~/.config/containers/systemd/vaultwarden.container
[Unit]
Description=Vaultwarden password sync server

[Container]
ContainerName=vaultwarden
Image=docker.io/vaultwarden/server:latest
AutoUpdate=registry
EnvironmentFile=%h/.config/vaultwarden/vaultwarden.env
Volume=%h/vw-data:/data:Z
PublishPort=127.0.0.1:8080:80
NoNewPrivileges=true

[Service]
Restart=always

[Install]
WantedBy=default.target

The container listens only on the loopback interface; Caddy is the only thing exposed. AutoUpdate=registry tells Podman to check the registry for a newer image behind the same fully qualified reference. Podman's documentation says the registry policy needs a fully qualified image reference, that podman-auto-update.service is triggered daily at midnight by podman-auto-update.timer, and that --rollback, on by default, returns to the previous image if the restarted unit fails.

The tag choice is a policy decision. latest plus auto-update gives you server releases within a day, which the Vaultwarden docs encourage because clients update themselves. A pinned tag such as 1.37.4 plus auto-update only picks up rebuilds of that exact tag, so you must bump the tag yourself, but you control the timing. Pick one deliberately and write it down.

systemctl --user daemon-reload
systemctl --user start vaultwarden.service
systemctl --user status vaultwarden.service --no-pager
curl -sI http://127.0.0.1:8080/ | head -3
systemctl --user enable --now podman-auto-update.timer
podman auto-update --dry-run

Step 6: put Caddy in front

Exit back to your admin user and edit /etc/caddy/Caddyfile:

vault.example.com {
    @admin {
        path /admin*
        not remote_ip private_ranges
    }
    respond @admin 403

    header {
        Strict-Transport-Security "max-age=31536000;"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "same-origin"
        -Server
    }

    log {
        output file /var/log/caddy/vault.log
    }

    reverse_proxy 127.0.0.1:8080 {
        header_up X-Real-IP {remote_host}
    }
}
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -sI https://vault.example.com/ | head -5

Caddy obtains and renews the certificate on its own. Its reverse proxy passes WebSocket upgrades through, which the clients use for live sync notifications. If you keep access logs, filter or redact the access_token query parameter on /notifications/hub requests before logs leave the box. Do not add X-Frame-Options: DENY without testing; the Vaultwarden proxy example warns that FIDO2 WebAuthn needs SAMEORIGIN.

Step 7: create accounts and turn on two-factor authentication

Create the accounts you need from a trusted device and enable two-factor authentication on each, preferably a FIDO2 WebAuthn security key or passkey, with the recovery code saved offline. Point the apps and extensions at your server URL in their self-hosted server settings. Then check each account's KDF settings: Argon2id at 64 MiB or more where every device can handle it, or at least the OWASP floors.

Step 8: close registration

sudo -iu vault
sed -i 's/^SIGNUPS_ALLOWED=true/SIGNUPS_ALLOWED=false/' ~/.config/vaultwarden/vaultwarden.env
systemctl --user restart vaultwarden.service

From outside your network, confirm that registration is refused and that https://vault.example.com/admin returns 403.

Step 9: back up the database and files every day

Back up with SQLite's online backup method so you never copy a half written database.

# As the vault user
mkdir -p ~/vw-backup
sqlite3 ~/vw-data/db.sqlite3 ".backup '/home/vault/vw-backup/db.sqlite3'"
sqlite3 ~/vw-backup/db.sqlite3 "PRAGMA integrity_check;"

Then push the database copy, attachments, config.json and the rsa_key* files to an encrypted restic repository on another machine. restic encrypts everything with AES-256 in counter mode and authenticates it with Poly1305-AES, deriving its keys from the repository password with scrypt. Its documentation is blunt that "losing your password means that your data is irrecoverably lost", so store the restic password in a place that does not depend on this server, such as the paper emergency kit described below.

export RESTIC_REPOSITORY=sftp:backup@nas.example.lan:/srv/restic/vaultwarden
export RESTIC_PASSWORD_FILE=/home/vault/.config/vaultwarden/restic.pass
restic init            # first time only
restic backup /home/vault/vw-backup /home/vault/vw-data/attachments \
  /home/vault/vw-data/config.json /home/vault/vw-data/rsa_key.pem
restic snapshots
restic check --read-data-subset=5%

Retention prunes old snapshots. Warning: forget --prune permanently deletes snapshot data. Before running it, list what you have and confirm the repository path is the one you mean.

echo "$RESTIC_REPOSITORY"
restic snapshots --compact
restic forget --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --prune

Run the backup daily from a systemd user timer or cron, and add a monthly offline copy on an encrypted USB drive kept elsewhere.

Step 10: rehearse a restore, on a different machine

A restore you have not rehearsed will fail at the worst time. Restore to a fresh directory, never over the live data folder.

Warning: a restore into the live data directory overwrites the vault. Check the target path first.

TARGET=/tmp/vw-restore-test
echo "Restoring into: $TARGET"
test ! -e "$TARGET" && mkdir -p "$TARGET"
restic restore latest --target "$TARGET"
sqlite3 "$TARGET/home/vault/vw-backup/db.sqlite3" "PRAGMA integrity_check;"

Then run the same image on a scratch VM against the restored folder, log in with a test account, open a few items and an attachment, and note how long it took. That is your real recovery time.

Step 11: monitor the boring things

  • Certificate expiry and the HTTP status of https://vault.example.com/ from outside your network.
  • The date of the newest restic snapshot; alert if it is older than two days.
  • The result of the nightly podman auto-update run (journalctl --user -u podman-auto-update.service).
  • Disk space on the data and backup volumes.
  • Vaultwarden release notes, so you know when an update is a security fix.

The file vault alternative in five commands

If you decide a server is not worth it, a KeePass format vault with Argon2 and a key file is a strong self-managed option. KeePassXC's command line tool documents these commands:

keepassxc-cli diceware -W 7                  # generate a seven word master passphrase
keepassxc-cli db-create --set-password --set-key-file ~/vault.keyx -t 1000 ~/vault.kdbx
keepassxc-cli db-info ~/vault.kdbx --key-file ~/vault.keyx
cp ~/vault.kdbx ~/vault-$(date +%F).kdbx   # dated copy before any merge
keepassxc-cli merge ~/vault.kdbx ~/Sync/vault-phone.kdbx

The -t 1000 option sets a target decryption time of 1,000 ms. KeePassXC recommends about one second and notes that phones can take two to four times longer than a desktop. merge replaces the first database with the merged result, and the KeePassXC manual advises keeping a backup of both files first, which is what the dated copy is for. Keep the key file off the cloud folder that syncs the vault, or it stops being a second factor.

KeePass's Argon2 guidance: iterations 2, memory the smaller of half the RAM of your weakest device and 1 GB (its example pairs a 32 GB PC with a 1 GB phone and lands on 500 MB), parallelism the smallest logical processor count among your devices, then test. On iOS it suggests 64 MB or less, because a large memory setting can stop AutoFill working. KeePass prefers Argon2d for local files, since GPU resistance matters more than side channels on a client; RFC 9106 and OWASP recommend Argon2id, the safer choice for anything on a server.

How should backups and emergency access work for a family or small team?

The cryptography protects you from strangers. It also protects your vault from your family if something happens to you. Plan for both.

Three layers of backup

  1. Server level backup. The nightly database, attachments and configuration copy described above. It restores the service.
  2. Vault level export. Every few months, each person makes an encrypted export from their client, or once your apps support it, a CXP transfer into a file vault. It restores the passwords if the server software itself becomes unusable.
  3. Paper emergency kit. A printed sheet per person with the server URL, the account email, the two-factor recovery code and a pointer to where the master password is kept. Seal it and store it somewhere safe and separate, such as a home safe or with a solicitor.

Never keep an unencrypted CSV export. If you must create one to move vaults, do it on an offline machine, import it, and securely delete it the same day.

Emergency access

Vaultwarden implements the emergency access feature of the compatible clients, and its configuration includes jobs that remind grantors and that grant requests once the required wait time has passed. You nominate a trusted contact and a waiting period; if the contact requests access and you do not reject it in time, access is granted. It depends on your server running, and invitations go out by email, so configure outgoing mail. Treat it as a complement to the paper kit, not a replacement.

For a small team, at least two people must be able to administer and restore the server, and both must have rehearsed it. A vault whose only administrator is unreachable is a single point of failure for the company.

Emergency access decision table

SituationWhat gets you back in
Server disk failureRestore last night's restic snapshot to a new host
Server compromisedRebuild from a known good image, restore data, rotate the admin token and rsa_key files, and change the master password and important credentials
One person forgets their master passwordNothing can decrypt their vault; use their last export only if it is protected by a different secret they still know, or a team owner re-shares shared items
Account holder incapacitatedEmergency access contact, or the sealed paper kit
Server administrator unavailableSecond administrator with rehearsed restore steps
Self-hosting abandonedEncrypted export or CXP transfer into a hosted manager or a KDBX file

Common mistakes

  • A weak master password with a strong KDF. Argon2id multiplies the cost of each guess; it cannot rescue a password that is in every cracking dictionary. Use a generated passphrase of six or more random words.
  • Leaving old KDF settings in place. Accounts created years ago may still use a low PBKDF2 count. Check every account's settings after setting up and after major client updates.
  • Exposing the admin page to the internet. Restrict /admin to private ranges or a VPN, hash the token, or leave the admin page disabled.
  • Leaving registration open. Anyone who finds the URL can create an account and use your storage and bandwidth. Turn SIGNUPS_ALLOWED off after setup.
  • Running a stale image. A container that was never updated keeps every vulnerability it shipped with, and new client versions may stop working with it. Automate updates or put a recurring reminder in a calendar you actually read.
  • Snapshots instead of backups. A VM snapshot on the same host dies with the host and may capture a database mid write. Use SQLite's backup method and copy off the box.
  • Never testing a restore. Many people find out their backup excluded the attachments folder on the day they need it.
  • Storing the backup password next to the data it protects. Keep recovery secrets in the paper kit, not on the server.
  • Using the web vault for daily work. It runs code served by your server.
  • Trusting client IP headers from anywhere. Attackers can then dodge rate limits. Trust only your own proxy.
  • Leaving plaintext exports lying around. An old CSV export in a downloads folder undoes every other control here.

FAQ

Is a self-hosted password manager safer than a hosted one?

Not automatically. The vault encryption is the same, so the difference is operational. A hosted provider is a bigger target with a security team and tested backups; a self-hosted server is a smaller target that depends entirely on your patching, access restrictions and backups.

Can the server owner read my passwords?

Not directly. Items are encrypted on your device and the server stores ciphertext, but it sees metadata such as your email, login times, IP addresses and item counts. A malicious or compromised server could serve altered web vault code that captures your master password, so prefer native apps.

What KDF settings should I use for my password manager?

Use Argon2id where every client you use supports it. RFC 9106 suggests 64 MiB and three passes for memory constrained environments and 2 GiB with one pass where memory allows; OWASP's minimum is 19 MiB, two passes and one lane. If you are stuck with PBKDF2-HMAC-SHA256, OWASP recommends at least 600,000 iterations. For KeePass files, use Argon2 and tune it to about one second on your slowest device.

What happens if I forget my master password?

For a properly designed vault, nobody can decrypt it, including the server operator. You are limited to what you set up beforehand: an emergency access contact, an organisation owner who can re-share shared items, or a sealed paper kit.

Can I store passkeys in a self-hosted password manager?

Yes, if your client apps support passkey storage. The sync server only stores encrypted vault items, so passkey support comes from the desktop app, browser extension or mobile app you use. KeePassXC supports passkeys in KDBX files through its browser extension. NIST SP 800-63B-4 allows synced passkeys up to AAL2 when access to the sync service uses multi-factor authentication.

Do I need to expose my password server to the internet?

No. If every user can reach your network over a VPN or private overlay network, keep the server private and the public login page disappears. Otherwise expose only HTTPS through a reverse proxy, keep the admin page private and enable two-factor authentication for every account.

How do I move my passwords from one manager to another safely?

Today most moves use an export file, often unencrypted: do it on a trusted machine, import immediately and securely delete the file. The FIDO Credential Exchange Protocol is designed to replace this with an encrypted app to app transfer covering passwords, passkeys, TOTP seeds and more, so check whether both apps support it first.

Is a KeePass file in a cloud drive safe?

The file is encrypted with AES-256 or ChaCha20 under a key derived with Argon2 or AES-KDF, so the cloud provider sees only ciphertext, its size and timestamps. Its safety rests on your master password, your KDF settings and the security of the devices that open it. Add a key file stored somewhere other than the same cloud folder, and keep dated copies so a sync conflict cannot destroy your only copy.

How often should I update a self-hosted password server?

Promptly, on a schedule you do not have to remember. The Vaultwarden project notes that clients update themselves, so a lagging server can stop working with them. Daily automatic updates with rollback, or a weekly manual update with release notes checked, are both reasonable.

Does NIST still require password changes every 90 days?

No. SP 800-63B-4 says verifiers SHALL NOT require periodic password changes, and SHALL force a change only on evidence of compromise. It also forbids composition rules such as mandatory symbols, requires a blocklist check and a 15 character minimum for passwords used alone, and requires services to allow password managers and autofill.

Where Safeguard fits

Safeguard is not a password manager, does not hold or manage your vault, does not audit a manager's cryptography and does not monitor your server's uptime or certificates. The fit is narrower and indirect. A self-hosted vault server is ordinary open source software delivered as a container image: a Rust server and its crates, a bundled web vault built from JavaScript packages, a Debian or Alpine base image, and a reverse proxy beside it. Safeguard can scan that image or its SBOM (for example safeguard scan --image docker.io/vaultwarden/server:1.37.4), list the components and versions inside it, match them against known vulnerabilities, and show which of your projects or images carry a given component version. Where you build your own images or automation around the server, it can open upgrade pull requests. For the client apps on your phones and laptops, and for the server's operating system, updates still come from their publishers.

Software supply chain hygiene still matters for a password manager, because the server that guards your most sensitive data is a container image you pull, rebuild and redeploy, and every component inside it ships fixes on someone else's schedule. The fit is indirect: it covers the open source components in images and code you build and ship, not the vault, the master password or the hosted services you use.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

These demos show dependency, image and remediation workflows, not password management. You can download Safeguard and follow the CLI docs to try them on your own projects.

This demo sets up the Safeguard runner on your own machine, approves it with its device code and scans from the terminal. Pointed at the vault server image you run, the same scan lists the packages and versions inside it and their known vulnerabilities, so you can tell whether last night's automatic update actually moved you past a fixed release.

Click through it at your own pace, or open it full screen.

This demo is a real CLI session: ask it to fix the lodash CVE in a repository and watch it read the finding and the advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with your approval, and push nothing. The same approve each step flow fits a repository that holds your self-hosting configuration, where a fix means bumping a pinned image tag or a dependency in a backup or provisioning script.

Click through it at your own pace, or open it full screen.

This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. You can then ask which of your projects or images ship a given component version and get the answer from your own scan data rather than from memory.

Click through it at your own pace, or open it full screen.

Quick check

Your self-hosted vault server is fully patched and uses Argon2id. An attacker takes over the server. Which of your devices is most at risk, and why?

Any browser that logs into the web vault. The server delivers the web vault's JavaScript, so an attacker who controls it can serve altered code that captures the master password at the next login. Native apps and store-installed extensions do not load their code from your server, so they are not exposed to that specific attack, although the attacker still gets the encrypted vault data to attack offline.

Under NIST SP 800-63B-4, what must protect access to a sync service that stores synced passkeys, and at which assurance level are synced passkeys not allowed?

Access to the sync fabric must be protected by AAL2 equivalent multi-factor authentication, and the stored keys must be encrypted with at least 112 bits of security strength, ideally under a user-controlled secret. Synced passkeys are not allowed at AAL3, because their private keys are exportable by design.

How many bits does a six word passphrase from a 7,776 word list carry, and what does raising PBKDF2 from 100,000 to 600,000 iterations add?

About 77.5 bits (six times log2 of 7,776, which is about 12.92). Raising PBKDF2 from 100,000 to 600,000 iterations adds only log2(6), about 2.6 bits of work per guess. The passphrase does most of the work; the KDF multiplies the cost of each guess.

Sources

Last reviewed: 23 October 2026. Server releases, client KDF defaults and the FIDO Credential Exchange specifications all change; check the linked pages for the version you actually run.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.