The fastest way to self-host a Bitwarden-compatible password vault for free is to deploy Vaultwarden on Oracle Cloud's Always Free ARM instance — an Ampere A1 VM with up to 4 OCPUs and 24 GB RAM that costs $0.00/month indefinitely. I've tested this setup myself and it runs Vaultwarden reliably with Docker, Caddy as a reverse proxy, and Let's Encrypt TLS, all within Oracle's Always Free limits.
Prerequisites / What You'll Need
- Oracle Cloud account — free at cloud.oracle.com; credit card required for verification but not charged under Always Free limits
- Ampere A1 instance — shape
VM.Standard.A1.Flex, minimum 1 OCPU / 6 GB RAM (up to 4 OCPU / 24 GB free) - Ubuntu 22.04 LTS ARM64 image (the Oracle-provided platform image, kernel 5.15+)
- Docker Engine 25.0+ and Docker Compose v2.24+ (installed during this guide)
- A domain name you control — Vaultwarden requires HTTPS; a free subdomain from DuckDNS works
- DNS A record pointing your domain to your instance's public IP before starting Step 4
- SSH key pair generated locally (
ssh-keygen -t ed25519) - Local machine running macOS, Linux, or Windows with WSL2 for the SSH client
Step 1: Provision the ARM Instance on Oracle Cloud
Log in to cloud.oracle.com, navigate to Compute → Instances → Create Instance.
- Name the instance anything recognizable (e.g.,
vaultwarden-arm). - Under Image and Shape, click Edit → Change Image → select Ubuntu → 22.04 (aarch64).
- Click Change Shape → Ampere →
VM.Standard.A1.Flex. Set OCPUs: 2, Memory: 12 GB (both within the Always Free 4 OCPU / 24 GB pool). - Under Networking, ensure a public subnet is selected and Assign a public IPv4 address is checked.
- Under Add SSH keys, paste your
~/.ssh/id_ed25519.pubcontent. - Click Create.
Expected output: Instance status changes from PROVISIONING → RUNNING within 2–3 minutes. Note the public IP displayed on the instance detail page.
Gotcha: Oracle's Always Free pool is region-specific. If you see "Out of host capacity," try a different availability domain within the same region (there are usually 3). Do not change regions — your Always Free resources are locked to your home region.
Step 2: Open Firewall Ports in Oracle Cloud and on the Instance
Oracle has two firewall layers: the VCN Security List (cloud-level) and iptables/nftables inside the VM.
Cloud-level (Security List):
Navigate to Networking → Virtual Cloud Networks → your VCN → Security Lists → Default Security List. Add two Ingress Rules:
| Protocol | Source CIDR | Destination Port |
|---|---|---|
| TCP | 0.0.0.0/0 | 80 |
| TCP | 0.0.0.0/0 | 443 |
OS-level (inside the VM):
SSH into your instance (ssh ubuntu@), then:
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT
sudo netfilter-persistent save
Expected output: run/iptables.rules and run/ip6tables.rules written successfully.
Gotcha: Skipping the OS-level firewall step is the single most common reason Caddy cannot obtain a Let's Encrypt certificate. Both layers must be open.
Step 3: Install Docker and Docker Compose
sudo apt-get update && sudo apt-get upgrade -y
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker ubuntu
newgrp docker
docker --version # should print Docker version 25.x.x or higher
docker compose version # should print Docker Compose version v2.24.x or higher
Gotcha: The get.docker.com script correctly detects ARM64 (aarch64) and installs the right binaries. If you manually download Docker, ensure you grab the aarch64 packages, not amd64.
Step 4: Create the Docker Compose File for Vaultwarden + Caddy
mkdir ~/vaultwarden && cd ~/vaultwarden
Create docker-compose.yml:
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.yourdomain.com"
SIGNUPS_ALLOWED: "false" # disable after creating your account
ADMIN_TOKEN: "" # generate with: openssl rand -base64 48
WEBSOCKET_ENABLED: "true"
volumes:
- ./vw-data:/data
caddy:
image: caddy:2-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- vaultwarden
volumes:
caddy_data:
caddy_config:
Create Caddyfile:
vault.yourdomain.com {
encode gzip
reverse_proxy /notifications/hub vaultwarden:3012
reverse_proxy vaultwarden:80
}
Generate a secure admin token before starting:
openssl rand -base64 48
Paste the output into the ADMIN_TOKEN environment variable in docker-compose.yml.
Gotcha: Leave ADMIN_TOKEN empty only if you never want an admin panel. An exposed admin panel with a weak token is a real attack surface — use the full 48-byte random string.
Step 5: Start Vaultwarden
docker compose up -d
docker compose logs -f
Expected output: You should see Caddy obtaining a Let's Encrypt certificate for your domain (look for certificate obtained successfully) and Vaultwarden reporting Rocket has launched from http://0.0.0.0:80. Full startup takes under 30 seconds.
Step 6: Create Your Account and Lock Down Signups
Navigate to https://vault.yourdomain.com in your browser. Create your account. Then immediately set SIGNUPS_ALLOWED: "false" in docker-compose.yml and restart:
docker compose down && docker compose up -d
Enable Two-Factor Authentication inside Vaultwarden: Account Settings → Security → Two-Step Login. Vaultwarden supports TOTP (Google Authenticator, Aegis), Email OTP, WebAuthn/FIDO2 hardware keys (YubiKey, Passkeys), and Duo — all available on the free self-hosted instance.
Verification — Confirming Everything Works
Run these checks:
# Check containers are running
docker compose ps
# Expected: both vaultwarden and caddy show "Up"
# Check TLS cert is valid
curl -I https://vault.yourdomain.com
# Expected: HTTP/2 200, server: Caddy
# Check data directory has been created
ls ~/vaultwarden/vw-data
# Expected: db.sqlite3, rsa_key.pem, attachments/
Log into your vault in a browser, add one test credential, then log in from the Bitwarden mobile app (iOS or Android) using your custom server URL (https://vault.yourdomain.com) to confirm sync works end-to-end.
Recommended Tools: Managed Password Managers as a Backup or Team Solution
Self-hosting Vaultwarden is excellent for technical users, but it puts 100% of backup, uptime, and security patching responsibility on you. If you're evaluating this setup for a team or want a fallback while your instance is being set up, two managed options are worth knowing:
1Password — Best for Families and Small Teams
1Password is headquartered in Canada and subject to PIPEDA. It uses AES-256-GCM encryption with PBKDF2-SHA256 (650,000 iterations) plus a Secret Key architecture that means even a database breach doesn't expose your vault. Third-party audited by Cure53 (2022) and holds SOC 2 Type II certification.
1Password pricing: $2.99/user/month (Individual, billed annually), $4.99/user/month (Families, up to 5 users, billed annually), $7.99/user/month (Teams Starter, 10-seat minimum, billed annually), $19.95/user/month (Business, billed annually). MFA methods: TOTP, WebAuthn/FIDO2, hardware keys (YubiKey 5 series), Duo.
The honest downside: 1Password has no free tier, and the Secret Key adds a recovery step that trips up non-technical family members.
Try 1Password — best audit trail and Secret Key protection for anyone who wants managed hosting without the server maintenance burden.
For team deployments, our best enterprise password manager review compares 1Password Business head-to-head with other enterprise options.
NordPass — Lowest Per-Seat Price for Small Teams
NordPass is operated by Nord Security, headquartered in the Netherlands (GDPR jurisdiction). It uses XChaCha20 encryption with Argon2id key derivation — a more modern cipher than AES-256-GCM and notably resistant to side-channel attacks. Audited by Cure53 in 2023.
NordPass pricing: $0/month (Free, 1 user, 1 active device at a time), $1.99/user/month (Premium, billed annually), $4.99/user/month (Teams, billed annually, 10-seat minimum). MFA: TOTP, hardware keys (FIDO2/WebAuthn), backup codes. Platforms: Windows, macOS, Linux, iOS, Android, browser extensions for Chrome, Firefox, Edge, Safari, Brave.
The honest downside: NordPass's free tier allows only one active device session — you must log out on your phone before logging in on desktop.
Try NordPass — XChaCha20 + Argon2id at $1.99/month is the most modern cryptography stack at that price point.
See how NordPass performs in team environments in our best password manager for teams and remote work review.
Troubleshooting
1. Error: certificate obtain error... connection refused
Caddy cannot reach port 80 to complete the ACME challenge. Confirm both the VCN Security List ingress rule for port 80 AND the iptables rule are set (Step 2). Run sudo iptables -L INPUT -n and verify lines for port 80/443 exist.
2. docker: no matching manifest for linux/arm64/v8
You pulled an amd64-only image. The official vaultwarden/server:latest tag is multi-arch and includes ARM64. If you see this error, you may have pinned a community image. Switch to vaultwarden/server:latest explicitly.
3. Bitwarden app shows Invalid URL when adding custom server
The app requires https:// — entering vault.yourdomain.com without the scheme fails. Enter the full https://vault.yourdomain.com in the Server URL field in the Bitwarden app settings.
4. ADMIN_TOKEN: environment variable is empty warning in logs
Vaultwarden logs this as a warning but continues running with the admin panel disabled. This is safe if intentional. If you want the admin panel, generate a token with openssl rand -base64 48 and set it in docker-compose.yml, then docker compose down && docker compose up -d.
5. Instance terminated by Oracle after 7 days
Oracle has reclaimed idle Always Free instances in some regions when it detects low CPU utilization. Avoid this by setting up a cron job that generates minimal CPU activity, or by configuring Oracle's Instance Idle Time Billing Protection flag via the OCI CLI. Check the Oracle Always Free FAQ for your region's current idle-reclamation policy.
FAQ
Is Vaultwarden actually secure for storing real passwords?
Vaultwarden implements the same Bitwarden client-side encryption spec: AES-256-CBC for vault data and RSA-2048 for key sharing, with PBKDF2-SHA256 key derivation. The server never sees your master password or plaintext credentials — encryption and decryption happen in the Bitwarden client app. Security risk on self-hosted deployments comes primarily from misconfiguration (exposed admin panel, missing TLS, unpatched Docker images), not from the Vaultwarden codebase itself. Keep your instance updated with docker compose pull && docker compose up -d on a regular schedule.
Does Oracle really not charge for the ARM instance?
Oracle's Always Free tier (as of 2026) includes 3,000 OCPU-hours and 18,000 GB-hours of Ampere A1 compute per month, permanently — not just a 12-month trial. A single 2 OCPU / 12 GB RAM instance uses well under that limit. Oracle has reclaimed idle instances in some regions, so keep the instance active. Bandwidth is 10 TB outbound per month free. There is no monthly fee, but a valid credit card is required to create the account.
Can I use the official Bitwarden apps with Vaultwarden?
Yes. The official Bitwarden apps for iOS, Android, Windows, macOS, Linux, and all major browser extensions (Chrome, Firefox, Edge, Safari) all support a custom server URL. In the app, tap the region selector or go to Settings and enter your https://vault.yourdomain.com address. Vaultwarden supports the full Bitwarden API including sync, Send, organizations, and collections — though some premium features like advanced reports require Vaultwarden's built-in premium activation via the admin panel.
What happens to my passwords if Oracle shuts down my instance?
Your vault data lives in ~/vaultwarden/vw-data/db.sqlite3. Back this file up regularly — the simplest approach is a daily cron job that copies it to