36 min read

How to Self-Host Vaultwarden: Complete Guide to Installation, HTTPS, Security, and Remote Access

Vaultwarden is a lightweight, open-source reimplementation of the Bitwarden server written in Rust. It is fully compatible with all official Bitwarden clients (browser extensions, desktop apps, iOS, Android) and runs on hardware as modest as a Raspberry Pi using under 50 MB of RAM.

Self-hosted Vaultwarden server connected securely to laptop and phone clients.
Vaultwarden runs locally while official clients connect through a secured HTTPS path.
Vaultwarden ยท Docker ยท HTTPS ยท Self-Hosting ยท 2026

Build a private vault with controlled, secure remote access

Vaultwarden is an unofficial, community-maintained implementation of the Bitwarden Client API designed for self-hosted deployments. This guide installs it with Docker Compose, keeps the service bound to loopback, publishes it through a Localtonet HTTP tunnel, and explains exactly where HTTPS terminates. It also covers account lockdown, client setup, Raspberry Pi storage, encrypted backups, restoration testing, updates, outage behavior, and practical troubleshooting.

๐Ÿณ Persistent Docker deployment ๐Ÿ”’ Trusted public HTTPS ๐ŸŒ No inbound router port forwarding ๐Ÿ’พ Tested backup and recovery plan

What Vaultwarden is, and what it is not

Vaultwarden, formerly called bitwarden_rs, is an alternative server implementation of the Bitwarden Client API written in Rust. It is not produced by or affiliated with Bitwarden, Inc. The project provides its own server, a modified web vault bundled with its container images, and support for many familiar Bitwarden capabilities.

The project describes its API implementation as nearly complete. That distinction matters. Official Bitwarden browser extensions, mobile applications, and desktop clients are commonly used with Vaultwarden, but compatibility should not be treated as universal or permanent. A newly released client feature can depend on an API behavior that Vaultwarden has not implemented yet. Test the specific clients and workflows your users need before treating an upgrade as production-ready.

Vaultwarden recommends its published container images for installation. Community packages and source builds are alternatives, but a community package may lag behind current releases or change configuration conventions. This tutorial therefore uses the official Vaultwarden container image with Docker Compose and a persistent host directory.

Vaultwarden has a separate support path

Do not contact official Bitwarden support about a Vaultwarden server. Report Vaultwarden problems through the Vaultwarden GitHub project, its discussions, or the Vaultwarden community forum. Before reporting a client problem, record the Vaultwarden version, client version, relevant logs, and whether the same operation works in the bundled web vault.

Durable deployment distinctions

The meaningful choice is not a volatile price or container count. It is who operates the server, who supports it, and who is responsible for recovery. Product pricing, resource requirements, feature entitlements, and supported deployment methods can change, so they should be checked directly before making a long-term decision.

Deployment model Operator responsibility Client and support relationship Recovery responsibility
Vaultwarden self-hosted You maintain the host, container, storage, TLS access path, updates, monitoring, and backups. Unofficial server with a nearly complete Bitwarden Client API implementation. Support is community-based. You must preserve the database, attachments, Sends, signing keys, configuration, and required secrets.
Official Bitwarden self-hosted You operate an official deployment using the currently supported Bitwarden installation path. Official server and official client relationship. Support availability depends on the applicable offering. You remain responsible for infrastructure and the documented backup and recovery process.
Hosted password-manager service The provider runs the service infrastructure, while you manage accounts, credentials, recovery options, and endpoint security. Provider-controlled server and client release cycle. Provider resilience does not replace account recovery planning, secure exports, or organization-specific continuity controls.

Self-hosting gives you operational control, but it also makes availability and recovery your job. A database on hardware you control is not automatically private, secure, or resilient. Host compromise, weak credentials, an exposed administration panel, an untrusted backup destination, or an untested restore can still put the vault at risk.

HTTPS, secure contexts, and the actual trust boundary

HTTPS and tunnel path from Bitwarden clients to a private Vaultwarden container.
HTTPS protects the client-facing connection, while the tunnel carries traffic to the private host.

Vaultwarden's web vault uses browser cryptography and requires HTTPS and a secure context. Browsers generally treat a valid HTTPS origin as potentially trustworthy. Loopback origins such as http://localhost also receive special secure-context treatment in common browsers, which is useful for same-machine testing. An ordinary LAN address such as http://192.168.1.20 is not equivalent to localhost and should not be used as the remote web-vault address.

The phrase โ€œany HTTPS URL worksโ€ is too broad. The certificate must be valid for the requested hostname and trusted by the device. An expired certificate, hostname mismatch, incomplete certificate chain, or untrusted private certificate authority can produce warnings or prevent a native client from connecting. Never instruct users to ignore a certificate warning for a password manager.

๐Ÿ–ฅ๏ธ Loopback testing http://localhost:8080 can be used on the host to confirm that Vaultwarden responds. It is not the remote client address.
๐Ÿ” Trusted HTTPS Remote browsers and applications should use an HTTPS URL with a valid, trusted certificate for that exact hostname.
๐Ÿ“œ Private certificates A private or self-signed certificate requires its issuing authority to be installed and trusted correctly on every client device.
๐ŸŒ Public tunnel endpoint A Localtonet HTTP tunnel gives the service an assigned public HTTPS address while the local target remains bound to loopback.

HTTPS options

Method Certificate model Inbound network requirement Operational consideration
Reverse proxy with a public certificate A reverse proxy such as Caddy or Nginx presents the certificate. Depends on certificate validation and routing. ACME HTTP-01 normally needs inbound port 80, TLS-ALPN-01 normally needs 443, while DNS-01 can validate through DNS without those inbound validation ports. You maintain DNS, certificate renewal, reverse-proxy configuration, and router or firewall exposure.
Private CA or self-signed certificate You create and distribute the trust anchor. No public validation is required. Every browser, operating system, and native client must trust the issuing CA correctly. Certificate warnings are not an acceptable steady state.
Localtonet HTTP tunnel The public endpoint presents HTTPS and forwards requests through the outbound tunnel. No inbound router port forwarding or public IP address is required. The selected Localtonet client must remain connected and the tunnel must remain started. Plan-specific timeout and availability behavior also applies.

Where TLS ends in this tutorial

This deployment intentionally binds Vaultwarden to 127.0.0.1:8080. A remote Bitwarden client connects to the assigned Localtonet HTTPS endpoint. HTTPS is terminated at the public tunnel edge, and traffic is carried through the outbound Localtonet tunnel to the Localtonet client. The final connection from that client to http://127.0.0.1:8080 is local HTTP.

That is not the same as TLS terminating inside Vaultwarden. The trust boundary includes the public tunnel endpoint, relay path, Localtonet client process, host operating system, Docker runtime, and Vaultwarden container. Keeping the Localtonet client and Vaultwarden on the same trusted host confines the final HTTP hop to loopback. If the client forwards to a different machine on a LAN, that final hop crosses the LAN in clear HTTP unless you independently add TLS there.

Do not call this end-to-end HTTPS to the container

The remote connection has public HTTPS, but Vaultwarden receives HTTP on its loopback listener in this design. If your threat model requires TLS all the way to the application or a local reverse proxy, configure and validate that additional TLS layer separately.

Prerequisites and supported installation scope

This tutorial covers a 64-bit Linux host, including a supported 64-bit Raspberry Pi installation, with Docker Engine and the Docker Compose plugin. Docker and Compose must be installed using the supported method for your operating system. The convenience script previously shown in this article is intentionally omitted because Docker documents caveats for that route and it should not be presented as the default production installation method.

  • A maintained 64-bit Linux distribution supported by Docker Engine.
  • Docker Engine and Docker Compose v2 installed from the appropriate package repository or supported platform package.
  • A non-root administrative account with controlled Docker access.
  • A persistent filesystem with enough capacity for the database, attachments, Sends, logs, and backup staging.
  • A Localtonet account and an installed Localtonet client on the same host for the loopback design used here.
  • A password manager or offline method for storing the distinct Vaultwarden admin credential, master password, two-factor recovery codes, device token, and backup-encryption key.

Use Docker's operating-system-specific Engine installation instructions and Compose installation instructions. Package names and repository setup differ by distribution, so this guide does not substitute a generic shell pipeline for those checks.

docker --version
docker compose version
docker info

All three checks should complete without an unexpected connection or permission error. Membership in the Docker group is effectively privileged host access because a user who controls Docker can mount host paths and start privileged containers. Grant it only to administrators who require it.

Choose separate credentials before installation

Your vault master password and Vaultwarden administration password must be unique. Do not reuse either as the host login, Localtonet account password, backup key, or disk-encryption passphrase. Store two-factor recovery codes offline in a location that remains available if the vault server is down.

Install Vaultwarden with Docker Compose

Docker Compose project showing Vaultwarden running with persistent storage.
The Compose deployment separates the Vaultwarden container from its persistent data.

The following deployment follows Vaultwarden's documented container pattern: a persistent /data mount, a loopback-only published port, a configured public domain once one is assigned, and a restart policy. Review the current Vaultwarden release notes and container-tag guidance before production use. The moving latest tag is convenient for an initial setup, but it should not be pulled automatically without review.

1

Create a protected project directory

Create the Compose project and persistent data directory under your administrative account. Restrict the project directory because it will contain sensitive configuration.

mkdir -p "$HOME/vaultwarden/vw-data"
cd "$HOME/vaultwarden"
chmod 700 "$HOME/vaultwarden" "$HOME/vaultwarden/vw-data"
2

Generate an Argon2 admin credential hash

Run Vaultwarden's hash utility and enter a strong administration password that is different from every user's master password.

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

The utility returns an Argon2 PHC string beginning with $argon2. Keep the original password in your credential store. Do not use the PHC string as the password entered at /admin.

3

Create the protected environment file

Compose interpolation treats dollar signs specially in several contexts. In a Compose environment file, a single-quoted value is literal. Put the complete PHC value inside single quotes, keep the file out of source control, and do not repeat the variables in an environment section.

umask 077
cat > .env <<'EOF'
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$replace_with_generated_salt$replace_with_generated_hash'
SIGNUPS_ALLOWED=true
TZ=Etc/UTC
EOF
chmod 600 .env

Replace the example with the exact generated PHC string. Keep the single quotes in the file. Do not paste a real token into terminal history, screenshots, tickets, or this article.

4

Create the Compose definition

The loopback binding prevents direct access through the host's LAN or public interfaces. The Localtonet client on the same host can still reach the target.

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:8080:80"

Save this as compose.yaml. For a controlled production lifecycle, replace the moving image reference with a release tag or digest selected after reviewing Vaultwarden's current image guidance and release notes.

5

Validate and start the container

Ask Compose to validate the file, then start Vaultwarden and inspect its state and logs.

docker compose config --quiet
docker compose up -d
docker compose ps
docker compose logs --tail=100 vaultwarden

Do not publish the expanded output of docker compose config. Depending on the command and Compose version, resolved output can reveal environment values.

6

Test local reachability

Verify that the host can reach the loopback listener before introducing a tunnel.

curl -I http://127.0.0.1:8080/
docker compose ps
docker compose logs --tail=100 vaultwarden

An HTTP response proves that the container and host port are connected. It does not yet prove public HTTPS, certificate validity, login, synchronization, or backup recovery.

Why the environment file is not duplicated in Compose

The env_file entry passes the values to the container. Repeating them as ADMIN_TOKEN=${ADMIN_TOKEN} adds another interpolation path and creates avoidable ambiguity around dollar signs. If you choose a different Compose secret-management method, test it with your exact Compose version and inspect Vaultwarden's startup warnings without printing the secret.

Create the Localtonet HTTPS access path

Localtonet exposes a service through an outbound connection from the client device to a Localtonet relay server. It does not require inbound router port forwarding, a public IP address, firewall changes, or VPN setup. For this deployment, create an HTTP tunnel whose local target is 127.0.0.1 on port 8080.

HTTP tunnels can use a generated subdomain, a custom subdomain where supported, or a custom domain. All three process types serve the target at a public HTTPS address. Do not assume a fixed hostname pattern. Use the exact URL assigned by the current dashboard.

1

Install and run the Localtonet client

Use the current installer for your operating system from Localtonet. Run the client on the same machine as Vaultwarden so that the local target remains on loopback. This article does not use an unverified shell installer or service-management command.

2

Authenticate or select the device

Use the device-specific authentication token for the Localtonet client that will run this tunnel. Treat the token as a secret. Do not place it in Compose, application logs, screenshots, or a public repository.

3

Open the HTTP tunnel configuration

In the dashboard, create an HTTP tunnel and choose the required process type: generated subdomain, supported custom subdomain, or custom domain. If you choose a custom domain, follow the current Localtonet DNS instructions rather than guessing the required records.

4

Select the device token and relay server

Select the token belonging to the client running on the Vaultwarden host, then select an available Localtonet relay server or region shown by the current product. Do not hardcode a server code from an older tutorial.

5

Set the local target

Enter 127.0.0.1 as the local IP address and 8080 as the local port. This must match the loopback port published in compose.yaml.

6

Create and explicitly start the tunnel

Save the tunnel configuration, then press Start. Creating a tunnel does not make it run. Record the exact assigned public HTTPS URL only after the dashboard shows the tunnel running.

7

Set Vaultwarden's public domain

Add the exact assigned URL to .env. Preserve the existing single-quoted admin hash and use only one DOMAIN line.

cd "$HOME/vaultwarden"
printf '\nDOMAIN=https://your-exact-assigned-hostname\n' >> .env
chmod 600 .env
docker compose up -d
docker compose logs --tail=100 vaultwarden

Replace the placeholder with the assigned URL. Recreating the container with docker compose up -d applies the updated environment.

Remote availability has three active dependencies

Vaultwarden must be running, the selected Localtonet client must remain connected, and the tunnel must remain started. Relay availability and the timeout or availability behavior of the applicable Localtonet plan also affect continuous access. For example, current free-plan behavior can include a tunnel timeout, while other plans may differ. Confirm current plan details before treating this as an always-on production endpoint.

Access controls and client compatibility

Where your selected Localtonet configuration supports them, IP allowlisting and related access controls can reduce exposure. Apply least privilege and test every required client network. A narrow home IP allowlist, for example, may block a phone when it switches to mobile data.

Be careful with an additional HTTP Basic Authentication, SSO, or interactive authentication layer in front of Vaultwarden. A browser can display an extra login prompt, but a Bitwarden native client may not know how to complete that challenge for API and synchronization requests. Do not enable an outer authentication layer until you have tested login, synchronization, attachments, Sends, and every required client.

First login and security hardening

Create the initial account and close registration

Open the assigned HTTPS URL and confirm that the browser reports a valid certificate for the exact hostname. Create the intended account with a unique master password. After all authorized initial accounts are created, change SIGNUPS_ALLOWED to false and recreate the container:

cd "$HOME/vaultwarden"
sed -i 's/^SIGNUPS_ALLOWED=.*/SIGNUPS_ALLOWED=false/' .env
docker compose up -d
docker compose logs --tail=100 vaultwarden

Then use a private browser window to confirm that public registration is no longer available. Do not rely only on the value in the file. A persisted administration configuration can affect effective settings, so test the actual public behavior after every security change.

Protect or disable the administration panel

The administration endpoint controls server settings and user administration. At /admin, enter the original administration password used to generate the Argon2 hash, not the PHC string stored in .env.

Use an administration password unrelated to every vault master password. Do not expose the administration endpoint more broadly than necessary. If you do not need ongoing web administration, consider disabling it by removing the admin token after completing required configuration. If you retain it, combine a strong credential with compatible tunnel restrictions and monitor access attempts.

Enable two-factor authentication and preserve recovery material

Enable a supported two-step login method for each account. Vaultwarden currently implements multiple authentication options, including authenticator-based codes and FIDO2 WebAuthn. Availability and behavior can vary by client and configuration, so enroll and test at least two client sessions before declaring the setup complete.

Store recovery codes outside the vault in a physically or cryptographically protected location. A recovery code kept only inside the vault is unavailable precisely when it is most needed. Do not assume the server administrator can decrypt a user's vault or reset a forgotten master password. Some organization and client recovery workflows may exist when configured in advance, but they are not a universal operator override.

Secure the host and secrets

๐Ÿ”‘ Protect secrets Keep .env, Localtonet device tokens, SMTP credentials, backup keys, and recovery codes out of repositories, logs, shell history, and screenshots.
๐Ÿ›ก๏ธ Patch the host Apply supported operating-system, Docker, Vaultwarden, and Localtonet client updates through a reviewed maintenance process.
๐Ÿšช Minimize listeners Keep Vaultwarden bound to 127.0.0.1 unless a documented architecture requires a broader listener.
๐Ÿ‘ค Limit administrators Restrict Docker and host administration to trusted users. Docker control is effectively root-level access to the host.
๐Ÿ’พ Encrypt backups Backups contain encrypted vault records, metadata, configuration, keys, and potentially credentials. Treat them as sensitive security assets.
๐Ÿ“‹ Review logs safely Inspect authentication and startup errors without uploading complete logs that may contain account identifiers, addresses, or configuration details.

Why this guide does not publish a Fail2Ban sidecar

A working Fail2Ban design requires the application log to contain the real client IP, a verified trusted-proxy configuration, and a ban action that can actually block the traffic path. With a relay or reverse proxy in front of Vaultwarden, the observed address may be a relay or proxy address instead of the user. A mistaken filter can ban infrastructure, ban nothing useful, or create a false sense of protection.

The previous configuration also granted a floating third-party container NET_ADMIN and NET_RAW capabilities. Those privileges materially increase its impact if compromised. This revision removes that configuration. Do not deploy Fail2Ban for this architecture until you have verified real client-IP propagation end to end, documented which proxy addresses are trusted, tested the exact Vaultwarden log format, pinned and reviewed the filtering software, and proved that a test ban blocks only the intended client.

Connect and test Bitwarden clients

Install an official Bitwarden client from its normal distribution channel. Before logging in, select the client's self-hosted server option and enter the exact Localtonet HTTPS URL. Labels and menu placement can change between browser, desktop, iOS, and Android releases, so use the current self-hosted server field rather than relying on a fixed sequence of UI labels.

1

Set the self-hosted URL

Enter the assigned HTTPS origin without adding /admin, an API path, or a trailing private route. Confirm the client accepts the certificate without a trust warning.

2

Log in and complete two-step login

Use the vault account email and master password, not the Vaultwarden administration password. Complete the configured second factor.

3

Test synchronization in both directions

Create a harmless test item in one client, synchronize another client, edit the item there, and verify that the first client receives the change.

4

Test required features

If you depend on organizations, collections, attachments, Sends, WebAuthn, emergency access, or another advanced workflow, test that feature with the exact client versions you will deploy.

If a newly updated client behaves differently, check Vaultwarden's current compatibility discussions before changing security settings. โ€œCompatible with official clientsโ€ does not guarantee that every new official feature is available immediately.

Verify the complete deployment

A successful container start is only the first check. Complete the following acceptance tests before importing real credentials or depending on the service.

Test How to perform it Expected result
Local reachability Request http://127.0.0.1:8080 from the host and inspect the container state. Vaultwarden responds locally and the container remains healthy enough to serve requests.
Public HTTPS and certificate Open the assigned URL from a separate network and inspect the certificate hostname, validity period, and trust chain. No warning, expiry error, hostname mismatch, or incomplete-chain error appears.
Account login Log in through the web vault and at least one native client. Authentication and the configured second factor complete successfully.
Synchronization Create and edit a harmless test item across two clients. Both clients receive the changes after synchronization.
Registration closure Use a private browser session after setting SIGNUPS_ALLOWED=false. An unauthenticated visitor cannot create an unrestricted new account.
Restart persistence Restart the container, then perform a planned host reboot during a maintenance window. The original test vault remains present and the container returns without creating an empty data directory.
Tunnel state Check that the selected client is connected and the tunnel is started after restart. The assigned URL returns only after all required components are active.
Failure behavior Separately stop the tunnel, disconnect the Localtonet client, and stop Vaultwarden, restoring each component after the test. Remote access fails as expected in every case and returns only when the missing dependency is restored.
Restore test Restore a backup into an isolated test directory or host. Users can log in and verify test records, attachments, Sends, settings, and required keys without altering production.

Raspberry Pi deployment and safe external storage

Vaultwarden publishes container images intended for self-hosted use, but support for a particular Raspberry Pi depends on the current image architecture, the installed 64-bit operating system, Docker support, and available storage. Check the host architecture before pulling the image:

uname -m
docker info --format '{{.Architecture}}'
lsblk -f

An ARM64 system commonly reports aarch64. Do not rely on old memory figures or assume that every Pi model and operating-system combination is supported. Verify the current Vaultwarden image tags and Docker platform support for your hardware.

Move existing data to an external drive safely

Never assume the external disk is /dev/sda1, never assume its filesystem is ext4, and never edit /etc/fstab before validating the correct filesystem and UUID. Changing the Compose mount without copying existing data can make an established vault appear empty because Vaultwarden starts against a new blank directory.

1

Create and verify a current backup

Complete the backup procedure in the next section and verify that its SQLite snapshot opens. Do not begin a storage migration with the only copy of the vault on the source card.

2

Identify the correct filesystem

Connect the external drive and inspect device names, filesystem types, labels, UUIDs, sizes, and existing mount points.

lsblk -f
sudo blkid
findmnt

Match the device by size, label, and UUID. Stop if the identity is ambiguous.

3

Stop Vaultwarden

Prevent database and attachment changes while migrating the complete data directory.

cd "$HOME/vaultwarden"
docker compose down
4

Mount and validate the destination

Create a mount point, mount the identified filesystem using the correct device or UUID, and verify it with findmnt. Substitute the verified device for the placeholder.

sudo mkdir -p /mnt/vault-storage
sudo mount /dev/verified-partition /mnt/vault-storage
findmnt /mnt/vault-storage
df -h /mnt/vault-storage
5

Copy data while preserving metadata

Use rsync with archive semantics. A trailing slash on the source copies the directory contents into the destination.

sudo mkdir -p /mnt/vault-storage/vw-data
sudo rsync -aHAX --numeric-ids "$HOME/vaultwarden/vw-data/" /mnt/vault-storage/vw-data/
sudo rsync -aHAXn --delete --numeric-ids "$HOME/vaultwarden/vw-data/" /mnt/vault-storage/vw-data/

The dry run should show no unexplained differences. Inspect ownership and permissions with ls -la on both directories.

6

Add and test the persistent mount

Back up /etc/fstab, then add an entry using the verified UUID and filesystem type. The exact options depend on that filesystem and host. Test the file before rebooting.

sudo cp /etc/fstab /etc/fstab.pre-vaultwarden
sudoedit /etc/fstab
sudo umount /mnt/vault-storage
sudo mount -a
findmnt /mnt/vault-storage

If mount -a reports an error or the expected filesystem is absent, restore the backup and correct the entry before proceeding.

7

Change the Compose mount only after validation

Replace ./vw-data:/data with the verified destination path:

volumes:
  - /mnt/vault-storage/vw-data:/data

Do not delete or rename the original source directory yet.

8

Restart and confirm the original vault

Start Vaultwarden, inspect logs, and log in to verify known records and attachments.

docker compose up -d
docker compose ps
docker compose logs --tail=100 vaultwarden

Retain the original data and verified backup until the new mount has survived a planned reboot and a complete application check.

Back up and restore Vaultwarden correctly

Vaultwarden backup and restore test covering the complete persistent data set.
A usable backup includes all persistent data and is verified through a test restore.

Backups must cover more than db.sqlite3. A recoverable Vaultwarden set includes a consistent SQLite snapshot, attachments, Sends, signing keys, persisted configuration, and the secrets needed to reconstruct the deployment. The environment file, SMTP credentials, device tokens, and backup keys are sensitive and should not be copied into an unencrypted backup directory.

Component Purpose Recovery treatment
db.sqlite3 Vault records, users, organizations, and related application state. Create a consistent SQLite snapshot rather than copying only the live main database file.
attachments/ Files attached to vault items. Copy recursively and restore with the database.
sends/ Stored files associated with Sends. Copy recursively if present.
rsa_key* Server signing-key material. Preserve all matching files and their permissions.
config.json Settings persisted through the administration interface. Restore deliberately because these settings can override or interact with environment configuration.
.env and deployment definition Admin hash, public domain, signup policy, and other deployment settings. Store only in an encrypted secret backup with tightly controlled access.

Install the backup prerequisites

The host needs the sqlite3 command-line client and rsync. Install those packages from your operating system's signed package repository. Verify them before scheduling a backup:

sqlite3 --version
rsync --version

Create a consistent backup set

The SQLite .backup command creates a consistent database snapshot while Vaultwarden is running. The other directories can still change during a live copy, so schedule backups during a quiet period. For the strongest cross-file consistency, stop Vaultwarden briefly before copying attachments, Sends, keys, and configuration, or use a storage snapshot mechanism whose consistency you have tested.

#!/bin/sh
set -eu
umask 077

PROJECT="$HOME/vaultwarden"
DATA="$PROJECT/vw-data"
ROOT="$HOME/vaultwarden-backups"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
DEST="$ROOT/$STAMP"

command -v sqlite3 >/dev/null
command -v rsync >/dev/null

mkdir -p "$DEST"

sqlite3 "$DATA/db.sqlite3" ".timeout 10000" ".backup '$DEST/db.sqlite3'"

for directory in attachments sends; do
  if [ -d "$DATA/$directory" ]; then
    rsync -aH --numeric-ids "$DATA/$directory/" "$DEST/$directory/"
  fi
done

if [ -f "$DATA/config.json" ]; then
  cp -p "$DATA/config.json" "$DEST/config.json"
fi

for key in "$DATA"/rsa_key*; do
  if [ -e "$key" ]; then
    cp -p "$key" "$DEST/"
  fi
done

sqlite3 "$DEST/db.sqlite3" "PRAGMA integrity_check;"
find "$DEST" -maxdepth 2 -type f -print
echo "Backup staging set created at: $DEST"

The integrity check must report ok. Save this script outside the public service path, make it executable only by its owner, and run it manually before scheduling it.

The staging directory is not a complete secure backup strategy

Encrypt the backup before copying it off-host, protect the encryption key separately, and retain at least one copy that is not continuously writable by the Vaultwarden host. Backups can expose account metadata, server configuration, signing keys, attachments, and secrets. Encrypted vault records can also become an offline password-guessing target. The absence of a plaintext master password does not make a backup safe to disclose.

Back up .env, compose.yaml, Localtonet recovery information, and any SMTP configuration only inside the encrypted archive or secret-management system. Do not mix unencrypted secret copies into the ordinary backup staging directory. Define retention based on your recovery objectives, available storage, and need to recover from delayed corruption or accidental deletion.

Restore into an isolated test location

A backup is not proven until it has been restored. The safest recurring test uses an isolated host or a separate project directory and port. Never point a test container at the production data directory.

1

Verify and decrypt the selected backup

Confirm the archive's integrity using the mechanism provided by your encryption tool. Extract it into a protected temporary directory and verify the SQLite snapshot:

sqlite3 /protected/restore-source/db.sqlite3 "PRAGMA integrity_check;"
2

Stop the target Vaultwarden instance

For a production recovery, stop the target container before replacing any file. Preserve the failed data directory for investigation instead of deleting it immediately.

cd "$HOME/vaultwarden"
docker compose down
mv vw-data "vw-data.before-restore.$(date -u +%Y%m%dT%H%M%SZ)"
mkdir vw-data
chmod 700 vw-data
3

Restore every required component

Copy the database, attachments, Sends, keys, and configuration while preserving metadata.

cp -p /protected/restore-source/db.sqlite3 "$HOME/vaultwarden/vw-data/"
rsync -aH --numeric-ids /protected/restore-source/attachments/ "$HOME/vaultwarden/vw-data/attachments/"
rsync -aH --numeric-ids /protected/restore-source/sends/ "$HOME/vaultwarden/vw-data/sends/"
cp -p /protected/restore-source/config.json "$HOME/vaultwarden/vw-data/"
cp -p /protected/restore-source/rsa_key* "$HOME/vaultwarden/vw-data/"

Skip only components that were genuinely absent from the source. Restore the protected environment and deployment secrets through your encrypted secret-recovery process.

4

Check ownership and permissions

Compare the restored directory with the preserved pre-restore directory or a known-good deployment. Do not apply a guessed numeric user ID. The required ownership can depend on the image and host setup.

ls -la "$HOME/vaultwarden/vw-data"
find "$HOME/vaultwarden/vw-data" -maxdepth 2 -printf '%M %u:%g %p\n'
5

Start and validate the restored vault

Start the target, inspect logs, then test login, synchronization, attachments, Sends, settings, and account records.

docker compose up -d
docker compose ps
docker compose logs --tail=200 vaultwarden

For a test restore, keep it isolated from production clients and mail delivery. Record the date, selected backup, result, and any manual recovery step.

Migrate an existing Bitwarden vault carefully

Review the current export choices in the Bitwarden client before creating a migration file. Encrypted JSON exports can use different protection models. A password-protected encrypted export is designed to be unlocked with the export password and is the appropriate encrypted form when portability is required. An account-restricted encrypted export is tied to the originating account and is not interchangeable with a portable password-protected export.

If the target importer does not support the selected encrypted format, a plaintext export may be required. Perform that operation only on a trusted, patched device, keep the file on encrypted storage, disconnect unnecessary synchronization or backup software, import it promptly, and securely remove temporary copies afterward. Confirm the import before deleting the source account.

Vault exports may not include every service object. Attachments and Sends require separate handling, and organization data can have its own export and import rules. Compare item counts and manually verify representative logins, secure notes, identities, cards, custom fields, organization collections, attachments, and two-factor records. There is no reliable universal migration-duration estimate.

Routine operation, updates, and rollback planning

Daily and weekly checks

  • Confirm the Vaultwarden container is running and review new startup or authentication warnings.
  • Confirm the Localtonet device is connected and the tunnel is started.
  • Test the public URL and certificate before certificate expiry becomes urgent.
  • Confirm scheduled backups completed, were encrypted, and reached the off-host destination.
  • Monitor disk capacity for the data directory, Docker storage, logs, attachments, and backup staging.
  • Review account enrollment, administration access, and whether public registration remains closed.

Review updates before applying them

A moving image tag changes when pulled. Before an update, read Vaultwarden release notes, check client-compatibility reports relevant to your environment, create and verify a fresh backup, and record the current image identifier:

cd "$HOME/vaultwarden"
docker compose images
docker image inspect vaultwarden/server:latest --format '{{index .RepoDigests 0}}'
docker compose logs --tail=100 vaultwarden

During a maintenance window, pull the reviewed image, recreate the service, and inspect logs:

docker compose pull vaultwarden
docker compose up -d vaultwarden
docker compose ps
docker compose logs --tail=200 vaultwarden

Then repeat certificate, login, synchronization, registration, and attachment tests. Do not automate unattended pulls for a password manager unless your organization has a tested update, monitoring, and rollback process.

Plan rollback before updating

Retain the previous image reference and the pre-update backup. Database migrations can make a simple image downgrade unsafe. If the new release changes the database in an incompatible way, rollback may require stopping the service, restoring the complete pre-update data set and required secrets, and starting the previously tested image. Document that process before the maintenance window.

Understand outage behavior

Component stopped Public behavior Recovery action
Vaultwarden container The tunnel can remain present, but the local target cannot serve vault requests. Inspect Compose state and Vaultwarden logs, correct the application or storage issue, then retest login and sync.
Localtonet client The relay cannot reach the local target through that device. Restore the selected client connection and protect its device token.
HTTP tunnel The assigned public endpoint is unavailable even if Vaultwarden is healthy locally. Start the existing tunnel and verify its selected device and relay server.
Host or storage Both Vaultwarden and the local tunnel client may disappear. An unmounted data disk can also cause an empty directory or startup failure. Validate filesystems and mounts before starting containers, then confirm the original vault is present.

Evidence-based troubleshooting

Symptom Checks Safe response
Public URL is unavailable Test 127.0.0.1:8080, check the container, confirm the selected Localtonet client is connected, and confirm the tunnel is started. Restore the first failed dependency. Creating a new tunnel is not necessary if the existing tunnel is merely stopped.
Certificate warning or native-client trust error Inspect hostname, validity dates, certificate chain, device clock, and the exact URL configured in the client. Correct the certificate or URL. Never train users to bypass a password-manager certificate warning.
Administration login fails Confirm that you entered the original admin password rather than the PHC hash. Review logs for interpolation or persisted-configuration warnings. Correct the effective configuration without printing the secret. Remember that config.json can contain settings saved through the admin interface.
Argon2 value is malformed Confirm the complete generated value is single-quoted in .env, the file has no accidental line break, and Compose is using only env_file. Regenerate the hash if necessary. Avoid resolved Compose output in tickets because it can expose secrets.
Client login works but synchronization fails Verify the self-hosted URL, public certificate, tunnel access controls, outer authentication layers, and compatibility of the exact client version. Remove an incompatible outer challenge only after reviewing exposure. Test the bundled web vault and consult Vaultwarden compatibility reports.
Vault appears empty after moving storage Stop the container and use findmnt to confirm the external filesystem is mounted at the expected path. Compare the old and new data directories. Do not create new records. Restore the correct mount or revert the Compose path, then verify the original database and attachments.
Container cannot write to /data Inspect mount state, filesystem permissions, ownership, read-only flags, and logs. Compare with the known-good source. Do not recursively assign a guessed user ID or grant world-writable permissions.
Backup database fails integrity check Confirm the source filesystem is healthy, sufficient space exists, and the snapshot was made with SQLite's backup command. Preserve the failed set for investigation, create a new snapshot, and do not delete the last known-good off-host backup.
Attachments are missing after restore Check whether attachments/ was included, restored to the correct data directory, and readable by the container. Stop the service, restore the matching attachments directory from the same backup set, verify permissions, and retest.

Frequently asked questions

Is Vaultwarden fully compatible with every Bitwarden client?

No permanent universal guarantee should be assumed. Vaultwarden describes itself as a nearly complete implementation of the Bitwarden Client API and is designed for use with official clients. New client releases and features can introduce temporary or lasting differences. Test the exact browser, desktop, mobile, and feature combinations you require.

Can the server administrator recover a forgotten master password?

Do not assume that the operator can decrypt a user's vault or simply reveal a forgotten master password. Recovery can depend on client or organization features configured before the loss, and those workflows are not a universal administrative override. Preserve the master password and two-factor recovery material securely outside the server.

Are Vaultwarden backups safe because vault records are encrypted?

No. Backups remain sensitive. They can contain encrypted records, account metadata, attachments, Sends, signing keys, administration configuration, and deployment secrets. They can also provide material for offline password guessing. Encrypt backups, keep a protected off-host copy, control the encryption key separately, and test restoration.

Do I need to own a domain?

No. A Localtonet HTTP tunnel can provide an assigned public HTTPS address using a generated subdomain. Custom subdomains and custom domains may also be available depending on current product and plan behavior. Use the exact URL displayed by the dashboard and do not assume a fixed hostname pattern.

Does Localtonet make Vaultwarden permanently available?

Availability depends on more than creating a tunnel. Vaultwarden must be running, the selected Localtonet client must remain connected, and the tunnel must be started. Relay availability and plan-specific timeout or availability behavior also apply. Confirm current plan terms for an always-on deployment.

Is the connection HTTPS all the way into Vaultwarden?

Not in this tutorial. The remote client uses HTTPS to the public endpoint, and traffic travels through the outbound Localtonet tunnel. The Localtonet client then connects to Vaultwarden over HTTP at 127.0.0.1:8080. Keeping both processes on the same trusted host confines that final HTTP hop to loopback.

Can Vaultwarden run on a Raspberry Pi?

It can run on compatible Raspberry Pi hardware when the current Vaultwarden image supports the architecture and the host uses a Docker-supported operating system. Use a maintained 64-bit installation, verify the architecture and image support, provide reliable storage, and avoid relying on old model-specific memory claims.

Which encrypted export should I use for migration?

Use a password-protected encrypted export when you need a portable encrypted file and the target importer supports it. An account-restricted encrypted export is tied to the originating account and should not be assumed portable to another server. Attachments, Sends, and organization data may require separate migration steps.

Publish your loopback-only Vaultwarden through Localtonet

Install Vaultwarden, verify it locally, then create an HTTP tunnel to 127.0.0.1:8080. Keep the device connected, explicitly start the tunnel, validate the assigned HTTPS certificate, and complete the security and restore tests before importing production credentials.

Get Started Free โ†’

Corrections & updates

Substantive changes approved by the Localtonet editorial team are listed transparently below.

Add the required lt-card guide navigation after the hero, give every linked h2 a unique lowercase fragment ID, shorten the hero title so it does not repeat the page H1, convert subsection headings to semantic h3 elements without lt-section-title, remove inline styles and unsupported classes, repair the malformed code block, and retain only approved lt-* components. Rebuild the comparison section around durable, sourced distinctions and remove or date-verify volatile pricing, RAM, container-count, audit, compatibility, and feature-enti

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support