Vaultwarden is a lightweight, community-built server compatible with Bitwarden clients. A Vaultwarden VPS can be inexpensive, but it becomes some of the most sensitive infrastructure you operate: it stores encrypted vaults, account metadata, attachments, recovery material, and sessions. The correct starting point is HTTPS, closed public registration, strong account MFA, and a tested off-server backup.
Vaultwarden is not the official Bitwarden server and is not operated or supported by Bitwarden. Review its project status and license before using it for an organization or regulated data.
Vaultwarden VPS requirements and LayerOne cost
| Item | Practical starting point |
|---|---|
| Minimum RAM | 1 GB for a personal instance with SQLite |
| Recommended RAM | 2 GB for OS and container update headroom and several active users |
| Expected CPU usage | Usually below 2% of one vCPU at idle; brief 10–40% bursts during login, sync, key derivation, and large attachment transfers |
| Storage requirement | 10 GB minimum; 20 GB or more if users store attachments or Sends |
| Exact LayerOne SKU | gc.micro — catalog slug layerone-starter, 1 vCPU, 2 GB RAM, 40 GB disk |
| Expected monthly cost | $5.00/month equivalent, metered at $0.0068/hour while the VPS exists |
Vaultwarden does not publish a universal RAM or CPU minimum. These are
conservative operating estimates for the Compose stack below, not performance
guarantees. User count, Argon2 settings, attachments, icons, audit activity, and
backup jobs change the result. Measure the real workload with docker stats
and the VPS monitoring guide.
LayerOne bills by the hour. The monthly equivalent assumes a continuously existing server and excludes optional services and usage that varies. Check Pricing for the current catalog before deployment.
Before you install
This guide targets a fresh Ubuntu 24.04 LTS VPS. Complete
Your first hour on a new server, install Docker from
Running Docker, and create a DNS A record such as
vault.example.com pointing to the VPS.
Use a dedicated hostname. Bitwarden web clients require a secure browser
context, so a raw public http://SERVER_IP deployment is not a usable or safe
production endpoint.
1. Start with a closed firewall
In the LayerOne Networking tab, use inbound DROP and outbound ACCEPT.
Initially allow TCP 22 only from your administration address. Add public TCP 80
and 443 only after the first account has been created locally. See
The cloud firewall.
Mirror the policy in UFW:
sudo apt update
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from YOUR.ADMIN.IP.ADDRESS to any port 22 proto tcp
sudo ufw enable
sudo ufw status verbose
Keep the browser console open until a new SSH
login works. Docker can bypass UFW for published container ports, so the
LayerOne cloud firewall remains essential. The temporary Vaultwarden port in
this guide binds to 127.0.0.1 and is never public.
2. Create the Compose project
sudo mkdir -p /opt/vaultwarden/data
sudo chown -R "$USER":"$USER" /opt/vaultwarden
cd /opt/vaultwarden
Create /opt/vaultwarden/compose.yaml:
services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "true"
volumes:
- ./data:/data
ports:
- "127.0.0.1:8000:80"
expose:
- "80"
caddy:
image: caddy:2-alpine
restart: unless-stopped
depends_on:
- vaultwarden
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Replace vault.example.com with the hostname you control. The official project
publishes its supported stable container as vaultwarden/server:latest; review
release notes and pin a tested version if your change policy requires explicit
versions.
Create /opt/vaultwarden/Caddyfile:
vault.example.com {
encode zstd gzip
reverse_proxy vaultwarden:80
}
Validate the stack, but start only Vaultwarden for now:
cd /opt/vaultwarden
docker compose config --quiet
docker compose up -d vaultwarden
docker compose logs --tail=100 vaultwarden
3. Create the first account without public registration
From your own computer, open an SSH tunnel to the loopback-only port:
ssh -L 8000:127.0.0.1:8000 admin@SERVER_IP
Leave that session open and visit http://localhost:8000 in the local browser.
localhost is treated as a secure development context by modern browsers.
Register the one intended owner account, sign in, and confirm the vault opens.
Then edit compose.yaml and change:
SIGNUPS_ALLOWED: "false"
Do not set ADMIN_TOKEN unless you actually need the separate Vaultwarden admin
panel. Omitting it keeps that privileged interface disabled. Validate and
recreate the service:
cd /opt/vaultwarden
docker compose config --quiet
docker compose up -d vaultwarden
docker compose logs --tail=50 vaultwarden
The registration form may still appear in clients, but the server must reject
new accounts after SIGNUPS_ALLOWED=false is active.
4. Publish HTTPS and verify the boundary
Now add TCP 80 and 443 from 0.0.0.0/0 to the LayerOne cloud firewall and UFW:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status verbose
cd /opt/vaultwarden
docker compose up -d
docker compose ps
docker compose logs --tail=100 caddy vaultwarden
Open https://vault.example.com, sign in as the existing user, install a
Bitwarden client, and perform a two-way test: add a disposable item on one
client, sync it to another, edit it, and sync back.
Confirm TLS and socket exposure:
curl -fsSI https://vault.example.com
sudo ss -lntp | grep -E ':(80|443|8000)[[:space:]]'
docker compose ps
Port 8000 should appear only on 127.0.0.1; 80 and 443 are the only public web
ports. Enable two-step login for every vault user and save recovery codes away
from the VPS and away from the vault they recover.
5. Back up everything needed for recovery
A client export is useful, but it is not a server backup: it may omit attachments, organizations, Sends, and server configuration. The simplest consistent small-instance backup is a brief stop and an archive of the whole data directory:
cd /opt/vaultwarden
docker compose stop vaultwarden
sudo tar -C /opt/vaultwarden -czf "/root/vaultwarden-$(date -u +%Y%m%dT%H%M%SZ).tar.gz" data compose.yaml Caddyfile
docker compose start vaultwarden
Encrypt the archive and move it off the VPS immediately. Vaultwarden's data can include plaintext account email addresses and two-factor material as well as encrypted vault content. Store the backup password or key separately. LayerOne does not back up the VPS; see Backups and snapshots.
For a restore, deploy the same or a compatible Vaultwarden version, stop the
container, replace /opt/vaultwarden/data with the saved directory, preserve
its ownership and permissions, and start Vaultwarden. Test login, attachment
download, client sync, organization access, and MFA before calling the restore
successful. Perform this test on an isolated hostname so clients cannot write
to both copies.
6. Update without risking the vault
Read Vaultwarden's release notes, make and copy off a fresh backup, then:
cd /opt/vaultwarden
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 vaultwarden
Verify the reported version, browser login, client sync, attachment access, and one new disposable item. Do not prune the previous image or delete the backup until those checks pass. Keep Ubuntu and Docker patched as separate maintenance tasks.
Security checklist
- Keep
SIGNUPS_ALLOWED=falseexcept for a deliberately controlled enrollment window. Prefer invitations for additional users. - Never use
DISABLE_ADMIN_TOKEN=true; it makes the admin panel unauthenticated. - Use HTTPS only, a unique long master password, account MFA, and recovery codes stored offline.
- Treat anyone with root access, Docker control, or backup access as a highly privileged operator even though vault item bodies are encrypted.
- Do not expose a database port. SQLite stays inside
/datain this design. - Configure SMTP if you depend on invitations, email verification, or event notices, and test delivery without weakening TLS validation.
- Monitor free space and backup growth. Attachments can consume the 40 GB disk much faster than vault text records.