Search
SEC Tutorial

Self-Host Vaultwarden: 13 Steps, 60 Minutes [2026]

Rachel Kowalski
Rachel KowalskiCybersecurity Analyst
22 min read
Self-Host Vaultwarden: 13 Steps, 60 Minutes [2026]

Bitwarden raised Premium pricing again this year, and password manager breaches keep landing in the news cycle. That combination is pushing a growing number of privacy-minded users toward Vaultwarden, the Rust-based, Bitwarden-compatible server that lets you run your own password vault on hardware you control. Vaultwarden now sees roughly 8,100 monthly searches in the US alone, and the project shipped version 1.37.4 on October 5, 2026, so interest and development activity are both climbing at the same time.

This tutorial walks through a complete, production-ready Vaultwarden deployment in 13 steps, roughly 60 minutes of hands-on work. You will provision a small VPS, deploy Vaultwarden with Docker Compose, put it behind a TLS-terminating reverse proxy, lock down the admin panel, connect the official Bitwarden apps to your own server, and set up a backup routine that will actually save your vault if a disk dies. Along the way we will flag the mistakes that get self-hosted password managers compromised or, more commonly, locked out by their own owners.

Nothing here requires a background in server administration beyond basic comfort with SSH and copy-pasting YAML carefully. What it does require is patience with the parts that matter most for a password vault specifically: the backup strategy, the admin token, and the reverse proxy configuration. Skipping any one of those three is how self-hosted deployments either get compromised or, far more commonly, lock their own owner out permanently after a routine server reboot.

Google · Preferred Sources

Don't miss new tech stories on Google

Add TrendinTech once in the Google app and our stories appear in your news suggestions.

Add Now

Why Self-Host a Password Manager in 2026

Bitwarden’s hosted Premium plan now runs $1.65 a month when billed annually ($19.80 a year), and Families costs $3.99 a month ($47.88 a year) for up to six users. Bitwarden also rolled out expanded Premium and Families features this year, including vault-health alerts, password coaching, 5GB of encrypted attachment storage, and support for up to 10 security keys covering hardware tokens, biometrics, and passkeys. None of that is expensive by SaaS standards, and Bitwarden still offers a free tier with unlimited logins across unlimited devices.

So why bother self-hosting? Three reasons keep coming up. First, control: your encrypted vault blob sits on a server you own, not on infrastructure you have to trust by default. Second, cost at scale: once you are running a VPS for other projects anyway, adding Vaultwarden for a household or a small team costs nothing extra, versus paying per-seat for Bitwarden Business. Third, auditability: Vaultwarden is open source, so you, or anyone, can read exactly what the server does with your data, rather than relying on a vendor’s security whitepaper.

The tradeoff is operational responsibility. You become the person who patches the server, rotates the admin token, and tests the backups. If that sounds like extra work you don’t want, a hosted plan is the better call. If you already run a home lab or a cheap VPS for other services, Vaultwarden is one of the lowest-maintenance things you can add to it.

There’s also a narrower, more practical driver behind the current spike in interest: credential-stuffing and vault-breach headlines never really stop, and every time a major provider discloses an incident, a chunk of its user base starts searching for an exit option that doesn’t depend on any single vendor’s infrastructure decisions. Self-hosting doesn’t make you immune to every attack, your VPS can still be compromised, your domain can still be hijacked, but it does mean the blast radius of a vendor-side breach that has nothing to do with your own operational choices no longer applies to you. The attack surface shifts from whatever happens on Bitwarden’s cloud infrastructure to whatever you personally configure, which is either reassuring or terrifying depending on how much you trust your own patch discipline.

Vaultwarden vs the Official Bitwarden Server: What’s Actually Different

Vaultwarden is not Bitwarden’s official self-hosted server. It is a community-built, API-compatible reimplementation written in Rust, designed to run comfortably on hardware far too small for Bitwarden’s own Docker stack, which bundles MSSQL and several microservices. Vaultwarden speaks the same client API, so the official Bitwarden browser extensions, mobile apps, and desktop apps all connect to it without modification. That compatibility is at the API and client level, though, not a guaranteed one-to-one feature match with Bitwarden’s official server, and newer Bitwarden features sometimes land in Vaultwarden weeks or months later, if at all.

WebAuthn and passkey support is a good example of where the two projects currently stand. Vaultwarden supports WebAuthn as a two-factor method and can store passkey credentials inside the vault, syncing them across supported clients. That support is still maturing, though, and exact behavior for passkey creation, use, and login can vary depending on which version of the Bitwarden app or browser extension you’re running. If passkeys are a hard requirement for your household, test the specific flow you need before committing to a migration.

CapabilityVaultwardenOfficial Bitwarden Server
Resource footprintSingle lightweight container, SQLite by defaultMulti-container stack, MSSQL-based
Minimum practical VPS1 vCPU / 512MB RAM4+ vCPU / 8GB+ RAM recommended
Client compatibilityOfficial Bitwarden apps and extensionsOfficial Bitwarden apps and extensions
WebAuthn / passkeysSupported, still maturingSupported, officially maintained
Admin panelBuilt-in /admin panel, token-protectedSeparate admin portal
Official support channelCommunity (GitHub issues, Discord)Commercial support available
License costFree, open sourceFree self-host, paid add-ons

For a household or a small team under 10 people, Vaultwarden’s lighter footprint and simpler deployment usually win out, which is the scenario this tutorial is built around.

Prerequisites and Versions You’ll Need

Before starting, make sure you have the following in place. Version numbers below reflect what was current as of this writing in October 2026. Always check the project’s own release notes immediately before you deploy, since Vaultwarden ships frequent point releases.

  • A VPS or home server running a current Linux distribution (Debian 12/13, Ubuntu 24.04 LTS, or similar) with root or sudo access
  • Docker Engine, version 29.5.1 or newer (Docker patched a container-escape issue, CVE-2026-41567, affecting docker cp archive handling, in 29.5.1, so don’t deploy on anything older)
  • Docker Compose v5.6.0 or newer, invoked as docker compose (the hyphenated docker-compose binary is legacy at this point)
  • A registered domain name, or at minimum a subdomain you control, for TLS and WebSocket support
  • Vaultwarden server image vaultwarden/server, pinned to the current stable tag (1.37.4 at the time of writing, released October 5, 2026)
  • Basic command-line comfort: SSH, a text editor, and enough familiarity with YAML to not fear indentation errors
  • The official Bitwarden browser extension or mobile app on at least one device, to test the connection once the server is live

On sizing: Vaultwarden is genuinely light. The table below reflects practical recommendations for different household and small-team sizes, not Vaultwarden’s bare technical minimum.

Use casevCPURAMStorage
Single user, bare minimum1512MB10GB SSD
Household (2-10 users)1-21GB20GB SSD
Small team with attachments/Sends22GB40GB+ SSD

Storage needs stay modest unless people start dumping large file attachments or Bitwarden Send files into the vault. For a typical household password manager with occasional secure notes and a handful of attachments, 20GB of SSD will last years.

Step-by-Step: Deploying Vaultwarden with Docker Compose

Step 1: Provision and Harden the VPS

Spin up a small VPS (the 1-2 vCPU / 1GB RAM tier from the table above is plenty for most households) running Debian or Ubuntu LTS. Before installing anything else, do the basic hardening pass: create a non-root sudo user, disable root SSH login, switch to key-based authentication, and enable a firewall (ufw or your provider’s equivalent) that only allows SSH, HTTP, and HTTPS inbound. This is the single most important step in the whole tutorial, because an exposed password vault server is a worse outcome than no server at all.

Step 2: Install Docker Engine and Compose

Install Docker Engine using the official convenience script or your distribution’s repository, then confirm both Docker and Compose are current:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
docker --version
docker compose version

You want Docker Engine 29.5.1 or newer and Docker Compose reporting a v5.x build. Docker’s own CLI reference documents the docker compose version command if you need to confirm exactly what shipped with your install.

Step 3: Create the Project Directory and Data Volume

Keep Vaultwarden’s persistent data in a dedicated directory outside of any container filesystem, so upgrades and rebuilds never touch your vault:

mkdir -p ~/vaultwarden/vw-data
cd ~/vaultwarden
touch docker-compose.yml .env

Step 4: Write the docker-compose.yml File

This is the core of the deployment. Pin the image to a specific version rather than latest, so an upstream release never surprises you mid-sleep:

services:
  vaultwarden:
    image: vaultwarden/server:1.37.4
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - DOMAIN=https://vault.example.com
      - SIGNUPS_ALLOWED=false
      - WEBSOCKET_ENABLED=true
      - ADMIN_TOKEN=${ADMIN_TOKEN}
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:8080:80"
    networks:
      - vaultwarden-net

networks:
  vaultwarden-net:
    driver: bridge

Note the port binding: Vaultwarden only listens on localhost (127.0.0.1:8080), never on a public interface. The reverse proxy you set up in Step 9 is the only thing that should ever be reachable directly from the internet.

Step 5: Configure Environment Variables and Secrets

Store secrets in .env rather than hardcoding them in the compose file, and set restrictive permissions on it:

echo 'ADMIN_TOKEN=$argon2id$...your-hashed-token-goes-here...' > .env
chmod 600 .env

If you’re using Docker Compose’s variable interpolation with an Argon2 PHC-format hash, escape every dollar sign as $$, or Compose will try to interpolate pieces of the hash string as its own variables and silently break the token.

Step 6: Generate and Hash the Admin Token

Never store ADMIN_TOKEN as plaintext. Vaultwarden ships a built-in command that hashes a token with Argon2id before you put it anywhere in a config file:

docker run --rm -it vaultwarden/server:1.37.4 /vaultwarden hash

# paste a long, randomly generated password when prompted
# copy the resulting $argon2id$... string into your .env file

Storing the hash instead of the raw token matters: if an attacker ever reads your configuration file, a hash doesn’t hand them the live admin password the way plaintext would.

Step 7: Launch the Container

docker compose up -d
docker compose logs -f vaultwarden

Watch the logs for a clean startup message with no database or permission errors. At this point Vaultwarden is running, but only reachable on localhost, which is exactly what you want before a reverse proxy and TLS are in place.

Step-by-Step: Securing Access with a Reverse Proxy

Step 8: Point a Domain and DNS Record at the Server

Create an A (or AAAA) record for a subdomain like vault.example.com pointing to your VPS’s public IP. Give DNS a few minutes to propagate before moving on, and confirm it resolves with dig vault.example.com from a different network than the server itself.

Step 9: Configure Caddy for Automatic TLS

Caddy issues and renews Let’s Encrypt certificates automatically, which removes an entire category of maintenance compared to manually managing certbot. Install Caddy on the host, outside the Vaultwarden container, and point it at the localhost port you bound in Step 4:

vault.example.com {
    reverse_proxy 127.0.0.1:8080 {
        header_up X-Real-IP {remote_host}
    }
}

Vaultwarden relies on WebSocket connections for live sync between clients, so make sure whichever proxy you choose, Caddy here, or nginx if you prefer manual TLS config, doesn’t strip the Upgrade and Connection headers that WebSockets need. Caddy’s reverse_proxy directive passes these through by default, which is one reason it’s the lower-friction option for a first deployment.

Step 10: Lock Down the /admin Panel

With ADMIN_TOKEN set, Vaultwarden’s admin panel becomes available at https://vault.example.com/admin, protected by the token you hashed in Step 6. For an extra layer, restrict access to that specific path at the proxy level to a known IP range, or put it on a separate internal-only hostname entirely. The admin panel can create and delete users and read diagnostic data, so it deserves the same caution as SSH access to the box itself.

Step-by-Step: Client Setup and Vault Migration

Step 11: Connect the Official Bitwarden Apps to Your Server

Install the official Bitwarden browser extension or mobile app, then before logging in, go to its settings and change the server URL from the default bitwarden.com to your own domain (https://vault.example.com). Create your account from there. Since SIGNUPS_ALLOWED is set to false in the compose file above, no one else can self-register, and you’ll need to flip it to true temporarily, or use the admin panel’s invite feature, for each additional household member.

Step 12: Import Existing Vault Data

If you’re migrating off another password manager, export your existing vault as a Bitwarden-compatible JSON or CSV file (most managers support at least CSV), then use the Bitwarden client’s built-in Import Data feature while logged into your new Vaultwarden server. Delete the plaintext export file immediately afterward, since an unencrypted vault export sitting in your Downloads folder defeats a good chunk of the point of this whole exercise.

Step 13: Enable Passkeys and Two-Factor Authentication

In the Bitwarden client’s security settings, enable two-factor authentication, an authenticator app or a hardware security key both work against Vaultwarden, and, if your client version supports it, start storing or using passkeys through the vault’s WebAuthn integration. Test the exact passkey flow you need (login with a passkey, or just storage of one) on each device before relying on it, since client-side passkey behavior against Vaultwarden still varies by app version.

Backing Up Your Vault: A Disaster Recovery Plan

A self-hosted password manager with no backup strategy is a liability, not a convenience. If the VPS disk fails and you have no copy of the data directory, every credential your household has stored becomes unrecoverable in one event. Four things live in that data directory and all four need to survive a disaster: the SQLite database itself, the attachments/ folder, the rsa_key* files, especially rsa_key.pem, and config.json.

The rsa_key.pem file deserves special attention. It is the private key Vaultwarden uses for session and sync operations. Delete it and restart the server, and Vaultwarden silently generates a brand-new one, invalidating every existing client session in the process. That’s recoverable, everyone just logs back in, but it’s a clean illustration of why a careless file-level backup that misses hidden or oddly-permissioned files can cause confusing outages.

Back up the live SQLite database using its proper online backup mechanism rather than copying the file while the container is running, which risks grabbing it mid-write:

#!/bin/bash
# vw-backup.sh - run via cron, e.g. daily at 3am
BACKUP_DIR=/home/youruser/vw-backups
DATE=$(date +%F)

mkdir -p "$BACKUP_DIR"
docker exec vaultwarden /vaultwarden backup
tar czf "$BACKUP_DIR/vaultwarden-$DATE.tar.gz" -C ~/vaultwarden/vw-data .
gpg --symmetric --cipher-algo AES256 "$BACKUP_DIR/vaultwarden-$DATE.tar.gz"
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete

Run that on a schedule with cron, encrypt the resulting archive, it contains sensitive configuration and cryptographic material, so it needs the same care as the vault itself, and copy it somewhere physically separate from the VPS, such as object storage at a different provider. Keep several generations rather than overwriting a single backup file, and actually test a restore at least once. A backup you’ve never restored from is a theory, not a plan.

Updating and Maintaining Vaultwarden Long-Term

Vaultwarden ships frequent point releases, and you can track the project’s release pipeline on GitHub to see exactly when new builds land. Pinning your compose file to an explicit version, as Step 4 did, means updates are a deliberate action, not something that happens silently overnight. Before updating, read the release notes, back up the data directory, then bump the version tag and redeploy:

# after editing the image tag in docker-compose.yml
docker compose pull
docker compose up -d
docker compose logs -f vaultwarden

Resist the temptation to run tools like Watchtower for fully automatic updates on a password manager. Automatic image updates are convenient for low-stakes services, but an unattended upgrade that breaks database migrations or client compatibility is exactly the kind of failure you want to catch manually, with a backup already in hand, rather than discover when you’re locked out at 7am trying to leave for work.

6 Common Pitfalls When Self-Hosting a Password Manager

  • Exposing the container directly to the internet. Binding Vaultwarden’s port to 0.0.0.0 instead of 127.0.0.1 skips the reverse proxy entirely and leaves an unencrypted HTTP service with no rate limiting facing the open internet. It’s an easy mistake to make when copy-pasting a compose file from an old tutorial, and it defeats nearly every other precaution in this guide at once, since TLS termination and admin-path restrictions both live at the proxy layer.
  • Leaving SIGNUPS_ALLOWED set to true indefinitely. This turns your private vault server into an open registration page for anyone who finds the domain, whether through a DNS leak, a shared link, or simple brute-force subdomain guessing. Flip it on briefly to add a household member, then flip it back off and restart the container to confirm the change actually took effect.
  • Running on the latest image tag in production. An upstream release can land with a breaking change, a database migration, or a behavior shift in session handling at any time. Pin a specific version and upgrade on your own schedule, after reading the changelog, rather than discovering a breaking change mid-week when you actually need to log into a bank account.
  • Treating the rsa_key files as disposable. Losing them invalidates sessions at minimum, and in more unusual failure modes can complicate restoring encrypted data from an old backup that still expects the original key pair. Back them up with the same discipline as the database, not as an afterthought bundled loosely with “the rest of the folder.”
  • Skipping WebSocket support in the reverse proxy config. Without the Upgrade and Connection headers passed through correctly, clients fall back to slow polling or stop syncing live changes altogether, which looks like a bug but is actually a proxy misconfiguration. This is the single most common support request in Vaultwarden’s community channels, and it’s almost always solved by checking the proxy’s header-forwarding rules rather than anything inside the container itself.
  • Forgetting that the admin panel and the user-facing vault share a domain by default. If you don’t separate them, as suggested in Step 10 and the Advanced Tips section below, anyone who finds your vault URL has also found your admin login page, and only the token stands between them and full administrative control.

Troubleshooting: 8 Common Vaultwarden Errors

  • “Invalid admin token” on the /admin page. Usually an unescaped dollar sign in an Argon2 hash inside docker-compose.yml. Escape every $ as $$, or move the raw hash into the .env file instead, where Compose’s interpolation rules behave more predictably. If the problem persists, regenerate the hash from scratch with the /vaultwarden hash command rather than trying to hand-edit an existing one.
  • Clients can’t sync in real time. Confirm WEBSOCKET_ENABLED=true is set and that your reverse proxy forwards WebSocket upgrade headers, then test with your browser’s developer tools network tab for a 101 Switching Protocols response on the notifications hub endpoint. If you see a 400 or 426 response instead, the proxy is terminating the upgrade request before it reaches the container.
  • 502 Bad Gateway from the reverse proxy. The Vaultwarden container likely isn’t running or is bound to a port the proxy isn’t checking. Run docker compose ps and docker compose logs to confirm the container is healthy before touching the proxy config. A healthy container that still 502s usually means a port mismatch between the compose file and the proxy’s upstream address.
  • “database is locked” errors in the logs. SQLite doesn’t handle heavy concurrent writes well. For a household this is rare, but if it happens repeatedly under load, typically when several people trigger syncs simultaneously on a small-team instance, consider migrating to PostgreSQL or MySQL, which Vaultwarden also supports as a configurable backend.
  • Attachments fail to upload. Check disk space on the VPS first with df -h, then confirm the vw-data directory has correct ownership and write permissions for the container’s user. A full disk produces a confusing client-side error that rarely mentions storage directly.
  • Email invites and 2FA emails never arrive. Vaultwarden needs SMTP credentials configured via environment variables (SMTP_HOST, SMTP_FROM, SMTP_USERNAME, SMTP_PASSWORD) to send mail. Without them, invite links have to be shared manually from the admin panel instead. Many residential ISPs and some VPS providers also block outbound port 25 and sometimes 587 by default, so a correctly configured SMTP block can still silently fail to deliver.
  • Let’s Encrypt certificate renewal fails. Confirm port 80 is still reachable from the internet for the HTTP-01 challenge, a firewall rule change is the usual culprit, and check that the domain’s DNS record hasn’t drifted to a different IP after a VPS migration or provider change.
  • Container keeps restarting in a loop. Almost always a bad environment variable value or a corrupted database file from an interrupted write. Check docker compose logs for the specific startup error before assuming the worst. Restoring yesterday’s backup is the fallback if the database itself is damaged, which is exactly why the backup routine earlier in this guide matters more than it might seem during a smooth first setup.

Advanced Tips: Hardening Your Deployment Further

Once the base deployment is stable, a few additional steps raise the security bar without much extra complexity. Put the /admin route on a separate subdomain that only resolves internally or over a VPN, rather than leaving it reachable at a predictable path on your main vault domain. Add fail2ban or an equivalent rate-limiting layer in front of the login endpoint to slow down credential-stuffing attempts against your own instance. If you use hardware security keys, register at least two per account, one as a physical backup, since a lost sole authenticator on a self-hosted system means recovery depends entirely on your own admin access, not a vendor’s support line.

For anyone running Vaultwarden across multiple family members or a small team, consider enabling organizations inside the vault to manage shared logins, streaming services, shared utility accounts, separately from personal credentials, rather than everyone dumping shared passwords into their individual vaults. And if you’re already running other self-hosted services behind the same reverse proxy, keep Vaultwarden on its own Docker network and avoid giving it unnecessary links to other containers. A compromised unrelated container should never be able to reach your password database directly.

Monitoring Uptime and Shipping Backups Off-Site

A password vault that’s quietly down is worse than one that’s visibly down, because nobody notices until they’re standing at a login screen unable to get into anything. A lightweight uptime check costs nothing to set up and catches outages before they become a crisis at an inconvenient moment. A simple cron-driven health check against Vaultwarden’s built-in alive endpoint, paired with any free uptime-monitoring service that can hit an HTTPS URL and alert you by email or push notification, covers the basics without adding another heavyweight service to maintain.

# simple health check, add to cron every 5 minutes
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://vault.example.com/alive)
if [ "$STATUS" != "200" ]; then
    echo "Vaultwarden health check failed: HTTP $STATUS" | mail -s "Vaultwarden DOWN" [email protected]
fi

The backup routine from earlier in this guide only protects you if the encrypted archive actually leaves the VPS. Keeping backups on the same disk as the live database protects against database corruption but does nothing against a provider-level disk failure, an accidental rm -rf, or a compromised root account. Shipping the encrypted archive to a separate object storage bucket, ideally with a different provider than the VPS itself, closes that gap. A tool like rclone makes this a one-line addition to the backup script from earlier:

# append to vw-backup.sh, after the gpg encryption step
rclone copy "$BACKUP_DIR/vaultwarden-$DATE.tar.gz.gpg" remote:vaultwarden-backups/
# "remote" is whatever name you gave the storage provider during `rclone config`

Run the health check and the off-site copy on independent schedules, and periodically confirm both are actually firing, not just configured. A cron job that silently stopped running six months ago because of a typo in a path is one of the more common ways self-hosted backup strategies fail in practice.

Alternatives to Vaultwarden Worth Knowing About

Vaultwarden is the dominant choice for self-hosted Bitwarden compatibility, but it isn’t the only self-hosted password manager worth knowing about, and understanding where it sits relative to the alternatives helps clarify why this tutorial recommends it as a default rather than the only option. Passbolt is a team-oriented, self-hosted password manager built from the ground up for organizations rather than retrofitted onto a consumer client. It’s a heavier deployment with its own purpose-built web interface, and it makes more sense for a company that needs granular sharing permissions than for a household. Psono is another self-hosted option aimed at teams, with a plugin-based architecture for things like file storage and SSO integration, again trading Vaultwarden’s simplicity for features aimed at larger organizations.

At the opposite end of the complexity spectrum, some people skip a server entirely and sync a local KeePassXC database file through a self-hosted file-sync tool like Syncthing. That approach has no server attack surface at all, since there’s no always-on service listening for connections, but it also loses the browser extension convenience, the mobile push-based autofill, and the multi-user sharing that Vaultwarden provides out of the box. For most households and small teams who specifically want the Bitwarden client experience without paying Bitwarden’s hosting fee, Vaultwarden remains the best-fit tool, which is why the rest of this guide focuses on it rather than treating it as one option among equals.

Cost Comparison: Self-Hosting vs Commercial Password Managers

Self-hosting isn’t free once you count the VPS, but for a household already paying for a server, the marginal cost of adding Vaultwarden is close to zero. Here’s how the economics actually shake out against Bitwarden’s current published plans.

OptionAnnual costUsers coveredWho maintains it
Bitwarden Free$01 (unlimited devices)Bitwarden
Bitwarden Premium$19.80/year1Bitwarden
Bitwarden Families$47.88/yearUp to 6Bitwarden
Vaultwarden on a dedicated small VPS~$60-$144/year (VPS cost)Effectively unlimitedYou
Vaultwarden on an existing home server/VPS~$0 marginal costEffectively unlimitedYou

If you’re starting from zero infrastructure, buying a VPS purely to run Vaultwarden rarely beats Bitwarden Families on price alone. The economics flip once you already have a home lab or a VPS doing other work: at that point Vaultwarden covers an unlimited number of household members for no additional subscription cost, at the price of becoming your own system administrator for it. Bitwarden’s own self-hosted track, including the newer Bitwarden Lite deployment option, remains available for anyone who wants official self-hosting without going through Vaultwarden at all, though it targets a heavier infrastructure footprint than Vaultwarden does.

Complete Working Project: Full Configuration Files

Here is the complete, working set of files from this tutorial, assembled in one place, cross-checked against a community Vaultwarden Docker setup guide for anyone who wants a second reference. Copy these into a fresh directory, fill in your domain and token, and you have the entire deployment from Steps 1-10 ready to launch.

# docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:1.37.4
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - DOMAIN=https://vault.example.com
      - SIGNUPS_ALLOWED=false
      - WEBSOCKET_ENABLED=true
      - ADMIN_TOKEN=${ADMIN_TOKEN}
      - SMTP_HOST=smtp.example.com
      - [email protected]
      - [email protected]
      - SMTP_PASSWORD=${SMTP_PASSWORD}
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:8080:80"
    networks:
      - vaultwarden-net

networks:
  vaultwarden-net:
    driver: bridge
# Caddyfile
vault.example.com {
    reverse_proxy 127.0.0.1:8080 {
        header_up X-Real-IP {remote_host}
    }
    encode gzip
}

With both files in place, docker compose up -d plus a running Caddy instance gets you a TLS-protected, WebSocket-capable, admin-locked Vaultwarden instance ready for clients to connect to. Also confirm your installed Compose build against the Docker Compose release notes so you’re not deploying against an outdated client.

Frequently Asked Questions

Is Vaultwarden safe to use instead of the official Bitwarden server?
Vaultwarden is widely used and actively maintained, and it implements the same client-side encryption model as Bitwarden, meaning your vault data is encrypted before it ever leaves your device. It is not officially affiliated with or supported by Bitwarden, so you’re relying on the open-source community for security review rather than a commercial vendor’s support contract.

Do I need a domain name to run Vaultwarden?
Practically, yes. WebSocket support and proper TLS both work far more reliably with a real domain and a reverse proxy than with a bare IP address, and most Bitwarden clients expect a proper HTTPS endpoint.

Can I run Vaultwarden on a Raspberry Pi or NAS instead of a VPS?
Yes. Vaultwarden’s resource footprint is light enough to run comfortably on a Raspberry Pi 4 or a Synology/QNAP NAS with Docker support. The main consideration is reliable uptime and backup, not raw compute power.

What happens if my VPS provider goes down?
If you have no backup, you lose access to your entire vault until the provider recovers, if it ever does. This is exactly why the backup routine in this tutorial copies encrypted archives off the VPS to separate storage. Without that, self-hosting introduces more single points of failure than a hosted service would.

Does Vaultwarden support passkeys for passwordless login?
Vaultwarden supports WebAuthn, including passkey storage and use, but support is newer than on the official Bitwarden server and client behavior can vary by app version. Test your specific passkey workflow on each device you plan to rely on before trusting it as your only login method.

How do I migrate from LastPass, 1Password, or another manager to Vaultwarden?
Export your existing vault in a Bitwarden-compatible CSV or JSON format from your current manager, then use the Bitwarden client’s Import Data feature while logged into your new Vaultwarden server, exactly as described in Step 12. Delete the plaintext export file immediately afterward.

Is SQLite good enough, or should I use PostgreSQL?
SQLite is the default and works well for individuals and households. If you start seeing “database is locked” errors under heavier concurrent use, typically in small-team settings, Vaultwarden also supports PostgreSQL and MySQL as drop-in alternatives.

How often should I update Vaultwarden?
Check the project’s release notes monthly at minimum, and update promptly for anything flagged as a security fix. Because the compose setup in this tutorial pins an explicit version tag, updates only happen when you deliberately change that tag and redeploy, never automatically.

Related Coverage

Rachel Kowalski

Rachel Kowalski

Cybersecurity Analyst

Rachel Kowalski is the Cybersecurity Analyst at TrendinTech, where she covers vulnerabilities, ransomware, supply chain attacks, nation-state operations and the security rules shaping organizations in the United States and Europe. Before moving into journalism she worked as a threat intelligence analyst at a security vendor and later reported for CyberScoop and the security desk at Wired, covering the SolarWinds compromise and the ransomware wave that hit hospitals and pipelines. Rachel holds a Master of Science in Cybersecurity from the Georgia Institute of Technology and attends Black Hat and DEF CON in Las Vegas each year, where she follows research from the security community. She writes to make risks and countermeasures understandable to people who are not specialists.

All stories by Rachel Kowalski (234)

Related Articles