Intermediate🐧 Linux

Deploy Bitwarden Self-Hosted on Linux: Complete Guide

Take full control of your passwords by self-hosting Bitwarden on your own Linux server. This step-by-step guide covers everything from Docker installation to SSL configuration, automated backups, and security hardening with Fail2ban.

45 min20views
DifficultyIntermediate
CategoryLinux
Duration45 min
Steps8

Overview

Bitwarden is an open-source password manager that allows you to securely store and manage your credentials. This tutorial walks you through deploying your own Bitwarden server on Linux with Docker.

Prerequisites

Before starting, make sure you have the following:

Minimum hardware requirements:

ComponentMinimumRecommended
Processorx64, 1.4 GHzx64, 2 GHz dual-core
RAM2 GB4 GB
Storage12 GB25 GB
DockerEngine 26+ with ComposeEngine 26+ with Compose

Other requirements:

  • A Linux server (Ubuntu 22.04/24.04, Debian 12, or equivalent)
  • A domain name pointing to your server (e.g., vault.mydomain.com)
  • Ports 80 and 443 open on your firewall
  • Root or sudo access to the server
  • A valid email address (for SSL certificates and SMTP configuration)

Step-by-Step Tutorial

01

Prepare the Server

Start by updating your system and installing base dependencies.

# Update the system
sudo apt update && sudo apt upgrade -y

# Install dependencies
sudo apt install -y curl wget gnupg lsb-release ca-certificates apt-transport-https software-properties-common

Configure the Firewall (UFW)

If you're using UFW, configure the necessary rules:

# Allow SSH (if not already done)
sudo ufw allow ssh

# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Enable the firewall
sudo ufw enable

# Check status
sudo ufw status
Step 1 screenshot
02

Install Docker and Docker Compose

Docker is essential for running Bitwarden. Here's how to install it properly on Ubuntu/Debian.

Add the Official Docker Repository

# Add Docker's GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add the Docker repository (for Ubuntu)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# For Debian, replace "ubuntu" with "debian" in the command above

Install Docker Engine

# Update packages
sudo apt update

# Install Docker
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Verify installation
docker --version
docker compose version

Enable Docker on Boot

sudo systemctl enable docker
sudo systemctl start docker
Step 2 screenshot
03

Create a Dedicated Bitwarden User

For security reasons, never install Bitwarden as root. Create a dedicated user:

# Create the bitwarden user
sudo adduser bitwarden

# Set a strong password
sudo passwd bitwarden

# Create the docker group (if it doesn't exist)
sudo groupadd docker

# Add the user to the docker group
sudo usermod -aG docker bitwarden

# Create the installation directory
sudo mkdir -p /opt/bitwarden

# Set permissions
sudo chmod -R 700 /opt/bitwarden

# Assign ownership to the bitwarden user
sudo chown -R bitwarden:bitwarden /opt/bitwarden
Step 3 screenshot
04

Obtain Installation ID and Key

Bitwarden requires an installation ID and key to operate. These credentials are free and allow Bitwarden to verify self-hosted installations.

  1. Go to https://bitwarden.com/host/
  2. Enter your email address
  3. Note the Installation ID and Installation Key provided

Important: Keep this information safe, you'll need it during installation.

Step 4 screenshot
05

Install Bitwarden

Now switch to the bitwarden user to perform the installation:

# Log in as bitwarden
su - bitwarden

# Navigate to the installation directory
cd /opt/bitwarden

Download the Installation Script

# Download the official script
curl -Lso bitwarden.sh "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux" && chmod 700 bitwarden.sh

Run the Installation

./bitwarden.sh install

The script will ask several questions. Here's how to answer them:

  1. Enter the domain name for your Bitwarden instance:

    • Enter your domain name, e.g., vault.mydomain.com
  2. Do you want to use Let's Encrypt to generate a free SSL certificate? (y/n):

    • Answer y to automatically generate a free SSL certificate via Let's Encrypt
    • If you answer n, you'll need to provide your own certificate
  3. Enter your email address (Let's Encrypt):

    • Enter a valid email address for certificate expiration notifications
  4. Enter your installation id:

    • Paste the Installation ID obtained in Step 4
  5. Enter your installation key:

    • Paste the Installation Key obtained in Step 4
  6. Enter your region (US/EU):

    • Choose US or EU based on your location (for paid licenses)

The installation downloads all necessary Docker containers. This may take several minutes depending on your connection.

Step 5 screenshot
06

Configure Environment Variables

After installation, configure essential settings, especially the SMTP server for sending emails.

Edit the Configuration File

nano ./bwdata/env/global.override.env

SMTP Configuration (Required)

Find and modify the following lines with your SMTP settings:

globalSettings__mail__replyToEmail=no-reply@mydomain.com
globalSettings__mail__smtp__host=smtp.mydomain.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__username=user@mydomain.com
globalSettings__mail__smtp__password=your_smtp_password
globalSettings__mail__smtp__startTls=true

Configuration examples for different providers:

For Gmail:

globalSettings__mail__smtp__host=smtp.gmail.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__startTls=true

For Office 365:

globalSettings__mail__smtp__host=smtp.office365.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__startTls=true

For Amazon SES:

globalSettings__mail__smtp__host=email-smtp.us-east-1.amazonaws.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__startTls=true

Admin Portal Configuration (Optional)

To access the system administration portal, add your email:

adminSettings__admins=admin@mydomain.com

The portal will be accessible at: https://vault.mydomain.com/admin

Apply Changes

./bitwarden.sh restart
07

Start Bitwarden

Now launch your Bitwarden instance:

./bitwarden.sh start

The first startup may take a few minutes as Docker downloads images from GitHub Container Registry.

Verify Everything is Working

# List running containers
docker ps

You should see several Bitwarden containers with "Up" and "healthy" status:

  • bitwarden-mssql
  • bitwarden-web
  • bitwarden-attachments
  • bitwarden-api
  • bitwarden-identity
  • bitwarden-sso
  • bitwarden-admin
  • bitwarden-icons
  • bitwarden-notifications
  • bitwarden-events
  • bitwarden-nginx
Step 7 screenshot
08

Test the Installation

  1. Open your browser and navigate to https://vault.mydomain.com
  2. You should see the Bitwarden login page
  3. Click Create Account to create your first user
  4. Check your email to verify the account

Tip: If the verification email doesn't arrive, check your SMTP configuration and logs with docker logs bitwarden-api.

Useful Commands

Here are the main bitwarden.sh script commands:

CommandDescription
./bitwarden.sh startStart all containers
./bitwarden.sh stopStop all containers
./bitwarden.sh restartRestart all containers
./bitwarden.sh updateUpdate Bitwarden
./bitwarden.sh updateselfUpdate the bitwarden.sh script
./bitwarden.sh rebuildRebuild after modifying config.yml
./bitwarden.sh renewcertRenew SSL certificate
./bitwarden.sh compresslogsDownload compressed logs
./bitwarden.sh uninstallUninstall Bitwarden
Step 8 screenshot

Conclusion

Maintenance and Best Practices

Automatic Backups

Create a backup script to protect your data:

#!/bin/bash
# /opt/bitwarden/backup.sh

BACKUP_DIR="/opt/bitwarden/backups"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Database backup
docker exec bitwarden-mssql /opt/mssql-tools/bin/sqlcmd \
    -S localhost -U sa -P "$(grep 'SA_PASSWORD' ./bwdata/env/mssql.override.env | cut -d'=' -f2)" \
    -Q "BACKUP DATABASE vault TO DISK = '/var/opt/mssql/data/vault_$DATE.bak'"

# Configuration files backup
tar -czf $BACKUP_DIR/bwdata_$DATE.tar.gz ./bwdata

# Clean old backups (keep 7 days)
find $BACKUP_DIR -type f -mtime +7 -delete

echo "Backup completed: $DATE"

Make the script executable and automate with cron:

# Make executable
chmod +x /opt/bitwarden/backup.sh

# Edit crontab
crontab -e

# Add daily backup at 3 AM
0 3 * * * /opt/bitwarden/backup.sh >> /var/log/bitwarden-backup.log 2>&1

Regular Updates

Keep your instance updated for security patches:

# Update the script
./bitwarden.sh updateself

# Update Bitwarden
./bitwarden.sh update

Log Monitoring

Monitor logs to detect potential issues:

# API logs
docker logs bitwarden-api --tail 100 -f

# Database logs
docker logs bitwarden-mssql --tail 100 -f

# Nginx proxy logs
docker logs bitwarden-nginx --tail 100 -f

Troubleshooting

Problem: Emails Are Not Being Sent

  1. Check SMTP configuration in global.override.env
  2. Test SMTP connection from the server
  3. Check logs: docker [logs](/glossary/log) bitwarden-[api](/glossary/api) | grep -i mail

Problem: SSL Certificate Expired

./bitwarden.sh renewcert
./bitwarden.sh restart

Problem: Containers Restarting in Loop

# Check disk space
df -h

# Check memory
free -h

# Check logs of the problematic container
docker logs bitwarden-mssql

Problem: Database Corruption

# Stop Bitwarden
./bitwarden.sh stop

# Restore a backup
docker start bitwarden-mssql
docker exec bitwarden-mssql /opt/mssql-tools/bin/sqlcmd \
    -S localhost -U sa -P "YOUR_PASSWORD" \
    -Q "RESTORE DATABASE vault FROM DISK = '/var/opt/mssql/data/vault_backup.bak' WITH REPLACE"

# Restart
./bitwarden.sh start

Problem: Cannot Access Web Vault

  1. Check if all containers are running: docker ps
  2. Verify DNS resolution: nslookup vault.mydomain.com
  3. Check firewall rules: sudo ufw status
  4. Review nginx logs: docker [logs](/glossary/log) bitwarden-nginx

Advanced Security

Fail2ban for Bitwarden

Protect your instance against brute-force attacks:

sudo apt install fail2ban -y

Create the file /etc/fail2ban/filter.d/bitwarden.conf:

[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>.*$
ignoreregex =

Create /etc/fail2ban/jail.d/bitwarden.local:

[bitwarden]
enabled = true
port = 80,443
filter = bitwarden
action = iptables-allports[name=bitwarden]
logpath = /opt/bitwarden/bwdata/logs/identity/Identity/log.txt
maxretry = 5
bantime = 3600
findtime = 600

Restart Fail2ban:

sudo systemctl restart fail2ban

# Check status
sudo fail2ban-client status bitwarden

Reverse Proxy with Nginx (Optional)

If you want to run Bitwarden behind an existing Nginx reverse proxy:

  1. Edit ./bwdata/config.yml:
http_port: 8080
https_port: 8443
  1. Rebuild: ./bitwarden.sh rebuild

  2. Configure your main Nginx:

server {
    listen 443 ssl http2;
    server_name vault.mydomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass https://127.0.0.1:8443;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Connecting Clients

Once your server is running, configure Bitwarden clients to connect:

Browser Extension / Desktop App / Mobile App

  1. Open the Bitwarden app
  2. Click the gear icon (Settings) on the login screen
  3. Under Self-hosted environment, enter your server URL: https://vault.mydomain.com
  4. Save and log in with your credentials

CLI

# Set server URL
bw config server https://vault.mydomain.com

# Log in
bw login

Frequently Asked Questions

Yes, Bitwarden self-hosted is completely free for personal use. The core features are available at no cost. However, some premium features like advanced 2FA options, emergency access, and organization features require a paid license that you can purchase from Bitwarden and apply to your self-hosted instance.

Bitwarden self-hosted is the official server implementation from Bitwarden Inc., written in C# and requiring more resources. Vaultwarden (formerly bitwarden_rs) is a community-developed, Rust-based alternative that's more lightweight and suitable for low-resource environments like Raspberry Pi. Both are compatible with official Bitwarden clients.

Yes, you can export your vault data from Bitwarden cloud and import it into your self-hosted instance. Go to Settings > Export Vault in the web vault, then import the file into your self-hosted server.

Comments

Want to join the discussion?

Create an account to unlock exclusive member content, save your favorite articles, and join our community of IT professionals.

Sign in