For a while, I was using 1Password for my personal and business accounts. However, the constantly increasing annual subscription fee and the idea of my data residing on a third-party's servers started to bother me. Especially after the latest price hike, I realized that the $5 I was paying monthly to 1Password could instead go towards a service I could control myself, a self-hosted solution. Since I already host many of my services on my own VPS, I decided to add a password manager to that list and ultimately settled on Vaultwarden.
The biggest factor in this decision was getting rid of an annual cost of approximately $60 and gaining full control over my passwords. When I run a system on my own server, its backup, security, and access are entirely my responsibility. This way, I both saved money and felt at ease about where my sensitive data was stored.
What is Vaultwarden and Why Did I Set Up My Own Solution?
Vaultwarden is a lightweight alternative to the open-source Bitwarden password manager, written in Rust. It works fully compatible with the Bitwarden API, meaning you can use Bitwarden's official clients (web, desktop, mobile, browser extensions) with your own Vaultwarden server. This was a significant advantage for me; I wouldn't have to get used to a new interface.
The main reasons for setting up my own password vault included cost savings and data sovereignty. An annual subscription fee of $60 becomes a significant expense, especially when I'm self-hosting multiple services. Moreover, with years of experience in enterprise software development, I know how critical it is where data resides and who controls it. Even in a production ERP, while implementing strict policies for supply chain data security, entrusting my personal passwords to someone else didn't make much sense to me. By running Vaultwarden on my own server, I ensured that my passwords are encrypted and stored only in a location I specify.
ℹ️ The Power of Open Source
Vaultwarden being open-source means the project's security can be reviewed and audited by the community. This offers an additional layer of trust compared to closed-source commercial solutions, as potential security vulnerabilities can be identified and fixed more quickly.
Pre-Installation Preparations: Essential Steps and Components
Before starting the Vaultwarden installation, I needed a few basic components. First, I acquired a Virtual Private Server (VPS). This VPS needed to have Ubuntu 22.04 LTS operating system and offer at least 1 CPU, 1 GB RAM, and 20 GB disk space. With my current VPS provider, this configuration costs around $5 per month.
Secondly, to securely access Vaultwarden over the internet, I needed a domain name and a valid SSL certificate for that domain. I decided to configure a subdomain of a domain I use for my side projects as vault.mydomain.com. For the SSL certificate, I would use Let's Encrypt, which wouldn't incur any additional cost. Finally, Docker and Docker Compose installation was essential, as running Vaultwarden in containers in an isolated manner provides great ease for both deployment and maintenance.
My last pre-installation preparation was configuring the server's firewall. I ensured that only SSH (port 22), HTTP (port 80), and HTTPS (port 443) ports were accessible from the outside. All other ports were closed. This was a critical step to minimize my server's attack surface.
# First, I updated the server
sudo apt update && sudo apt upgrade -y
# Docker and Docker Compose installation
sudo apt install docker.io docker-compose -y
# Added user to the docker group
sudo usermod -aG docker $USER
# Logged out and logged back in to ensure the change took effect
# UFW (Uncomplicated Firewall) installation and configuration
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
After completing these steps, I was ready to proceed with the actual Vaultwarden installation. These preliminary preparations took me about 10-15 minutes as someone experienced in system administration, but it might take a bit longer for beginners.
Vaultwarden Installation: Step-by-Step with Docker Compose
Installing Vaultwarden with Docker Compose is quite simple. I created a folder named vaultwarden in my home directory and placed my docker-compose.yml file inside it. This file defined the Vaultwarden service and the PostgreSQL database. I could have used SQLite, but I preferred PostgreSQL for larger-scale and more manageable solutions. Since I use PostgreSQL 14+ in my production ERP, I'm more comfortable with this database.
The content of docker-compose.yml was as follows:
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
environment:
# SMTP settings (for email notifications and password reset)
# You can delete these lines if you don't want email support
# Even in my AI services using RAG and prompt engineering, email notifications are critical.
SIGNUPS_ALLOWED: "true" # Enabled user registration for initial setup, will disable later
WEBSOCKET_ENABLED: "true" # Required for Bitwarden clients
DOMAIN: "https://vault.mydomain.com" # My domain here
ROCKET_TLS: "true" # Because I'm using SSL behind an Nginx proxy
# DATABASE_URL: "postgresql://vaultwarden:secretpassword@db:5432/vaultwarden" # If using PostgreSQL
DATABASE_URL: "data/vaultwarden.sqlite3" # To use SQLite by default
LOG_LEVEL: "warn"
TZ: "Europe/Istanbul" # Set the timezone
volumes:
- ./vw-data:/data # To persistently store Vaultwarden data
ports:
- "127.0.0.1:8000:80" # Only open to localhost, Nginx will proxy
# PostgreSQL database (optional, starting with SQLite)
# db:
# image: postgres:14-alpine
# container_name: vaultwarden_db
# restart: always
# environment:
# POSTGRES_DB: vaultwarden
# POSTGRES_USER: vaultwarden
# POSTGRES_PASSWORD: secretpassword # Please use a strong password!
# volumes:
# - ./db-data:/var/lib/postgresql/data
After saving this file, I ran the docker-compose up -d command in the terminal to start the services. The first time I ran it, Docker images were downloaded, and the services came up. It took about 30 seconds.
Nginx Reverse Proxy and SSL Configuration
The Vaultwarden service was running on port 127.0.0.1:8000. For external access, I needed to configure Nginx as a reverse proxy. This way, Nginx would manage my SSL certificate and forward encrypted traffic to Vaultwarden.
My Nginx configuration file at /etc/nginx/sites-available/vault.mydomain.com was as follows:
server {
listen 80;
listen [::]:80;
server_name vault.mydomain.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name vault.mydomain.com;
ssl_certificate /etc/letsencrypt/live/vault.mydomain.com/fullchain.pem; # To be created by Certbot
ssl_certificate_key /etc/letsencrypt/live/vault.mydomain.com/privkey.pem; # To be created by Certbot
ssl_trusted_certificate /etc/letsencrypt/live/vault.mydomain.com/chain.pem; # To be created by Certbot
# SSL Settings
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_prefer_server_ciphers on;
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Security headers
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options DENY;
client_max_body_size 128M; # For large attachments
location / {
proxy_pass http://127.0.0.1:8000;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_redirect off;
}
# For Websocket support
location /notifications/hub {
proxy_pass http://127.0.0.1:8000;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_redirect off;
}
}
To enable this configuration, I created a symbolic link and restarted Nginx:
sudo ln -s /etc/nginx/sites-available/vault.mydomain.com /etc/nginx/sites-enabled/
sudo nginx -t # Configuration error check
sudo systemctl reload nginx
Finally, I obtained the SSL certificate with Let's Encrypt:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d vault.mydomain.com
Certbot automatically updated my Nginx configuration, added the SSL certificates, and redirected the listen 80 block with return 301 https://$host$request_uri;. After this step, I could securely access the Vaultwarden interface at https://vault.mydomain.com. The initial setup and Nginx/SSL configuration took a total of about 45 minutes.
Security and Maintenance: How I Protect My Own Password Vault
By setting up my own password vault, the responsibility for security and maintenance entirely shifted to me. For me, this wasn't a risk but rather more control. The main security measures I took were:
- Strong Master Password and 2FA: I set a very strong, long, and complex master password to access my Vaultwarden account. Additionally, I enabled two-factor authentication (2FA) with an OTP application (Authy) on my mobile phone. This significantly increased the login security of my password vault.
- Disabling User Registration: I had initially set
SIGNUPS_ALLOWED: "true". Immediately after creating my own account, I updated thedocker-compose.ymlfile toSIGNUPS_ALLOWED: "false"and restarted the service withdocker-compose up -d. This prevented new users from registering on my server and reduced the risk of unauthorized access. -
Regular Backups: Data loss is unacceptable for a critical service like a password manager. Therefore, I take regular backups of the
vw-datafolder. Using thetarcommand, I automatically compress this folder nightly with acronjob and send it to a secure storage location on another server.
# Command to add to Crontab (example) # 0 3 * * * /usr/bin/tar -czf /path/to/backup/vaultwarden_backup_$(date +\%Y\%m\%d).tar.gz /path/to/vaultwarden/vw-dataThis also resembles my backup strategies for ERP servers where I deal with issues like
PostgreSQL WAL bloat. Keeping Up-to-Date: Regularly updating Docker images is critical for patching known security vulnerabilities. Once a month, I run
docker-compose pullfollowed bydocker-compose up -d.Fail2ban and SSH Security: I use
fail2banon my server to prevent SSH brute-force attacks. Additionally, I moved the SSH port from the default 22 to a different port and only allow key-based authentication. Since I saw SSH brute-force attacks start within 7 minutes when I opened a VPS for one of my side projects' backends, I always take these precautions.Monitoring System Logs: I regularly check Docker container logs and Nginx access logs with
journalctl. I'm vigilant for abnormal activity or error messages. I also usesystemd-cgtopto check if soft limits likecgroup memory.highare exceeded.
⚠️ At Your Own Risk!
Hosting your own password vault means you are solely responsible for all security and maintenance. Failing to back up, neglecting updates, or using weak passwords can lead to your data being compromised. Therefore, diligently following these steps is vital.
These security and maintenance routines take me about 15-20 minutes weekly in total. However, this time is a small price to pay for the security of my passwords and having them under my control.
Data Migration Process from 1Password to Vaultwarden
The transition process from 1Password to Vaultwarden was quite smooth. Since Bitwarden clients support importing password files in various formats, this operation was easily done.
As a first step, I exported my passwords from the 1Password desktop application. 1Password's export options include .csv and .json formats. I preferred the .json format as it provides more data integrity. During the export process, 1Password saved all my vaults into a single encrypted .json file. I checked the content of this file and ensured that sensitive data was exported correctly.
ℹ️ Export Security
When exporting your passwords, ensure that this file is not in an insecure location, even temporarily. Don't forget to securely delete this file after the process is complete. In my case, I immediately deleted the exported file with the
shred -ucommand after the operation, leaving no traces on the disk.
Next, I downloaded the Bitwarden desktop application to my computer. I hadn't connected it to my own Vaultwarden server yet, as it was easier to import the data locally first. After opening the Bitwarden application, I found the "Import Data" option from the "File" menu. Here, options like "1Password (JSON)" or "1Password (CSV)" were listed. I selected the JSON file I had previously exported and started the import process.
The import process usually takes a few seconds. All my passwords, notes, credit card information, and identities began appearing in the Bitwarden application. At this stage, I checked all imported items one by one. I specifically ensured that URLs, usernames, and passwords matched correctly. Some special fields or attachments might not be fully transferred during import, but in my case, I didn't encounter any major issues.
Finally, I connected the Bitwarden desktop application to my own Vaultwarden server. To do this, I selected the "Self-hosted environment" option from the application settings and entered my server's URL (https://vault.mydomain.com). Then, I logged in with the username and master password I created on my Vaultwarden server. After this process, all the data I had imported locally was automatically synchronized to my own Vaultwarden server.
This migration process took me approximately 20 minutes. This was a fairly quick and painless process for switching to a new password manager.
My Experiences and Lessons Learned: Why It Was Worth It?
Several months have passed since I set up my own password vault with Vaultwarden, and I understand the correctness of my decision better every day. My most significant gain, of course, has been cost savings. Instead of a $60 annual 1Password subscription, I now use a very small fraction of my VPS for Vaultwarden. This makes a significant difference for someone like me who develops multiple side projects and manages their own infrastructure. Running Vaultwarden on the same VPS where I host the backend of my custom financial calculators ensures efficient resource utilization.
The second major advantage is data control. Having my passwords and other sensitive information reside on a server I specify and manage gives me great peace of mind. My risk of being directly affected by a potential data breach or service outage from a third-party company is reduced. This is invaluable, especially for someone who understands how critical data sovereignty is in enterprise software architecture.
Of course, every coin has two sides. Managing my own server also brings the responsibility of regular maintenance and security updates. The initial setup and configuration took me about 2 hours. However, this didn't impose an additional burden on me, as I already have nearly 20 years of experience in system administration and network security. In fact, routine tasks like monitoring Vaultwarden's status with systemd units and checking logs with journalctl were even enjoyable for me. Unlike the performance issues I experienced while working on Redis OOM eviction policy selections, I haven't encountered such serious performance problems with Vaultwarden.
With this transition, I not only changed my password management but also further strengthened my own infrastructure and had the opportunity to review my security practices once again. This experience showed me once more that with the right tools and a little technical knowledge, we can set up affordable and secure alternatives to many expensive services offered by large companies.
Conclusion: Owning Your Own Vault
My decision to switch from 1Password to Vaultwarden has been very productive for me, both financially and technically. Getting rid of a $5 monthly cost and taking full control of my passwords was an important step that reinforced my digital sovereignty. The technical details of the setup process and the subsequent regular maintenance responsibility were more of an enjoyable challenge than a burden for someone with a system administration background like me.
If you also have similar cost concerns or want to keep full control of your data, you should definitely consider open-source and self-hosted solutions like Vaultwarden. Although it requires some time and technical knowledge initially, the long-term benefits are definitely worth it. Remember, being the true owner of your own data in the digital world is becoming increasingly critical. Next, perhaps I can share my experience of setting up my own DNS server, where I also encountered interesting negative caching scenarios.
Top comments (0)