Skip to content

This repository contains scripts and configurations for deploying a self-hosted Vaultwarden instance with Cloudflare Tunnel integration, optional Nginx reverse proxy, and Docker Compose.

Notifications You must be signed in to change notification settings

dynamic-stall/vaultwarden-docker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vaultwarden Deployment with Cloudflare Tunnel

BLUF: This repository contains scripts and configurations for deploying a self-hosted Vaultwarden instance with Cloudflare Tunnel integration and (optional) DuckDNS custom subdomain via Docker Compose.

Vaultwarden is an alternative implementation of the Bitwarden server API, written in Rust, and compatible with upstream Bitwarden clients⁠.

Bitwarden/Vaultwarden is capable of password management via web app, desktop app, browser extension, mobile app, or CLI.

DuckDNS is a free dynamic DNS service. It allows users to create custom domain names that automatically update to point to a specific IP address, which is particularly useful for home servers, remote access, or hosting services with changing IP addresses. Users can choose a subdomain under duckdns.org and configure it to always point to their current IP address, making it easier to access their network or servers remotely.

If you have a registered domain, you can further customize your Bitwarden experience by modifying the server URLs (instructions provided further down).


Prerequisites

  • Linux/macOS server (or WSL instance if running Windows)
  • Docker installed
  • Cloudflare account
  • DuckDNS account + registered subdomain and token <OR> personal registered domain
  • Basic understanding of networking and Docker concepts

Components

  1. Docker Compose Setup: Deploys Vaultwarden and Cloudflare Tunnel containers
  2. (Optional) DuckDNS subdomain: Allows for secure access to your vault instance without relying on an IP address
  3. Cloudflare Tunnel: Provides secure access without exposing ports
  4. Cloudflare Domain: Add you own registered domain or DuckDNS subdomain to your Cloudflare dashboard to resolve traffic to your Vaultwarden instance behind the Cloudflare Tunnel
  5. (Optional) Nginx Configuration: Nginx reverse proxy for SSL termination (useful if deploying as part of a larger infrastructure, i.e., you already have other containers deployed as part of your infrastructure)
  6. Admin Token Generation: Securely creates admin dashboard access

Setup Instructions

1. Initial Setup

  1. Clone this repository:
git clone https://github.com/dynamic-stall/vaultwarden-docker
cd vaultwarden-docker
  1. Create .env from example file (be sure to add your personalized variables):
cp .env.example .env

Required environment variables:

  • VAULT_NAME: Vaultwarden container and hostname (used to create DOMAIN_URL)
  • VAULT_VOLUME: Persistent volume for vaultwarden container and automated back-up locations
  • VAULT_PORT: Local port for Vaultwarden (default: 8443)
  • TUNNEL_TOKEN: Cloudflare Tunnel token (obtained from your personal Cloudflare account)
  • SMTP_*: Email configuration variables (default: smtp.gmail.com)
  • DDNS_DOMAIN: (Optional) Your DuckDNS subdomain (i.e., example.ddns.com; used to create DOMAIN_URL)
  • DDNS_TOKEN: (Optional) DuckDNS subdomain token (obtained from your personal DuckDNS account)
  • DOMAIN_NAME: Either your DuckDNS subdomain or your personal registered domain name (used to create DOMAIN_URL)
  • ADMIN_TOKEN: Generated by admin-token-create.sh

(NOTE: More on DOMAIN_NAME variable setup further down)

  1. (Optional) If deploying with Nginx, you will need to either have your own SSL certificates (i.e., private.key and certificate.crt) or the deploy-nginx.sh script will generate them for you.

Copy the config/nginx/openssl.cnf.example file and update with your own values:

cd config/nginx
cp openssl.cnf.example openssl.cnf

NOTE: Before running the deploy-nginx.sh script, be sure to have the absolute paths to your SSL certificates.

  • The following will be auto-configured for you:
    • SSL private key and self-signed certificate
    • vaultwarden.conf Nginx configuration file
    • Nginx server configuration

(NOTE II: If skipping Nginx and SSL configuration, simply run the deploy-standalone.sh script.)


2. Domain Name Configuration

Option 1: Using DuckDNS (Free Domain)

  1. Visit DuckDNS and sign in using your preferred OAuth provider

image

  1. Create a subdomain (i.e., vault.duckdns.org)

  2. Copy your token from the DuckDNS dashboard

image

  1. Modify these variables to your .env file:
DDNS_DOMAIN=<your-chosen-subdomain>
DDNS_TOKEN=<your-duckdns-token>
  • NOTE If you own example.duckdns.org, then set DDNS_DOMAIN=example.

The DuckDNS container will automatically:

  • Update your IP address every 5 minutes
  • Maintain your subdomain registration
  • Handle logging and retry logic
  • Keep your subdomain active (domains remain valid as long as they're updated once every 30 days)
  • No additional maintenance is required as long as the container remains running.

Option 2: Using Your Own Domain

If you have a registered domain, you can skip the DuckDNS setup and modify the vw-compose.yml file:

  1. Remove the DuckDNS service block:
  # Remove this entire block
  duckdns:
    image: linuxserver/duckdns
    # ...
  1. Update the DOMAIN_NAME variable in .env, either commenting out or deleting the first DOMAIN_NAME variable referencing the DuckDNS subdomain:

Get rid of:

DOMAIN_NAME="${DDNS_DOMAIN}.duckdns.org"

...and modify the following variable:

# Remove the "#" and enter your personal registered domain
DOMAIN_NAME="example.com"

NOTE: Regardless of whether you use DuckDNS or bring your own domain, the final DOMAIN_URL variable will be correctly formatted for use in later configurations:

DOMAIN_URL="https://${VAULT_NAME}.${DOMAIN_NAME}"

3. Cloudflare Domain Zone Setup

⚠️ Skip this step if using DuckDNS ⚠️

  1. Login to your Cloudflare account

  2. Navigate to Account HomeDomains

  3. Select the blue + Add a domain button to enter your domain name: either your full DuckDNS subdomain or your personal registered domain. Leave default settings as they are.

image

  1. In your DNS dashboard, you should see four records: two A records (containing your current public IP address) and two MX records (ignore these...).

image

  1. Save this page for later; we'll come back to it for the next step...

4. Cloudflare Tunnel Setup

  1. Login to your Cloudflare Zero Trust dashboard

  2. Navigate to NetworksTunnels

  3. Create a new tunnel:

    • Click Create a tunnel.

    • Select Cloudflared on the left.

    • Name your tunnel (the name is only important to you). Click Save on the bottom-right.

    • Under the "Choose your environment" options, select Docker. image

    • Under "Install and run a connector", copy the docker run command provided. Paste this command in a secure note-taking environment to see the full token.

    • Copy this token and paste it into your .env file, updating the TUNNEL_TOKEN variable.

    # Cloudflare Configuration
    TUNNEL_NAME="${VAULT_NAME}-tunnel"   # NOTE: this variable is for the Docker container name
    TUNNEL_TOKEN="<your-cloudflare-tunnel-token>"
    • Back to your Cloudflare dashboard, click Save on the bottom-right.
  4. Configure the tunnel's Public Hostname:

    • Subdomain: Ensure this value matches your chosen VAULT_NAME value in your .env file
    • Domain: Either your personal registered domain name (i.e., example.com) or your DuckDNS subdomain (i.e., example.duckdns.org)
    • Path: (Leave this field blank)
    • Type: HTTP
    • URL: localhost:8443 (or your chosen VAULT_PORT value, if you changed it)
  • NOTE: If you are using a DuckDNS subdomain, you will not be able to add your subdomain to your Cloudflare dashboard for longer than 28 days (without NS record verification, which isn't possible with DuckDNS). You can still enter a "custom domain name" in the Public Hostname section. Be sure to hit the ENTER key when populating this value so it doesn't disappear. A warning for custom domains will appear. It means nothing configuration-wise, but be mindful:

image

  1. (Optional) Configure the tunnel's Private Network:

    • Cloudflare offers an extensive array of features available at free-tier. If you plan on utilizing WARP with your Zero Trust account (which I recommend), you can implement more robust access policies as well as custom private networks/IPs to access remote resources without requiring a public domain
    • For the sake of simplicity, these instructions are beyond the scope of this GitHub project, but I suggest you check them out on your own, especially Cloudflare Access -- which can secure access to your self-hosted applications and more via various authentication and posture-assessment methods (i.e., Google OIDC for single sign-on with your Gmail account, restricting access to resources based on public IP or country, and much, much more).
  2. Click Save tunnel in the bottom-right.


5. Deployment

Run one of the main deployment scripts:

If configuring SSL and Nginx, run:

./deploy-nginx.sh

This will:

  1. Generate admin token
  2. Create SSL certificates
  3. Configure Nginx
  4. Launch Docker containers
  5. (Optionally,) configure Bitwarden CLI

If deploying without nginx, run:

./deploy-standalone.sh

This will:

  1. Generate admin token
  2. Launch Docker containers
  3. (Optionally,) configure Bitwarden CLI

Accessing Your Vault

Configuring Clients

Using the Web Vault:

  1. Navigate to the admin panel of your Vaultwarden instance (i.e., vault.example.com/admin)

  2. Use the Admin token you set to authenticate

  3. From the admin page, you can create users for general access and password management (access the Web Vault at, i.e., vault.example.com/#/login)

Using the Desktop App:

  1. Open Bitwarden desktop app

  2. Expand the "Accessing" dropdown menu below your login email

image

  1. Select "Self-hosted" and enter your server URL (ex: https://vault.example.com)

image

  1. Use your created user's master password to login

Programmatic Access

Using the CLI:

The main deployment scripts will (optionally) build a Docker container which will allow you to run the Bitwarden CLI -- while also pre-configuring it to use your custom domain.

NOTE: If you would prefer a host installation of the CLI, you can use the scripts/cli-host-config.sh script instead of the Docker deployment.

Reference the below for manual configuration of the CLI:

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

# Configure individual endpoints
bw config server \
  --api https://vault.example.com/api \
  --identity https://vault.example.com/identity \
  --web-vault https://vault.example.com \
  --icons https://vault.example.com/icons \
  --notifications https://vault.example.com/notifications

Cloudflare Origin CA Certificate

If you would like to register your SSL certificate with Cloudflare (or another certificate authority) and obtain an Origin CA certificate, you will first need to generate a certificate signing request (CSR). Use the command below (replace with your private key name, if you brought your own):

openssl req -new -key private.key -out request.csr -config config/nginx/openssl.cnf

After you have your CSR, use it to obtain the Origin CA certificate by following the official documentation. Once you have registered your SSL certificate with Cloudflare and configured your setup to use them, you can discard the self-signed certificate, certificate.crt, IF it is no longer being used in your deployment...


File Structure

.
├── config/
│   ├── docker/
│   │   ├── cli.Dockerfile
|   |   └── vw-compose.yml
│   └── nginx/
|       ├── vaultwarden.conf.template
│       └── openssl.cnf.example
├── deploy-nginx.sh
├── deploy-standalone.sh
├── .env.example
├── .gitignore
├── README.md  # this file
└── scripts/
    ├── admin-token-create.sh
    ├── bw-cli-config.sh
    ├── cli-config-host.sh
    ├── docker-custom-net.sh
    ├── nginx-config.sh
    └── ssl-cert-create.sh

Security Considerations

  • Always use strong passwords
  • Keep your system updated
  • Regularly backup the /opt/bitwarden directory (automated by default)
  • Monitor logs for suspicious activity
  • Use 2FA where possible

Maintenance

Backup

Back-ups are AUTOMATED via the vw_backup container as part of the vw-compose.yml file. Default is set to daily at 5 AM.

For manual back-ups, you can back up the /opt/vaultwarden directory:

tar -czf backup.tar.gz /opt/vaultwarden

Updates

To update Vaultwarden:

docker compose pull
docker compose up -d

Troubleshooting

  1. Check container logs:
docker logs <vault_container_name>
docker logs <tunnel_container_name>
  1. Verify Nginx configuration:
nginx -t
  1. Check Cloudflare tunnel status:
docker logs <tunnel_container_name>

Contributing

Pull requests are welcome. For major changes, please open an issue first.

About

This repository contains scripts and configurations for deploying a self-hosted Vaultwarden instance with Cloudflare Tunnel integration, optional Nginx reverse proxy, and Docker Compose.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published