Seeking Guidance: How to Self-Host Bitwarden with Cloudflare Integration

Hello there, I'm diving into setting up Bitwarden on a Linode VPS and honestly, I'm pretty new to all this. I've got Docker and Ubuntu 23.04 up and running, and now I'm looking at adding Cloudflare into the mix for extra security. The thing is, I'm at a bit of a loss on where to even begin. The initial setup was a breeze since the Bitwarden self-installer took care of the SSL configuration with Certbot and Let's Encrypt. But now, when it comes to integrating Cloudflare, especially for securing my domain and subdomains, I feel out of my depth. I would really appreciate some guidance on: The basics of integrating Cloudflare with a Bitwarden setup on Docker/Ubuntu. Essential steps to secure my domain and subdomains with Cloudflare. Any beginner-friendly resources or tips to help me navigate this new territory. If anyone can point me in the right direction or share some beginner-friendly advice, it would mean a lot. Thanks so much for your help! Note: I am using a clouldflare owned Domain. https://bitwarden.com/help/install-on-premise-linux/
Bitwarden
Linux Standard Deployment | Bitwarden Help Center
This article guides you through the process of installing and deploying the Bitwarden password manager to a Linux server.
59 Replies
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Hey @Achllys I'd be happy to help, there's a few things I'd do from here to harden your server and add Cloudflare into the mix. Given this is a password manager, the most secure way to handle such a server is to block ALL incoming connections from everywhere (except for maybe your own IP for SSH purposes), and then use Cloudflare Tunnels to expose the Bitwarden app to the internet via an outbound only connection. This way, there's no possible way that anyone can compromise your server or access Bitwarden without going through Cloudflare. You can block all incoming connections either through your cloud provider's dashboard, or by using iptables or UFW directly on the server. You can follow the instructions to setup a tunnel here: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/ After all this is done, you can add further WAF rules at Cloudflare to lock down who can access Bitwarden.
Create a remotely-managed tunnel (dashboard) ยท Cloudflare Zero Trus...
Follow this step-by-step guide to get your first tunnel up and running using Zero Trust.
achllys
achllysโ€ข6mo ago
@AlphaCentauri so, should I use the ssl with bitwarden still or what would you suggest? can they both work side by side?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
I would continue to use the automated SSL configuration, mostly because it allows you to easily migrate away from Cloudflare if you ever need to without having to worry about configuring SSL at that point. The Tunnel should work without you making any changes to your Bitwarden configuration.
achllys
achllysโ€ข6mo ago
thank you if I bought a name through clouldflare would I do the nameservers of clouldflare there? unsure though
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Yes, if you purchase a domain through cloudflare, the nameservers are automatically set to your assigned ones
achllys
achllysโ€ข6mo ago
so, I can skip this thank you @AlphaCentauri through docker or not?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
What do you mean through Docker? Do you mean run the Cloudflare Tunnel via docker? If so, yeah, that'll work just fine. Though if you're not using Docker for Bitwarden then it probably makes more sense to just install Cloudflared on the host machine directly
achllys
achllysโ€ข6mo ago
What's better practice? I run most of my applicactions on docker?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
There's no objective better option, it all depends on what best fits your use case. If you run most of your applications in Docker, then it makes perfect sense to choose Docker for Cloudflared too!
achllys
achllysโ€ข6mo ago
Oh, alright so now I'm confused. I did this. but forgot to remove the 2 numbers of the ip in the ss emma
AlphaCentauri
AlphaCentauriโ€ข6mo ago
So your second entry is incorrect as you won't have a protocol/prefix of HTTPs on Port 80, so you'll need to edit/delete that. Also you don't need two entries, if your app is listening on port 80, you can just have one entry pointing to http://localhost:80 and everything will work fine.
achllys
achllysโ€ข6mo ago
local host would be my ip right?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
You can actually just use localhost because Cloudflared can connect to your service via localhost as it's installed on the machine itself. Your public IP should also work, but using localhost makes migration a little easier.
achllys
achllysโ€ข6mo ago
hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Give me a moment, I'm going to read the guide you followed to understand how you've configured everything on your server ๐Ÿ˜„
achllys
achllysโ€ข6mo ago
im sorry lmao
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Nah it's all good ๐Ÿ˜„ I have Bitwarden setup myself, but I use the much nicer Rust unofficial implementation called Vaultwarden which works much faster and easier tbh. Alright, let's do a sanity check and I'll try to help you get this working. Can you run docker ps and send me a screenshot of what's running? And also can you confirm that if you visit your server's IP address in the browser with HTTP, does it launch Bitwarden there?
achllys
achllysโ€ข6mo ago
fixed it lol it was https
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Lol Tbh the way you've setup Certbot isn't ideal because it needs to run on the same ports as Bitwarden to generate a certificate. It makes more sense to run a DNS challenge with Cloudflare API keys if you want to generate your own SSL certificate. Or better yet, just use a self signed certificate or use HTTP only and let Cloudflare handle SSL for you which is much simpler
achllys
achllysโ€ข6mo ago
How would I do that I'm sorry ;-;
AlphaCentauri
AlphaCentauriโ€ข6mo ago
To make things much easier, I would remove Certbot completely and solely run Bitwarden on your server. You can then specify N for all the options relating to SSL certificates. If you do that, all you then have to do is use the tunnel to proxy http://localhost:80 and everything will work perfectly. If you read that last option, Cloudflare Tunnels will act as the HTTPS proxy so you can avoid all the extra complications.
achllys
achllysโ€ข6mo ago
Did that website isn't up or anything
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Can you run some troubleshooting steps for me and I'll help you get it working. Firstly, if you type your server's IP in the browser like http://1.2.3.4, does it launch the Bitwarden Web UI? You may have to ignore certificate warnings, but we need to ensure that it's actually live.
achllys
achllysโ€ข6mo ago
It does not for some reason
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Okay, so you'll need to troubleshoot Bitwarden itself in this case, as it doesn't seem to be running. It won't be a Cloudflare issue as there's nothing to proxy at the moment.
achllys
achllysโ€ข6mo ago
ah alright
AlphaCentauri
AlphaCentauriโ€ข6mo ago
If you want, I have some free time right now and can send you a fully configured docker-compose.yml file for Vaultwarden which should work out of the box
achllys
achllysโ€ข6mo ago
I wouldn't mind that actually I've wanted to get that working for awhile, but it was a bit too confusing for me as I'm pretty new to clouldflare and networking within linux
AlphaCentauri
AlphaCentauriโ€ข6mo ago
That's fair, I'll help you set it up as I'm procrastinating right now from my actual job and need something else to do ๐Ÿ˜‚ Give me 5 minutes and I'll write a quick file for you that incorporates Bitwarden + Cloudflared
achllys
achllysโ€ข6mo ago
thank you :DDDDDDDD mind sending me this one actually?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Sure thing, so first you'll need to first perform the following commands to remove your old containers and to set up the structure for Bitwarden: Step 1: docker stop $(docker ps -a -q) (this stops ALL your Docker containers) Step 2: mkdir -p /opt/achllys/containers/vaultwarden/data/ (this creates the persistent directory for your Vaultwarden data) Step 3: cd /opt/achllys/ && touch docker-compose.yml (this creates your docker-compose file) Then, type nano /opt/achllys/docker-compose.yml and paste the following in:
version: '3.8'
services:

bitwarden:
container_name: bitwarden
image: vaultwarden/server:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
network_mode: host
volumes:
- /opt/achllys/containers/vaultwarden/data/:/data/

cloudflare_tunnel:
container_name: cloudflare_tunnel
image: cloudflare/cloudflared:latest
restart: unless-stopped
network_mode: host
command: tunnel run
environment:
- TUNNEL_TOKEN=PASTEYOURTOKENHERE
version: '3.8'
services:

bitwarden:
container_name: bitwarden
image: vaultwarden/server:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
network_mode: host
volumes:
- /opt/achllys/containers/vaultwarden/data/:/data/

cloudflare_tunnel:
container_name: cloudflare_tunnel
image: cloudflare/cloudflared:latest
restart: unless-stopped
network_mode: host
command: tunnel run
environment:
- TUNNEL_TOKEN=PASTEYOURTOKENHERE
You will need to replace PASTEYOURTOKENHERE with your Cloudflared token that starts with ey........ Then, run docker compose up -d and make sure your Tunnel is configured like before with http://localhost:80 And you should be able to access the Web UI Let me know if you need any more help setting it up ๐Ÿ™‚
achllys
achllysโ€ข6mo ago
Is the tunnel token this?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Nope One sec
achllys
achllysโ€ข6mo ago
ah okay thank you ๐Ÿ˜„
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Go to this page by clicking on the Tunnel and pressing Configure and find the token within the code box that starts with ey
achllys
achllysโ€ข6mo ago
O that
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Do you see a long string starting with ey Yup haha You'll have to paste the entire thing in a text editor and extract the token And paste just the token in the compose file
achllys
achllysโ€ข6mo ago
and the website no worky ;-;
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Works for me ๐Ÿ˜„
achllys
achllysโ€ข6mo ago
Did you have to install anything else apart from the docker?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Can you type the following : docker stop $(docker ps -a -q) You shouldn't have two tunnels active Then make sure that no docker containers are running by typing docker ps Once you have confirmed that, type cd /opt/achllys/ && docker compose up -d Then type docker ps again and make sure only two containers are active
achllys
achllysโ€ข6mo ago
OMG TYSM
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Hahaha ๐Ÿ˜‚ congrats ๐ŸŽ‰ No worries at all! Glad I could help you get it working ๐Ÿ˜„
achllys
achllysโ€ข6mo ago
i appricate this so much ๐Ÿ˜„
AlphaCentauri
AlphaCentauriโ€ข6mo ago
You're most welcome haha! You caught me while I had some free time bored at work so I don't mind at all ๐Ÿ˜‚
achllys
achllysโ€ข6mo ago
I can't wait to learn more about networking with clouldflare @AlphaCentauri what do you use for emails? SMTP?
AlphaCentauri
AlphaCentauriโ€ข6mo ago
I don't use email as I only use Bitwarden internally, but yes, you can add the following to the bitwarden service in the docker-compose file to set up SMTP:
environment:
- SMTP_HOST=<smtp.domain.tld>
- SMTP_FROM=<vaultwarden@domain.tld>
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=<username>
- SMTP_PASSWORD=<password>
environment:
- SMTP_HOST=<smtp.domain.tld>
- SMTP_FROM=<vaultwarden@domain.tld>
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=<username>
- SMTP_PASSWORD=<password>
achllys
achllysโ€ข6mo ago
I get the email, but when I click verfiy the page is dead
AlphaCentauri
AlphaCentauriโ€ข6mo ago
What is the full URL in the browser?
achllys
achllysโ€ข6mo ago
http://localhost/#/verify-email/?userId=3a4dd047-a884-4158-acf4-76399a6588a5&token (token is shown)
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Nice, yeah you just need to use this updated docker compose file:
version: '3.8'
services:

bitwarden:
container_name: bitwarden
image: vaultwarden/server:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
network_mode: host
volumes:
- /opt/achllys/containers/vaultwarden/data/:/data/
environment:
- SMTP_HOST=<smtp.domain.tld>
- SMTP_FROM=<vaultwarden@domain.tld>
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=<username>
- SMTP_PASSWORD=<password>
- DOMAIN="https://secure.achllys.net"

cloudflare_tunnel:
container_name: cloudflare_tunnel
image: cloudflare/cloudflared:latest
restart: unless-stopped
network_mode: host
command: tunnel run
environment:
- TUNNEL_TOKEN=PASTEYOURTOKENHERE
version: '3.8'
services:

bitwarden:
container_name: bitwarden
image: vaultwarden/server:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
network_mode: host
volumes:
- /opt/achllys/containers/vaultwarden/data/:/data/
environment:
- SMTP_HOST=<smtp.domain.tld>
- SMTP_FROM=<vaultwarden@domain.tld>
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=<username>
- SMTP_PASSWORD=<password>
- DOMAIN="https://secure.achllys.net"

cloudflare_tunnel:
container_name: cloudflare_tunnel
image: cloudflare/cloudflared:latest
restart: unless-stopped
network_mode: host
command: tunnel run
environment:
- TUNNEL_TOKEN=PASTEYOURTOKENHERE
You just need to pass the real domain to Vaultwarden
achllys
achllysโ€ข6mo ago
hmm, now the website wont start after going back to the old config it works Well, it's unreachable*
AlphaCentauri
AlphaCentauriโ€ข6mo ago
If you start it with the new config and type docker logs bitwarden what shows up? Did you make sure to replace PASTEYOURTOKENHERE in the new config?
achllys
achllysโ€ข6mo ago
I did version: '3.8' services: bitwarden: container_name: bitwarden image: vaultwarden/server:latest restart: unless-stopped security_opt: - no-new-privileges:true network_mode: host volumes: - /opt/achllys/containers/vaultwarden/data/:/data/ environment: - SMTP_HOST=smtp-relay.brevo.com - SMTP_FROM=vaultwarden@secure.achllys.net - SMTP_PORT=587 - SMTP_SECURITY=starttls - SMTP_USERNAME= - SMTP_PASSWORD= - DOMAIN="https://secure.achllys.net" cloudflare_tunnel: container_name: cloudflare_tunnel image: cloudflare/cloudflared:latest restart: unless-stopped network_mode: host
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Interesting, we are doing that. Can you try renaming it to:
- DOMAIN='https://secure.achllys.net'
- DOMAIN='https://secure.achllys.net'
Or if that also fails, try (without quotes):
- DOMAIN=https://secure.achllys.net
- DOMAIN=https://secure.achllys.net
achllys
achllysโ€ข6mo ago
it was the quates it seems alls is working now ๐Ÿ˜„
AlphaCentauri
AlphaCentauriโ€ข6mo ago
Awesome!
achllys
achllysโ€ข6mo ago
Thank you ๐Ÿ˜„
achllys
achllysโ€ข6mo ago
Hmm, if I'd want to setup openziti what would I need to do through clouldflare? https://openziti.io/
Dave Finger
Open Source Zero Trust Networking
Open Source Zero Trust Networking
OpenZiti is an open source zero trust network applying zero trust principles directly into applications through SDKs or to existing networks using tunnelers