Skip to main content

Self-Host Bitwarden with Docker: Complete Setup Guide

A practical guide to running your own Bitwarden password vault with Docker, from initial server setup through configuration, updates, and common troubleshooting.
Feb 9, 2026  · 15 min read

In this article, I’ll walk you through installing Bitwarden with Docker on a fresh Ubuntu server, configuring HTTPS with Let's Encrypt, and handling common setup issues.

If you’re just starting out with Docker, you’re better of enrolling in our Introduction to Docker or Intermediate Docker courses - learn the fundamentals before managing multiple container setups.

What Is Bitwarden's Docker Deployment?

Bitwarden has an official Docker-based installation that allows you to run a password manager on your own terms.

All you need to do is to run a single install script. There’s no need to manually install databases, web servers, or write any code. Docker pulls pre-configured containers, sets up networking between them, and gets everything running. Updates work the same way - just run the update script and Docker handles the rest.

Bitwarden's Docker setup runs as multiple containers working together. You get a web vault container for the user interface, an API container for handling requests, a database container for storing encrypted vault data, and supporting services for attachments and icons. Docker Compose orchestrates these containers so they can communicate with each other.

Everything is preconfigured for you.

This multi-container approach means each component runs in isolation. If you need to modify the database, you can restart just that container without touching the web interface. If you want to check logs, each service has its own log stream.

The official deployment uses Docker Compose to manage everything through a single configuration file, which makes the whole system easier to understand and maintain than a traditional server install.

Requirements Before Running Bitwarden with Docker

You need a few things in place before you can run Bitwarden, but none of them require enterprise hardware or complex setups.

A Linux server or VM is your starting point. Ubuntu Server is really all you need. You can use a cloud instance from AWS, DigitalOcean, or Linode. A basic instance with 2GB RAM and 20GB storage is enough to run Bitwarden for personal use or small teams.

Docker and Docker Compose handle the actual installation. You'll install Docker Engine (not Docker Desktop) and Docker Compose as separate packages. Most Linux distributions include both in their package managers.

A domain name is required because Bitwarden needs HTTPS to work. You can't run it on an IP address. You’ll have to point your domain to your server's IP address before starting the installation.

Ports 80 and 443 need to be open on your server. Port 80 handles HTTP traffic and certificate validation, while port 443 serves the actual HTTPS traffic. Configure your firewall and cloud provider's security groups to allow incoming connections on both ports.

You also need basic command-line skills. You'll be SSH-ing into your server, running installation scripts, and editing configuration files. If you know how to navigate directories and run commands with sudo, you're ready.

And that’s it! There are things you need to know, sure, but almost anyone a bit tech-savvy can do it. Let me show you how next.

How to Install Bitwarden Using Docker (Official Method)

This walkthrough uses a DigitalOcean Ubuntu droplet Cloudflare for domain and DNS management. You’re free to use other providers and services - but if you want to follow along without stress, I recommend choosing the same.

Setting up your environment

First, Create a DigitalOcean droplet with Ubuntu 24.04 LTS. The $12/month Basic droplet (2GB RAM, 1 CPU, 50GB SSD) runs Bitwarden fine for personal use or small teams. Choose a datacenter region close to you for better response times. Don’t forget to add an existing SSH key or create a new one.

After the droplet boots, note its public IP address from the DigitalOcean dashboard.

DigitalOcean droplet details

DigitalOcean droplet details

Next, configure DNS in Cloudflare. Log into your Cloudflare account and add an A record pointing your domain to the droplet's IP address:

  • Type: A

  • Name: vault (or your preferred subdomain)

  • IPv4 address: Your droplet's IP

  • Proxy status: Off (gray cloud)

Turn off Cloudflare's proxy for initial setup. Let's Encrypt needs direct access to your server to verify domain ownership. You can enable the proxy after Bitwarden is running and certificates are generated.

I’ve used one of mine active domains for the purposes of this article:

Cloudflare DNS setup

Cloudflare DNS setup

DNS propagation takes a few minutes. Run this shell command to verify the changes are visible:

nslookup vault.yourdomain.com

You should see your droplet's IP address in the response.

Nslookup results

Nslookup results

You can now connect to your droplet via SSH:

ssh root@your-droplet-ip

And you’re in:

Connecting to the Ubuntu instance

Connecting to the Ubuntu instance

Okay, so the first order of business here is to update the system packages. Run the following command:

apt update && apt upgrade -y

Now you're ready to install Docker and Bitwarden.

As mentioned earlier, you’ll need both Docker and Docker Compose. Run these commands to install them:

sudo apt install docker.io docker-compose-v2 -y
sudo systemctl enable docker
sudo systemctl start docker

And now verify the installation:

docker --version
docker compose version

You should see version numbers for both commands.

Docker and Docker Compose versions

Docker and Docker Compose versions

Up next, I’ll show you how to install Bitwarden.

Downloading and Preparing the Bitwarden Installer

Bitwarden's official installer is stored in their GitHub repository. You can download it directly to your server:

curl -Lso bitwarden.sh "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux" && chmod +x bitwarden.sh

This downloads the installation script and makes it executable. The script handles everything from downloading Docker images, creating configuration files, to setting up the directory structure.

The next step is to create a directory where Bitwarden will store its data:

sudo mkdir /opt/bitwarden

You can now move the installation script there:

sudo mv bitwarden.sh /opt/bitwarden/
cd /opt/bitwarden

And finally, run the installer:

sudo ./bitwarden.sh install

The script creates a bwdata directory that contains all of Bitwarden's configuration files, certificates, logs, and database files. This is where everything lives, so back this directory up regularly.

Running the Installation

The installer asks you several questions. Answer them carefully because getting these wrong means starting over.

Enter your domain name exactly as it appears in your DNS records. If you set up vault.yourdomain.com in Cloudflare, enter that exact string. Don't include https:// or trailing slashes.

Choose Let's Encrypt for SSL certificates. The installer will handle certificate generation and renewal automatically. If you're using Cloudflare's proxy (the orange cloud), you might need to disable it temporarily during initial setup so Let's Encrypt can verify your domain.

Enter your email address. This is where you’ll get your certification expiration reminders.

Bitwarden installation (1)

Bitwarden installation (1)

Bitwarden will then pull the required Docker images. It will take a minute or so, and then you’re in for another round of prompts.

Choose a name for the database. No need to get creative here, vault works perfectly fine.

Bitwarden installation (2)

Bitwarden installation (2)

Then the installation will proceed to download additional Docker images.

Get the installation ID and key. Open the Bitwarden Host page and enter your admin email and region. You’ll then get both values - copy/paste them when prompted during installation.

Bitwarden installation ID and key

Bitwarden installation ID and key

And that’s it - installation is complete:

Bitwarden installation (3)

Bitwarden installation (3)

The script generates configuration files in ./bwdata/config.yml and ./bwdata/env/global.override.env. You can edit these files directly if you need to change settings later.

The only thing left to do now is to start Bitwarden:

sudo ./bitwarden.sh start

Docker pulls all the required images and starts the containers. This takes a few minutes on the first run. The script shows progress as each container starts.

Bitwarden installation (4)

Bitwarden installation (4)

After a couple of minutes, you should see a message Bitwarden is up and running! printed in the terminal. This means the installation was successful, and you’re ready to proceed to the next section.

Bitwarden installation (5)

Bitwarden installation (5)

Verifying the Installation

Open your domain in a browser. You should see the Bitwarden login page with a valid HTTPS certificate.

Bitwarden login page

If you see a certificate warning, Let's Encrypt probably couldn't verify your domain. Check that:

  • Your DNS records point to the correct IP address
  • Ports 80 and 443 are open in your firewall
  • If you're using Cloudflare's proxy, try disabling it temporarily

Click "Create Account" to set up your first user. This account becomes your vault's owner, so use a strong master password you won't forget. Bitwarden can't recover this password - if you lose it, your vault data is gone.

Bitwarden user creation

Bitwarden user creation

After creating your account, log in to verify everything works. You can create a test login item and make sure it saves correctly.

Adding a login item to Bitwarden

Adding a login item to Bitwarden

This works as expected, so next, I’ll go back to the terminal to verify everything works well there too.

Run this command to check that all containers are running:

sudo docker ps

You should see multiple containers with names like bitwarden-web, bitwarden-api, bitwarden-db, and others.

Runnning containers

Running containers

If any containers show as "Restarting" or aren't listed, check the logs with these commands:

sudo docker logs bitwarden-api
sudo docker logs bitwarden-web

If you have any startup issues, these are typically due to port conflicts or permission issues.

Port conflicts happen if something else is using ports 80 or 443. Stop the conflicting service or change Bitwarden's ports in ./bwdata/config.yml.

Database initialization failures usually mean permissions issues. Check that the Docker user can write to the bwdata directory:

sudo chown -R root:root /opt/bitwarden/bwdata
sudo chmod -R 755 /opt/bitwarden/bwdata

Certificate generation failures mean Let's Encrypt couldn't reach your server. Verify your domain points to the right IP and that your firewall allows incoming traffic on ports 80 and 443.

If containers keep restarting, check available disk space and memory. Bitwarden needs at least 2GB of RAM to run all its services.

Configuring HTTPS and Certificates

Bitwarden requires HTTPS for all connections. There's no way to run it over plain HTTP.

Bitwarden's browser extensions and mobile apps refuse to connect to HTTP endpoints. The protocol itself requires encrypted connections to protect your vault data in transit.

The installation script sets up Let's Encrypt certificates. Let's Encrypt is a free certificate authority that issues SSL/TLS certificates and handles renewals. When you entered your domain during installation, the script configured automatic certificate generation through Let's Encrypt's ACME protocol.

Certificates expire after 90 days, but Bitwarden's Docker setup includes automatic renewal. A cron job checks for expiring certificates and renews them before they expire. You don't need to do anything manually.

Custom certificates make sense in a few situations. If you're running Bitwarden behind a reverse proxy that already handles SSL termination, you can disable Let's Encrypt and let the proxy manage certificates. If your organization has an internal certificate authority, you can configure Bitwarden to use those certificates instead.

To use custom certificates, edit ./bwdata/config.yml and set ssl_certificate_path and ssl_key_path to your certificate files.

Using custom certificates docker bitwarden

Using custom certificates

Then restart Bitwarden:

sudo ./bitwarden.sh restart

When certificate renewal fails, you should first check the logs:

sudo docker logs bitwarden-nginx

Common renewal failures happen when:

  • Your domain's DNS changed and no longer points to the server
  • Cloudflare's proxy is enabled (the orange cloud), blocking Let's Encrypt's verification
  • Port 80 is blocked, preventing ACME challenges from completing
  • The certificate files have incorrect permissions

Fix the underlying issue, then manually trigger renewal:

sudo docker exec bitwarden-nginx certbot renew

If that succeeds, the automatic renewal cron job should work on future attempts.

Email (SMTP) Configuration

Bitwarden needs email to send user invitations, password reset links, and two-factor authentication codes.

Without SMTP configured, users can't reset their passwords. You can't invite team members to your organization. Emergency access requests won't work. The system works, but you lose critical account recovery and user management features.

SMTP settings live in ./bwdata/env/global.override.env.

SMTP settings file docker bitwarden

SMTP settings file

Open this file and add your email provider's configuration:

globalSettings__mail__replyToEmail=no-reply@yourdomain.com
globalSettings__mail__smtp__host=smtp.gmail.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__username=your-email@gmail.com
globalSettings__mail__smtp__password=your-app-password

The format uses double underscores to represent nested configuration. Each __ separates a level in the settings hierarchy.

After editing the file, don’t forget to restart Bitwarden:

sudo ./bitwarden.sh restart

Test email delivery by requesting a password reset or sending a test email through the admin panel.

Here are some common SMTP mistakes you’ll want to avoid:

  • Using your regular email password instead of an app-specific password. Most providers require you to generate a dedicated password for SMTP access. Gmail calls these "App Passwords," and you create them in your Google account security settings.

  • Wrong port numbers. Port 587 handles STARTTLS connections, port 465 handles SSL/TLS, and port 25 is usually blocked by cloud providers. If one port doesn't work, try another.

  • SSL/TLS confusion. Set ssl=false for STARTTLS on port 587, or ssl=true for direct SSL on port 465. Mixing these settings causes connection failures.

  • Firewall blocking outbound SMTP. Some cloud providers block outbound port 25 by default. Use ports 587 or 465 instead, which are rarely blocked.

If emails aren't sending, check the API container logs:

sudo docker logs bitwarden-api

Look for SMTP connection errors or authentication failures. The logs show exactly what went wrong with the email delivery.

Updating and Backing Up Bitwarden

With self-hosted installation comes the pain of manual backups and updates. Luckily, these are easy to do.

Updating Bitwarden

Before updating, stop Bitwarden and back up your data. Updates can fail or introduce issues, and you need a way to roll back if something goes wrong.

cd /opt/bitwarden
sudo ./bitwarden.sh stop

Back up the entire bwdata directory:

sudo tar -czf bitwarden-backup-$(date +%Y%m%d).tar.gz bwdata/

Move this backup somewhere safe, like an external drive or different server.

Now update Bitwarden with this command:

sudo ./bitwarden.sh update

The update script pulls the latest Docker images, updates configuration files if needed, and restarts all containers. This usually takes a few minutes.

Updating Bitwarden

Updating Bitwarden

After the update completes, verify everything works by logging into your web vault and checking that your data is intact.

If the update breaks something, simply restore your backup:

sudo ./bitwarden.sh stop
sudo rm -rf bwdata/
sudo tar -xzf bitwarden-backup-YYYYMMDD.tar.gz
sudo ./bitwarden.sh start

Backups

The bwdata directory contains everything Bitwarden needs to run. You should back it up regularly.

This directory includes:

  • Your vault database with all encrypted passwords
  • SSL certificates
  • Configuration files
  • Logs and attachments
  • Docker Compose definitions

Stop Bitwarden before backing up to ensure data consistency:

sudo ./bitwarden.sh stop
sudo tar -czf bitwarden-backup-$(date +%Y%m%d).tar.gz bwdata/
sudo ./bitwarden.sh start

Store backups in multiple locations. Keep one on the server, one on a different machine, and one in cloud storage if possible.

To restore from backup, stop Bitwarden, delete the current bwdata directory, extract your backup, and restart. The process is the same as rolling back from a failed update.

You can even automate backups with a cron job that runs daily or weekly, depending on how often your vault data changes.

Common Issues When Running Bitwarden in Docker

Even with a clean installation, you can run into issues. Here's how to diagnose the most common ones.

Port conflicts happen when another service is already using ports 80 or 443. Check what's using these ports:

sudo netstat -tlnp | grep ':80\\|:443'

If you see Apache, Nginx, or another web server running, you need to either stop that service or change Bitwarden's ports. To change ports, edit ./bwdata/config.yml and set http_port and https_port to different values like 8080 and 8443. Then restart:

sudo ./bitwarden.sh restart

Certificate failures show up as browser warnings or Bitwarden refusing to start. Check the nginx container logs with this command:

sudo docker logs bitwarden-nginx

Look for ACME challenge failures or certificate validation errors. Here are the most common causes:

  • DNS doesn't point to your server yet
  • Cloudflare proxy is blocking Let's Encrypt verification
  • Port 80 is blocked by your firewall
  • The domain in your config doesn't match your DNS records

Fix the DNS or firewall issue, then manually request certificates:

sudo docker exec bitwarden-nginx certbot renew --force-renewal

Containers not starting usually means database problems or missing files. Check which containers are running by running this:

sudo docker ps -a

Containers in "Exited" or "Restarting" status have problems. Check their logs:

sudo docker logs bitwarden-db
sudo docker logs bitwarden-api

Database initialization errors mean the bwdata directory has permission issues. Fix permissions:

sudo chown -R root:root /opt/bitwarden/bwdata
sudo chmod -R 755 /opt/bitwarden/bwdata

If containers still won't start, check disk space:

df -h

Remember that Bitwarden needs at least a few GB of free space to run properly.

SMTP not working prevents password resets and user invitations. Test your SMTP settings first by checking the API logs when you try to send an email:

sudo docker logs -f bitwarden-api

Trigger a password reset attempt and watch for SMTP errors in the logs. Here are the most common issues:

  • Wrong username or password (use app-specific passwords, not your regular password)
  • Wrong port or SSL settings
  • Firewall blocking outbound SMTP connections
  • Email provider requiring additional authentication steps

You can verify your SMTP settings in ./bwdata/env/global.override.env match your provider's documentation exactly. Even small typos in the hostname or port break email delivery.

After fixing SMTP settings, restart Bitwarden and test again.

Bitwarden vs Vaultwarden (Docker Users' Choice)

Vaultwarden is an unofficial, community-maintained implementation of the Bitwarden server written in Rust.

It's not affiliated with Bitwarden Inc., but it's compatible with all official Bitwarden clients. You use the same browser extensions, mobile apps, and desktop applications. The difference is entirely on the server side.

Why users choose Vaultwarden

  • Lower resource usage. Vaultwarden runs on a single lightweight container that needs less than 100MB of RAM. Official Bitwarden uses multiple containers and needs at least 2GB. If you're running on a small VPS or Raspberry Pi, Vaultwarden makes more sense.
  • Simpler setup. One container means fewer moving parts. No separate database container, no separate web container. You pull one image, configure one container, and that’s it.
  • Some premium features work without a paid license. Vaultwarden enables features like file attachments and emergency access that require a premium subscription on official Bitwarden.

Tradeoffs with Vaultwarden

  • It's a community project. Updates come from volunteers, not a company with dedicated support staff.
  • No official support. Bitwarden Inc. won't help you with Vaultwarden issues. You're on your own with community forums and GitHub issues.
  • Potential compatibility issues. When Bitwarden releases new features, Vaultwarden needs to catch up. There's usually a delay before new functionality works.

Which should you use?

Use official Bitwarden if you want enterprise support, guaranteed compatibility with all features, and backing from the company that builds the clients. The resource requirements matter less if you're on a properly sized VPS.

Go with Vaultwarden if you're running on constrained hardware, want a simpler setup, or need premium features without paying. Just understand you're trading official support for resource efficiency.

Both work well for self-hosting, and both protect your passwords with the same encryption the clients expect.

Basic Security Best Practices

Stating the obvious, but Bitwarden stores your passwords, so you’ll want protection beyond just encryption. Here are some best practices to follow.

Keep your server updated. Security patches matter, so run updates regularly. Here’s a command for doing so:

sudo apt update && sudo apt upgrade -y

You can set up automatic security updates so critical patches are installed without manual intervention. On Ubuntu, install unattended-upgrades:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

Restrict access to the admin panel. Bitwarden's admin interface lives at /admin and uses a separate admin token for authentication. Generate a strong token during installation and store it somewhere safe. Don't expose the admin panel to the public internet if you can avoid it.

If you need remote admin access, use SSH tunneling or a VPN instead of leaving /admin publicly accessible.

Use HTTPS everywhere. Never disable HTTPS or bypass certificate warnings. If your certificates aren't working, fix them rather than working around the problem. Bitwarden clients refuse to connect over HTTP for good reason.

Monitor Bitwarden releases. Subscribe to Bitwarden's GitHub releases or check their blog for security updates. When a new version drops, read the release notes before updating to understand what changed.

Enable two-factor authentication on your vault account. Even if someone steals your master password, 2FA blocks unauthorized access. Use an authenticator app or hardware key.

Use a firewall. For reference, here’s how you can configure UFW to only allow necessary ports:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Block everything else by default.

Check logs occasionally for unusual activity. Look for failed login attempts or unexpected API calls:

sudo docker logs bitwarden-api | grep -i "failed\\|error"

As you can see, self-hosted Bitwarden means you’ll have to do some work every now and then. That’s the price of full control.

Conclusion

Docker makes self-hosting Bitwarden easy and you don’t need enterprise infrastructure.

The official installation script does everything for you. You get automatic updates, certificate management, and a working vault in under an hour - it took me roughly 15 minutes to set up, including compute instance provisioning and DNS setup. Most users never need anything more than what I covered in this article.

Start with the basic setup on a single server. Get comfortable with backups, updates, and basic troubleshooting before adding reverse proxies, external databases, or high availability setups. Those advanced configurations solve problems you probably don't have yet.

If you don’t want to trust third parties with your passwords, this is the way to go. But it’s also important not to overcomplicate the setup and break something. Run the official Docker deployment, back it up regularly, and you've got a solid password manager under your control.

Are you ready to learn more about Docker? Start with our Containerization and Virtualization Concepts course and then see it in action with Docker and Kubernetes.


Dario Radečić's photo
Author
Dario Radečić
LinkedIn
Senior Data Scientist based in Croatia. Top Tech Writer with over 700 articles published, generating more than 10M views. Book Author of Machine Learning Automation with TPOT.

FAQs

How can I ensure high availability for my Bitwarden self-hosted instance?

High availability requires running multiple Bitwarden instances behind a load balancer with a shared external database like PostgreSQL or MySQL. You'll need to configure each instance to connect to the same database and use shared storage for attachments. For most personal and small team deployments, regular backups and a documented restore process provide adequate protection without the complexity of HA architecture.

What are the best practices for configuring SMTP in Bitwarden?

Use app-specific passwords instead of your regular email password, and verify your SMTP settings match your provider's documentation exactly. Always test email delivery after configuration by triggering a password reset or using the admin panel's test function. Store SMTP credentials securely in the global.override.env file and restrict file permissions to prevent unauthorized access.

How do I troubleshoot a 502 Bad Gateway error in Bitwarden?

Check if all containers are running with sudo docker ps and look for any in "Restarting" status. Review the nginx and API container logs using sudo docker logs bitwarden-nginx and sudo docker logs bitwarden-api to identify the failing service. Common causes include the API container not starting due to database connection issues, insufficient memory, or certificate problems blocking the reverse proxy.

Can I use custom server ports with Bitwarden?

Yes, edit ./bwdata/config.yml and change http_port and https_port to your preferred values like 8080 and 8443. After changing ports, restart Bitwarden with sudo ./bitwarden.sh restart. Remember that using non-standard ports means you'll need to include the port number in your domain URL when accessing the vault.

How do I enable logging to syslog in Bitwarden?

Bitwarden's Docker containers log to stdout/stderr by default, which Docker captures automatically. You can forward these logs to syslog by configuring Docker's logging driver in the container settings or using a log aggregation tool like Fluentd or Logstash. For simple syslog integration, use Docker's syslog logging driver by adding --log-driver=syslog to your container configuration, though this requires manual Docker Compose file modification.

Topics

Learn Docker with DataCamp

Course

Introduction to Docker

4 hr
42.1K
Gain an introduction to Docker and discover its importance in the data professional’s toolkit. Learn about Docker containers, images, and more.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

Tutorial

PostgreSQL in Docker: A Step-by-Step Guide for Beginners

Your complete guide to running PostgreSQL in Docker—from setup to best practices—so you can enhance your development workflow without headaches.
Dario Radečić's photo

Dario Radečić

Tutorial

Running MongoDB in Docker: A Complete Guide with Examples

This guide walks you through running MongoDB in Docker, covering both quick command-line deployments and full Docker Compose configurations. It’s perfect for developers looking to self-host or experiment locally without immediately jumping into cloud hosting.
Nic Raboy's photo

Nic Raboy

Tutorial

Install Docker on Debian: A Complete Installation Guide

This guide covers four installation approaches, from the official Docker repository to manual package installation, plus essential post-installation configuration for enterprise deployments. You'll learn how to secure your Docker environment, troubleshoot common issues, and maintain a production-ready setup.
Dario Radečić's photo

Dario Radečić

Tutorial

Update Docker: A Step-by-Step Guide

Learn how to update Docker Engine, Docker Desktop, and container images — all without breaking your setup.
Dario Radečić's photo

Dario Radečić

Tutorial

Docker Build Secrets Guide: Secure Container Image Development

Learn how to use Docker build secrets to handle sensitive data securely during image builds. Master secret mounts, SSH authentication, and CI/CD integration.
Benito Martin's photo

Benito Martin

Tutorial

Install Docker on Ubuntu: From Setup to First Container

It only takes a few commands from a fresh OS installation to running your first containerized application. Learn how to do this with this ultimate Docker Ubuntu setup guide.
Dario Radečić's photo

Dario Radečić

See MoreSee More