Passwords · no KYC
Host Vaultwarden on an Offshore VPS
Run your own Bitwarden-compatible password vault on hardware you control, in a privacy-friendly jurisdiction, paid in crypto with no identity attached.
What it is
Vaultwarden is a lightweight, unofficial Bitwarden server written in Rust that speaks the same API as Bitwarden, so all official Bitwarden clients (browser extensions, desktop, iOS/Android, CLI) sync against it. It stores encrypted vaults for passwords, passkeys, TOTP seeds, cards, and secure notes, with organizations, attachments, and admin controls, while using a fraction of the RAM of the official stack.
Why host it offshore
Your password vault is the single most sensitive asset you own, so who holds the server and under what law matters as much as the crypto. A no-KYC, crypto-paid VPS in a privacy-tier location (NL/CH/RO/IS) means the box that stores your encrypted vaults is not tied to your legal identity, is not subject to a US/UK subpoena, and cannot be locked by a payment provider deplatforming you.
The deploy
A working reference setup
Copy this onto a fresh ChainVPS instance. Replace the placeholders, then bring it up.
# 1) DNS: point vault.example.com -> your ChainVPS IP (A/AAAA record)
# 2) Generate an Argon2 ADMIN_TOKEN (do NOT use a plain string):
# docker run --rm -it vaultwarden/server /vaultwarden hash
# paste the resulting '$argon2id$...' string as ADMIN_TOKEN below (single-quote it in .env)
# 3) Save as docker-compose.yml, create the Caddyfile shown, then: docker compose up -d
services:
vaultwarden:
image: vaultwarden/server:1.32.7
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com" # must match the public URL exactly
SIGNUPS_ALLOWED: "false" # create your account, then keep this false
INVITATIONS_ALLOWED: "true"
ADMIN_TOKEN: "${ADMIN_TOKEN}" # Argon2 hash from step 2, kept in .env
WEBSOCKET_ENABLED: "true" # live sync (served on the main port)
SENDS_ALLOWED: "true"
ROCKET_PORT: "80"
volumes:
- ./vw-data:/data # vaults, attachments, sqlite db, keys
networks: [vw]
# no host port published: only Caddy talks to it over the internal network
caddy:
image: caddy:2
container_name: vaultwarden-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-data:/data
- ./caddy-config:/config
networks: [vw]
depends_on: [vaultwarden]
networks:
vw:
# ---- Caddyfile (same directory) ----
# vault.example.com {
# encode gzip
# reverse_proxy vaultwarden:80
# }
# Caddy fetches and renews a Let's Encrypt cert automatically; HTTPS is mandatory
# because Bitwarden clients use WebCrypto, which only runs on a secure origin.
Firewall
Ports to open
| Port | Protocol | Purpose |
|---|---|---|
| 443 | TCP | HTTPS vault + client sync + WebSocket (via Caddy); the only port that must be public |
| 80 | TCP | HTTP -> HTTPS redirect and ACME/Let's Encrypt certificate issuance |
| 443 | UDP | Optional HTTP/3 (QUIC) for faster client sync |
Right-sizing
Which plan you need
VPS Nano/Small (1 vCPU, 1-2 GB RAM)
Vaultwarden idles around 15-30 MB RAM on SQLite; a Nano is comfortable. Storage is tiny unless you store big attachments.
VPS Pro (2 vCPU, 4 GB RAM)
Headroom for concurrent syncs, attachments, and running Caddy plus fail2ban/backups on the same box.
VPS Pro (high tier) or entry Dedicated
Move from SQLite to Postgres/MySQL and put attachments on a Storage plan or larger disk; dedicated CPU keeps sync latency flat under load.
Best locations: Choose a ChainVPS privacy-tier location for a vault: Switzerland (CH) and Iceland (IS) have strong data-protection and privacy traditions, the Netherlands (NL) offers excellent connectivity with EU privacy law, and Romania (RO) or Moldova (MD) sit outside the strictest surveillance-sharing blocs. Pick the one geographically closest to where you and your users sync from to minimize latency, since the vault is encrypted client-side either way.
Lock it down
Hardening checklist
- Keep SIGNUPS_ALLOWED=false after creating your account and use INVITATIONS to add users; an open signup endpoint on a public vault is a magnet for abuse.
- Always set ADMIN_TOKEN to an Argon2 hash generated with 'vaultwarden hash' (never a plaintext string), or disable the /admin panel entirely by leaving ADMIN_TOKEN unset once configured. Consider firewalling /admin to your IP.
- Enforce HTTPS only and let Caddy manage Let's Encrypt certs; Bitwarden clients refuse to run crypto over plain HTTP, and a valid cert prevents downgrade/MITM on sync.
- Back up the ./vw-data directory (especially rsa_key.pem, config.json, db.sqlite3, and attachments) on a schedule to an off-box location such as a ChainVPS Storage plan; losing rsa_key.pem invalidates all existing sessions/tokens.
- Run fail2ban against Vaultwarden's log (LOG_FILE + LOG_LEVEL) to ban brute-force login attempts, and require every user to enable 2FA; expose only 80/443 via ufw/nftables and drop everything else.
Deploy it on
The right ChainVPS product
Questions
Hosting Vaultwarden — FAQ
Is Vaultwarden the same as Bitwarden?
It is a separate, lightweight server implementation of the Bitwarden API. It is not made by Bitwarden Inc., but the official Bitwarden apps and extensions work against it, and it supports vaults, organizations, attachments, Sends, and passkeys. It is ideal for individuals and small teams who want self-hosting without the resource footprint of the official server stack.
Is my data safe if the server is seized or the host is compromised?
Vaults are encrypted and decrypted client-side with a key derived from your master password, so the server only ever stores ciphertext. Hosting on a no-KYC box in a privacy-friendly jurisdiction reduces who can compel access, but you still must use a strong master password, enable 2FA, and keep DOMAIN on HTTPS to protect the login flow itself.
Do I need HTTPS, or can I use a plain IP?
You need HTTPS with a valid certificate and a domain name. Bitwarden clients use the browser WebCrypto API, which only functions on a secure origin, so a plain http:// or bare-IP setup will fail to sync. The included Caddy service issues and renews a free Let's Encrypt certificate automatically.
SQLite or MySQL/Postgres?
SQLite (the default) is perfectly fine and fastest for personal use and small teams up to a few dozen users. Switch to MySQL or PostgreSQL only for large multi-org deployments or when you want centralized DB backups and replication; set DATABASE_URL accordingly.
How do I add users without opening public signups?
Keep SIGNUPS_ALLOWED=false and INVITATIONS_ALLOWED=true, then invite users from an Organization (or via the /admin panel). Invited users receive an invite and can register even though public signup is closed, which keeps the endpoint from being abused.
Can I pay for the VPS without giving ID?
Yes. ChainVPS is no-KYC and accepts cryptocurrency, so the server holding your encrypted vaults is not tied to your legal identity or a card processor that could freeze the account.
More to self-host
Other one-click stacks
Spin up Vaultwarden
in the next 60 seconds.
Unmetered bandwidth · DDoS included · 21 cryptocurrencies · no KYC.