How to Secure Vaultwarden with Nginx Proxy Manager
Learn how to expose your self-hosted Vaultwarden instance to the internet securely using Nginx Proxy Manager and Let's Encrypt for valid SSL termination.
Disclosure: this article contains an affiliate link. DotExe may earn a commission if you purchase through it, at no extra cost to you. Any discount is subject to Hostinger's current offers (20% OFF) and eligibility terms.
Vaultwarden is a lightweight, high-performance implementation of the Bitwarden API, written in Rust. It is an excellent choice for managing sensitive credentials in a private environment, offering a feature-rich experience while remaining significantly more resource-efficient than the official Bitwarden server. However, because Vaultwarden handles your most sensitive data—your passwords, recovery codes, and identity information—exposing it to the internet requires a robust security posture. A fundamental requirement for modern web applications is the use of HTTPS, which is strictly enforced by the Vaultwarden client applications. To achieve this, you need a reverse proxy that handles SSL termination and routes traffic to your container. In this guide, we will walk through how to secure Vaultwarden with Nginx Proxy Manager (NPM). NPM provides a user-friendly interface for managing Nginx configurations and automating the acquisition of Let's Encrypt SSL certificates, making it an ideal choice for self-hosted setups.
Prerequisites and Assumptions
Before starting, ensure you have the following:
- A server running Linux with Docker and Docker Compose installed.
- A registered domain name pointing to your server's public IP address.
- Ports 80 and 443 open on your firewall and forwarded to your server.
- Basic familiarity with Docker Compose and networking concepts.
If you are looking for a reliable environment to host your services, you might consider Hostinger Web Hosting. Disclosure: this article contains an affiliate link. DotExe may earn a commission if you purchase through it, at no extra cost to you. Any discount is subject to Hostinger's current offers (20% OFF) and eligibility terms.
Why Reverse Proxying Matters
Running a web service directly on a host port is rarely a good idea in production. A reverse proxy like Nginx Proxy Manager acts as a gatekeeper. It terminates SSL/TLS connections, meaning the encryption handshake happens at the proxy rather than the application container. This offloads the computational burden of encryption from your application, allows for centralized certificate management, and provides a layer of abstraction between the public internet and your internal container network. By using NPM, you gain a GUI-based interface to manage complex Nginx directives, such as WebSocket support, which is critical for Vaultwarden's real-time synchronization features.
Deploying Vaultwarden with Docker Compose
First, we need to define our Vaultwarden service. Create a directory for your project and a docker-compose.yml file. We will use a standard configuration that persists data to a local volume. We also define a custom network to ensure the container is isolated from the host's default bridge.
version: '3.8'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- SIGNUPS_ALLOWED=false
- DOMAIN=https://vault.yourdomain.com
volumes:
- ./vw-data:/data
networks:
- proxy-net
networks:
proxy-net:
external: true
Note that we set SIGNUPS_ALLOWED=false to prevent unauthorized users from creating accounts on your instance once it is exposed. We also place the container on a dedicated Docker network named proxy-net, which allows Nginx Proxy Manager to communicate with the container without exposing the Vaultwarden port directly to the host machine's public interface. This is a crucial security step; by not mapping ports on the host, you ensure that the only way to reach Vaultwarden is through the proxy.
Setting Up Nginx Proxy Manager
Nginx Proxy Manager acts as the gateway for your services. If you haven't already, deploy NPM using a similar Docker Compose structure. Ensure it is connected to the same proxy-net network defined above. Once NPM is running, log into the web interface (usually on port 81). Navigate to the "Proxy Hosts" tab and click "Add Proxy Host".
- Domain Names: Enter the subdomain you intend to use (e.g.,
vault.yourdomain.com). - Scheme: Select
http. - Forward Hostname/IP: Use the service name defined in your Vaultwarden
docker-compose.yml(e.g.,vaultwarden). - Forward Port: Use
80(the internal port Vaultwarden listens on). - Websockets Support: Enable this toggle. Vaultwarden requires WebSocket connections for real-time synchronization between the server and your browser extensions or mobile apps. Without this, you will experience sync errors.
Configuring SSL with Let's Encrypt
After saving the proxy host, click the three dots next to your new entry and select "Edit". Navigate to the "SSL" tab.
- SSL Certificate: Select "Request a new SSL Certificate" from the dropdown.
- Let's Encrypt: Enable "Force SSL" and "HTTP/2 Support".
- Email: Enter your email address for renewal notifications.
- Terms of Service: Agree to the Let's Encrypt terms.
Click save. NPM will now communicate with Let's Encrypt to validate your domain and issue a certificate. Once finished, your Vaultwarden instance will be accessible via https://vault.yourdomain.com. The "Force SSL" option is critical because it ensures that any unencrypted HTTP traffic is automatically upgraded to HTTPS, preventing accidental transmission of credentials over insecure channels.
Advanced Security Considerations
Exposing a password manager to the internet is a significant security decision. While HTTPS provides encryption in transit, you should implement additional layers of protection to mitigate the risks of public exposure.
Disabling Signups and Limiting Access
As shown in our configuration, set SIGNUPS_ALLOWED=false once your account is created. This prevents attackers from registering new accounts on your instance to probe for vulnerabilities or use your resources. If you need to add new users, you can temporarily flip this to true and restart the container, but it should remain false by default.
Strong Master Passwords and 2FA
Since the vault is the single point of failure, ensure your master password is long, unique, and stored in a physical location if necessary. Enable 2FA within Vaultwarden to add a second layer of authentication. Even if an attacker gains your master password, they will be blocked without the second factor. Consider using hardware security keys (like YubiKey) for the highest level of protection.
Server Hardening
Follow best practices for Hardening Your Linux Server: A Practical Checklist for Production Security to ensure the underlying host is not compromised. This includes disabling root SSH logins, using a firewall (UFW) to restrict access to only essential ports, and keeping your system packages updated.
Monitoring and Maintenance
Self-hosting requires diligence regarding data integrity. Ensure you have a strategy for Designing Self-Hosted Backups You Can Actually Restore. For Vaultwarden specifically, you should regularly back up the vw-data directory, which contains the SQLite database and attachments. If you are using a more complex setup, consider Automating Vaultwarden Backups: A Complete Strategy for SQLite and PostgreSQL. For high-traffic or enterprise-grade deployments, you may also want to look into Vaultwarden High Availability Scaling Production.
Troubleshooting Common Issues
If you cannot access your instance, check the following:
- Container Connectivity: Ensure both the Vaultwarden container and the Nginx Proxy Manager container are on the same Docker network. You can verify this by running
docker network inspect proxy-net. - Firewall Rules: Verify that your server's firewall (e.g., UFW) allows traffic on ports 80 and 443. If you are using a cloud provider, check their security group settings as well.
- DNS Propagation: If you just added the DNS record, it may take time to propagate. Use
digornslookupto verify that your domain resolves to your server's IP. - Logs: Use
docker logs vaultwardenand the logs within the NPM interface to identify specific handshake or routing errors. Common issues include "502 Bad Gateway" which usually indicates the proxy cannot reach the container, or "403 Forbidden" which might relate to file permissions.
Understanding the Traffic Flow
To better understand why this setup is secure, consider the flow of a request. When a user navigates to https://vault.yourdomain.com, the request hits your public IP on port 443. Nginx Proxy Manager receives this request, performs the SSL handshake using the Let's Encrypt certificate, and decrypts the traffic. It then forwards the decrypted request to the vaultwarden container over the internal proxy-net network. Because the vaultwarden container is not exposed on the host's public interface, it cannot be reached directly by external traffic, effectively shielding it from direct attacks on its internal API endpoints.
Why HTTPS is Non-Negotiable
Vaultwarden and the official Bitwarden client applications enforce HTTPS to ensure that sensitive data, such as your vault contents and master password, are encrypted during transit. Furthermore, modern web browsers restrict access to certain APIs, such as the Web Crypto API, to "Secure Contexts" (HTTPS). Without HTTPS, the browser will block the vault's core functionality, rendering the application unusable. By using Nginx Proxy Manager to handle this, you ensure that your instance meets these strict requirements while keeping your internal container configuration simple and focused on application logic rather than certificate management.
Frequently Asked Questions
Do I need to open port 80 and 443 on my router?
Yes, you must forward ports 80 and 443 from your router to your server's internal IP address to allow Nginx Proxy Manager to receive traffic and perform the Let's Encrypt validation challenge. Port 80 is specifically required for the ACME HTTP-01 challenge, which proves you own the domain.
Why does Vaultwarden require HTTPS?
Vaultwarden and the official Bitwarden client applications enforce HTTPS to ensure that sensitive data, such as your vault contents and master password, are encrypted during transit and to enable features like the Web Crypto API. Without a secure context, the browser will prevent the application from functioning correctly.
Can I use a self-signed certificate instead of Let's Encrypt?
While you can use a self-signed certificate, most client applications will reject it by default, requiring you to manually trust the certificate on every device, which is cumbersome and less secure than using a valid, automated certificate from Let's Encrypt. Using a valid certificate avoids these trust issues and ensures seamless synchronization.
Does Nginx Proxy Manager handle certificate renewals automatically?
Yes, Nginx Proxy Manager automatically tracks the expiration of your Let's Encrypt certificates and attempts to renew them before they expire, provided your server remains reachable on port 80. This automation eliminates the risk of your service going down due to an expired certificate.