Hey there password protectors, or, soon to be fellow password protectors!
Ever wanted a password manager that supports pretty much any feature you want out of the box AND you wanted to be it’s gatekeeper? Well, meet VaultWarden; your soon to be go-to in the world of password management. In this guide we will be setting up an install of VaultWarden using an AWS EC2 instance with docker and docker-compose for easy management and updates.
Why VaultWarden? Link to heading
Think of it as your own personal digital vault (hence the name) where you can securely store all your passwords, credit card info, and other sensitive stuff. It’s like a fortress for your digital secrets (as long as you know what you are doing). VaultWarden is self hosted and open source, that means you’re in control; which comes with it’s own set of pros and cons.
- Pros
- You have complete control over your data. It’s stored on your server, and you decide how it’s managed and who has access.
- Self-hosting can provide a higher level of privacy and security because you’re not relying on a third-party service to safeguard your sensitive information.
- Unlike some cloud-based password managers, self-hosting VaultWarden usually doesn’t come with subscription fees.
- Can run on low powered devices at home such as a raspberry pi.
- Cons
- Setting up and maintaining a self-hosted solution can be complex, requiring technical knowledge in server administration, security, and networking.
- You’re responsible for the security of your server, including updates, patches, and backups. Neglecting these responsibilities can lead to vulnerabilities.
- You have to rely on community forums and documentation for support.
Why AWS and how is it free? Link to heading
AWS, simply by sheer scale, is a reliable means of having a self hosted server (or instance in this case) that is easily manageable. They offer a free tier to brand new accounts, it lets you try out their services with minimal risk. The free tier lasts for 12 months from the date of account creation; there are limits on what you can and can’t use and exceeding those limits will incur charges. It’s an easy way to jump into the world of AWS; as long as you keep an eye on your usage.
The Plan Link to heading
Time to get into the nitty gritty of it all. How are we going to get VaultWarden running and operational? The easiest way would be through AWS Fargate and ECS, but there are two problems:
- Using this method will incur monthly costs.
- What fun is doing things the easy way? We’re here to learn!
What we will be doing instead is
- Setup a t2.micro EC2 instance with the current Ubuntu Server LTS OS that is “Free tier eligible”.
- We will then update the instance, install docker and docker-compose.
- Use the official VaultWarden docker image along with caddy for setup.
- Finally harden the VaultWarden setup.
Prerequisites Link to heading
- A domain name if you wish to access your VaultWarden install over the internet & enable SSL vs a private local network. This guide will be focusing on using a domain.
- An AWS account created and setup with the region of your choice selected.
- An IAM user with the appropriate policies enabled for configuring EC2, KMS & Route 53 (The latter is only needed If using AWS to manage the domain). You can technically use your root AWS account; however, it’s generally not recommended due to security best practices. A guide to setup IAM permissions or purchase and setup a domain using route53 is currently out of scope for this guide, however, I will have a write-up linked once it’s ready.
- OpenSSH or Putty depending on the key pair created to SSH into the instance.
- A GitHub account (optional, but recommended).
Setting Up a t2.micro EC2 Instance with an Elastic IP Link to heading
- Login to your AWS console using your IAM user.
- On the search bar at the top of the page, search for
EC2
and select theEC2, Virtual Servers in the Cloud
service. - Click on the
Launch Instance
button, usually located right below theResources
section. - Make the following selections:
- Name and tags: VaultWarden.
- Application and OS Images: Ubuntu Server 22.04 LTS (or whichever version is
free tier eligible
). - Instance type: t2.micro (will have the label
Free tier eligible
). - Key pair: Choose a key-pair; if one exists you should already have the private key file. Alternatively create a new key pair and save the private key file somewhere safe.
WarningYou cannot access the instance using SSH without your private key file. It is your password; keep it safe.
- Network Settings:
- Network: Keep the default selection, a different VPC is generally not required.
- Subnet: Keep the defaults.
- Auto-assign public IP: Enable.
- Firewall (security groups): Create security group.
TipNote down the name of the security group, you will need it later.
- Allow SSH traffic from: Enable this option by ticking the check box, in the drop down beside it change the value to
My IP
. This limits SSH access to your ip address, you can always change it within the security groups later. - Allow HTTPS traffic from the internet: Leave unchecked.
- Allow HTTP traffic from the internet: Leave unchecked.
- Configure Storage: Click the
Advanced
button on the right side of the title.- Storage Type: EBS
- Device name: /dev/sda1
- Size: 8 GiB is all you realistically need. You can go up to 30 GiB in the free tier.
- Volume Type: gp2
- Delete on termination: No. This ensures your data is retained upon termination of an instance.
- Encrypted: Encrypted. Your data is encrypted at rest.
- KMS Key: Default aws/ebs
- Go ahead and launch the instance by selecting the launch instance button on the right side of the page.
- Go back to the main EC2 Dashboard.
- On the menu located on the left side of the page, select
Elastic IPs
, found under theNetwork & Security
section. - On the top right section of the page, select
Allocate Elastic IP Address
. - Leave all the default options as is, click the
Allocate
button and an Elastic IP address will be assigned. AWS will charge you for the IP address if you do not use it. - Back in the Elastic IP Addresses page, click the checkbox beside the allocated IP to select it. Now click the
Actions
button on the top right corner of the page, and then selectAssociate Elastic IP address
. - Make the following selections in the new page:
- Resource Type: Instance.
- Instance: Search for and select the VaultWarden instance.
- Click the
Associate
button to associate the ip with the instance.
Updating the instance and setting up docker & docker-compose Link to heading
- Open the EC2 Dashboard, then select
Instances
from the menu on the left. - Click on the instance ID, to open information about it. Locate the
Public IPv4 DNS
section and save that address. - Using an SSH client of your choice, connect to the instance using the
Public IPv4 DNS
as the address,ubuntu
as the user name and the private key file for authentication. - After connecting, run
sudo apt update && sudo apt upgrade
. This will update your instance with all the latest packages and core files. - Next run the following
sudo apt install -y docker && sudo apt install -y docker-compose
. This command will install both docker and docker-compose.
- sudo: Tells the underlying Linux operating system the command must be run with root (elevated) priviledges.
- apt: Apt is the default package manager used by Ubuntu.
- -y: We are passing a “yes” to any installation prompts that might arise.
Initial Setup of VaultWarden & Changes to EC2 Security Groups Link to heading
-
Run the following to make sure you’re in your home directory
cd ~/
. -
We’re going to use my ready to go VaultWarden-Example repo to setup the docker-compose.yml file, .env and Caddyfile files. Run this command to get started:
git clone https://github.com/drunknsorry/VaultWarden-Example.git
. -
Run
ls
and you should see the folder VaultWarden-Example listed. Lets rename it to VaultWarden by running the commandmv ./VaultWarden-Example ./VaultWarden
. -
Lets open the folder by running
cd VaultWarden
. Now let’s rename example.env to .env by runningmv ./example.env ./.env
. Once done run the commandls -a
to make sure the .env file is in the folder. -
Now it’s time to start making some configuration changes. The .env file and docker-compose.yml files are pre-populated with the most common options you need to set. You simply need to uncomment the relevant lines and update their values.
-
Lets start with the docker-compose.yml file. Run
nano docker-compose.yml
, this will open up the file in a text editor. All relevant options have a description in the in-line comments; please go through them in detail. Once you’ve enabled or disabled options, pressctrl + x
and theny
to save and exit.WarningTheADMIN_TOKEN
is commented out and disabled by default. The only protection mechanism for the admin panel once enabled is the password you implement along with any ip restriction you implement to that sub-directory. If you want to use the admin panel, please follow the instructions in the docker-compose.yml file to generate a strong argon2 token. If argon2 is not available simply runsudo apt install argon2
to install it. -
Next is the .env file. Run
nano .env
. Uncomment all the variables you need and replace the values after the equal sign with your values; there should be no space following the “=”. Please ensure only the variables enabled in your docker-compose.yml are uncommented. Once done pressctrl + x
and theny
to save and exit. -
We also have a Caddyfile which is setup to enable access logs through Caddy, auto perform ACME challenges to setup an SSL cert via letsencrypt, and pass on IP Addresses to Rocket to use with fail2ban. You can see the contents by running
nano Caddyfile
. No changes are needed so usectrl + x
to exit. -
In a browser window open your EC2 dashboard. On the menu located on the left side of the page, select
Security Groups
, found under theNetwork & Security
section. -
Click on the “security group id” of the security group you created earlier. In the new page select
Actions
on the top right corner and thenEdit Inbound Rules
. -
You should already see one rule allowing SSH access from your IP. Click the
Add rule
button and add the following two rules:-
- Type: HTTP
- Source type: Anywhere-IPv4
-
- Type: HTTPS
- Source type: Anywhere-IPv4
Save the changes by clicking
Save rules
on the bottom right corner of the page. What we’ve done is allow all traffic to the server over port 80 and port 443. -
-
Back in your SSH session, make sure you’re back in the VaultWarden folder by running
cd ~/VaultWarden
. -
Now run
sudo docker-compose up -d
. If everything is setup as above, your VaultWarden instance is up and running. Simply navigate to the domain you setup inside the .env file.
- .env: Known as environment variables file. Usually used to store sensitive information that you don’t want hard coded.
- docker-compose.yml: Used to define and launch multi container applications. The file allows launching and controlling all services from a single location.
- ls: Lists all files and folders in the current folder/directory; does not list hidden files.
- ls -a: Lists all files and folders in the current folder/directory, including hidden files.
- mv: Is the move file or folder command, works well to rename as well.
- nano: A command line text editor in Linux. Others exist such as vim; I just prefer nano.****
- docker-compose up: Launching the containers and network within the docker-compose.yml file
- docker-compose up -d: Launching the containers and network, but, running in the background.
Hardening VaultWarden Link to heading
There are a few things we can do to keep things secure, some have already been taken care of within the Caddyfile and will be explained below.
- Caddy (All of the following are already applied in your Caddyfile)
- Strict SNI: Caddy automatically enables this. Strict SNI ensures the site can only be accessed while using the domain name and not the IP address.
- Strict-Transport-Security “max-age=31536000;”: Setting a header value letting the browser know it should never load our site without https.
- X-XSS-Protection “1; mode=block”: Setting a header value enabling cross-site filter (XSS) and letting the browser know to block detected attacks.
- X-Frame-Options “SAMEORIGIN”: Setting a header value stopping the site from being used in an iframe.
- X-Robots-Tag “none”: Setting a header value telling search engines to ignore the site.
- -Server: Removing identifiable server information.
- Run Docker as a non-root user
- The basic setup strikes a decent balance between keeping things secure and user-friendly. When you run it as the main administrator (root) inside a Docker container that doesn’t have full access to your system, it’s pretty safe. Plus, it’s simpler for people who might not be Linux experts and don’t want to fuss with complex ownership and permission settings. That said, when it comes to security, it’s smarter to run programs with the absolute minimum level of access they need.
- You can see this implemented in the docker-compose.yml file on line 7
user: 1000:1000
. 1000 user id (uid) and group id (gid) is generally the default on most Linux distributions. To very this runid
. - Remove
sudo
when launching from docker-compose.yml
- fail2ban
- Setting up fail2ban is encouraged for the vault. VaultWarden provides a pretty detailed guide to help with setup.
That’s it. I hope the guide helps you setup your very own password vault; with you as it’s gatekeeper. For better or for worse.
Backup and maintenance Link to heading
- AMI: Amazon Machine Image’s allow you to save a copy of the instance in it’s current form. These images can be restored with very little downtime and are ready to be deployed. I recommend creating at least one image every 6 months if solely for personal use. To create an image follow these steps:
- Login to AWS and go into your EC2 dashboard. In the menu on the left side select
instances
. - Select the checkbox for your instance.
- On the top right corner select
Actions
and thenImage and templates
and finallyCreate Image
. - Give your image an identifiable name such as “VaultWarden_Month_Day_Year”
- Select the
Create image
button on the bottom right corner of the page and you’re done.
- Login to AWS and go into your EC2 dashboard. In the menu on the left side select
- Data Snapshots: Take regular point in time snapshots of the data either manually or with a data life-cycle policy.
- Login to AWS and go into your EC2 dashboard. In the menu on the left side select
Volumes
. - Select the checkbox for your volume.
- On the top right corner select
Actions
and thenCreate snapshop
- Give your snapshot an identifiable description such as “VaultWarden_Month_Day_Year”
- Select the
Create snapshot
button on the bottom right corner of the page and you’re done.
- Login to AWS and go into your EC2 dashboard. In the menu on the left side select
- Updates: Periodically login to your instance and update it’s packages. Follow these steps:
- Login to your EC2 instance using SSH.
- Take your containers down using
sudo docker-compose down
. - Run
sudo apt update && sudo apt upgrade
to update packages from Ubuntu. - Run
cd ./VaultWarden
to get into the docker-compose.yml folder. - Run
docker-compose pull
to pull any new updates to VaultWarden. - Start your containers using
sudo docker-compose up -d
. - And you’re done. In most cases nothing else is needed.
I really am done now. I hope all of the above helps! If you spot any errors or run into problems feel free to get in touch.
Ok… maybe I lied, here’s a little bit more.
Additional Guides Link to heading
- Adding a WAF (Web Application Firewall) Article coming soon
- Auto deployments through github Article coming soon