Self-Host Bitwarden: Your Passwords Deserve Better Than Cloud Vibes
The “Oh Crap, My Passwords Are Hosted by Mark Zuckerbucks’ Cousin” Wake-Up Call
So you’ve decided to self-host Bitwarden. Bless your paranoid little heart. Because let’s be brutally real: trusting some free cloud service with your passwords is like handing your house keys to a raccoon wearing a “Trust Me Bro” t-shirt. Sure, Bitwarden’s official cloud is *fine*—if you enjoy gambling with your digital life while some algorithm monetizes your anxiety. But you? You’re smarter. You’ve Googled “self-hosted Bitwarden + Postgres Docker” at 3 a.m., half-awake and vibrating with existential dread. Congrats! You’re officially on the homelab path to redemption (or a spectacular crash-and-burn). Today, we dissect how to deploy official Bitwarden (not Vaultwarden—more on that later), slap Postgres under it, automate backups like a robot overlord, and actually sleep at night. And no, Karen, this isn’t about “just using Bitwarden Cloud.” We’re here for the hard mode.
Why “Official Bitwarden” Isn’t Just Corporate Brainwashing (Unlike My Last Relationship)
You’ve heard of Vaultwarden—the spunky, unofficial “Bitwarden RS” that runs on a toaster. Cute. But this guide? We’re doing the real Bitwarden self-host. Not the “lite” version. Why? Because:
- Compliance Theatre: If your job requires auditable FIPS 140-2 compliance (or you just want to flex at IT meetings), official Bitwarden serves that up. Vaultwarden? It’s busy being “lightweight” while ignoring your boss’s demands.
- No Feature FOMO: Unified beta (yes, that Dec 8, 2022 forum post you skimmed) bundles API, web vault, and more into one glorious Docker image. Vaultwarden lags on features like “two-factor auth for dogs” (okay, maybe not dogs yet).
- Serious Backups: The Jan 26, 2026 Reddit guide hammered this: official self-host + Postgres = backup sanity. Vaultwarden? Its backup system feels like duct-taping your router to a kite.
Bottom line: If you want “official Bitwarden self-host” (their words, not mine), you’re committing to the full stack—Postgres, Redis, and all the Docker-compose melodrama. No shortcuts. Because your Netflix password ≠ rocket science. Yet.
Docker Compose: Because Clicking “Next” Isn’t Hardcore Enough
Forget “one-click installs.” We’re building a Frankenstein server that screams “I have hobbies.” The official hosting docs (shoutout to that “beginner-friendly map” article) require Docker Compose. Here’s what the real stack looks like based on the Jan 26, 2026 homelab guide:
- Bitwarden Unified Image: The Dec 8, 2022 Unified beta isn’t just hype—it’s your lifeline. This single image replaces the old messy collection of
api,web, andiconscontainers. One container to rule them all (until it doesn’t). - PostgreSQL 14+: No SQLite nonsense. Bitwarden’s docs demand it. You’ll see
postgres://username:password@postgres:5432/bitwardenin configs—yes, that’s the exact URI format from the Unified beta forums. Don’t typo that password; your future self will sob into a backup tape. - Redis for Caching: Because hitting Postgres for every login feels like faxing your resume to Google.
- Mounted Volumes: As per the May 22, 2025 migration guide:
/bitwarden/datafor encrypted vaults. Lose this? Congrats, you’ve invented a new cryptocurrency (it’s called “panic”).
Here’s the docker-compose.yml skeleton—not the full thing (we’ve got 2000 words to burn), but the critical bits:
version: '3.8'
services:
bitwarden:
image: bitwarden/self-host:latest
container_name: bitwarden
ports:
- "8080:8080"
environment:
- GLOBAL_SETTINGS__DOMAIN=https://your-domain.com
- DATABASE_PROVIDER=postgres
- DATABASE_CONNECTIONSTRING=postgres://bwuser:supersecretpw@postgres:5432/bitwarden?sslmode=disable
volumes:
- ./bw-data:/bitwarden/data
depends_on:
- postgres
- redis
postgres:
image: postgres:14
container_name: bitwarden-postgres
environment:
POSTGRES_DB: bitwarden
POSTGRES_USER: bwuser
POSTGRES_PASSWORD: supersecretpw
volumes:
- ./postgres-data:/var/lib/postgresql/data
redis:
image: redis:7
container_name: bitwarden-redis
Note: sslmode=disable? Yes, because Docker networks are intra-container jungles where SSL is overkill. Outside? Terminate SSL at your reverse proxy (Caddy, Nginx—more later). And never, ever expose Postgres to the internet. That’s how you end up on “Have I Been Pwned” before breakfast.
Postgres: It’s Not Just for Hipster Breweries Anymore
Why Postgres? Because Bitwarden said so—and they’re not wrong. SQLite crashes harder than a Windows 95 update under load. But configuring it? Let’s demystify the Jan 26, 2026 guide’s Postgres setup:
- Isolation is Sexy: Run Postgres in its own container (see
docker-composeabove). Shared DBs = shared pain when your homelab accidentally nukes itself. - Connection Strings Matter: That
postgres://bwuser:supersecretpw@postgres:5432/bitwardenURI? Break it down:bwuser: Not “root”. Not “admin”. A dedicated user. Because privilege escalation isn’t just for sysadmins with trust issues.postgres:5432: The service name (postgres) from Docker Compose—notlocalhost. Docker networks route via service names. Get this wrong, and your containers stare at each other awkwardly.sslmode=disable: Again, internal traffic. Don’t bring a SSL cert to a Docker networking fight.
- Backups Start Here: Daily backups (not just volume snapshots) require
pg_dump. Why? Because Bitwarden’s data is relational gold. If your volume corrupts,pg_dumpis your parachute. (More on automating this later.)
“Postgres feels like overkill until your vault hits 500 logins and SQLite implodes like a reality TV marriage.” — Wong Edan, probably
Pro tip: Monitor Postgres disk space. Bitwarden’s attachment feature (yes, it exists) turns your DB into a black hole. Set alerts for 90% disk usage or enjoy playing “Where’s Waldo?” with missing passwords.
Backup Automation: n8n + S3 or “You’re Doing It Wrong”
Snapshots of your Docker volumes? Amateur hour. If your disk melts, those snapshots melt with it. The Jan 26, 2026 Reddit post (r/Bitwarden) nails it: daily pg_dump backups → encrypted → shipped to S3. Automate it or lose everything. Here’s how the homelab guide does it:
- Step 1: Dump the DB Daily
Triggerpg_dumpvia cron inside a lightweight container. Sample script (from the guide’s GitHub repo):
#!/bin/bash
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DUMP_FILE="/backups/bitwarden_$TIMESTAMP.sql"
pg_dump -h postgres -U bwuser -d bitwarden > $DUMP_FILE
gzip $DUMP_FILE # Compress because you’re not made of disk space
- Step 2: Encrypt Like a Spy
Encrypt with GPG. Why? Because S3 buckets get leaked more often than politicians’ texts. Use asymmetric encryption:
gpg --encrypt --recipient "[email protected]" /backups/bitwarden_*.sql.gz
- Step 3: n8n Automation Flow
n8n (pronounced “nayn”) is the open-source Zapier for control freaks. The guide’s flow:- Trigger: Cron job at 2 a.m. (when your homelab isn’t streaming 4K).
- Action 1: Execute shell script (the
pg_dump+ GPG above). - Action 2: Upload encrypted .gpg file to AWS S3 via n8n’s S3 node.
- Action 3: Slack/email alert if upload fails. Because silence = panic.
Why n8n? Unlike commercial tools (looking at you, June 27, 2024 “automatic backup program” dev), n8n’s local-first. Your backup keys never touch the cloud. Also, it’s free. Unlike my ex’s therapy bills.
Note: The Jan 26, 2026 guide explicitly uses n8n → S3. No Google Drive. No Dropbox. S3 (or MinIO) only. Because “free” cloud storage has terms of service that say “we own your encrypted passwords now.”
Reverse Proxy & TLS: Because Port 8080 Sucks the Life Out of You
Raw port 8080 access? That’s how you get “free” DDoS practice from script kiddies. The May 22, 2025 setup nails it: Caddy as a separate Docker service. Why Caddy?
- Automatic TLS: Caddy grabs Let’s Encrypt certs without you begging like a dog at a steakhouse.
- HTTP/3 Out of the Box: Because “QUIC” sounds like a superhero move.
- Simple Config: While Nginx configs resemble hieroglyphics, Caddy’s
Caddyfileis humane:
your-domain.com {
reverse_proxy bitwarden:8080
encode zstd gzip
}
Docker Compose snippet for Caddy:
caddy:
image: caddy:latest
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
depends_on:
- bitwarden
Key detail: Bitwarden’s GLOBAL_SETTINGS__DOMAIN must match Caddy’s your-domain.com. Mismatch this, and CORS errors will ruin your week. Also, terminate SSL at Caddy—never pass HTTP to Bitwarden. Encryption isn’t optional; it’s “don’t be stupid 101.”
Wong Edan’s Verdict: Stop Being Lazy or Lose Everything
Let’s get real: self-hosting Bitwarden with Postgres isn’t “I followed a YouTube tutorial.” It’s a commitment. Like adopting a high-maintenance emotional support alpaca. You’ll want to quit when Postgres won’t start because of a typo in docker-compose.yml. But here’s the cold, hard truth from Jan 26, 2026:
- Backups or Bust: Automated daily
pg_dump→ n8n → S3 isn’t “nice-to-have.” It’s why your vault survived the Great Homelab Crash of 2025. If you skip this, don’t cry when Bitwarden’s docs say “restore from backups” and you have zip. - Docker Compose > Everything Else: Don’t try bare-metal installs. The official docs demand Docker. Fight it, and you’ll beg for mercy at 2 a.m.
- Official Bitwarden Wins: Vaultwarden’s for hobbyists. If you’re serious about encryption standards and audits (or just avoiding future migraines), Unified Docker image + Postgres is non-negotiable.
Is it worth it? Absolutely. Because cloud services will get breached. Your ISP will log your Bitwarden traffic. And that “free” password manager will monetize your anxiety. Self-hosting shifts control back to you. Just don’t half-ass it. Automate backups religiously. Isolate Postgres. Use Caddy. And for the love of all that’s holy, test restoring from a backup before disaster strikes.
“Your passwords are worth more than your coffee subscription. Now go fix your backups before AWS bills you for storing leaked credentials.” — Wong Edan’s new tattoo
Final thought: That June 27, 2024 dev working on “automatic backup programs”? Bless their heart. But until it’s battle-tested like the Jan 26, 2026 n8n guide, stick with proven open-source tools. Your future self—with zero passwords—will thank you. Or haunt you. One of the two.