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.
It’s fine if you have no idea what you’re doing or know the meaning of everything just yet. Just follow the guide to a T; it’s a learning experience.

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 free tier is based on usage. Make sure you don’t exceed the monthly free tier usage within an eligible service.

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

  1. Setup a t2.micro EC2 instance with the current Ubuntu Server LTS OS that is “Free tier eligible”.
  2. We will then update the instance, install docker and docker-compose.
  3. Use the official VaultWarden docker image along with caddy for setup.
  4. Finally harden the VaultWarden setup.
Please read through the entire setup below, BEFORE you attempt it. It’ll make your life a lot easier.

Prerequisites Link to heading

  1. 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.
  2. An AWS account created and setup with the region of your choice selected.
  3. 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.
  4. OpenSSH or Putty depending on the key pair created to SSH into the instance.
  5. A GitHub account (optional, but recommended).

Setting Up a t2.micro EC2 Instance with an Elastic IP Link to heading

  1. Login to your AWS console using your IAM user.
  2. On the search bar at the top of the page, search for EC2 and select the EC2, Virtual Servers in the Cloud service.
  3. Click on the Launch Instance button, usually located right below the Resources section.
  4. 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.
      You 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.
        Note 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
  5. Go ahead and launch the instance by selecting the launch instance button on the right side of the page.
  6. Go back to the main EC2 Dashboard.
  7. On the menu located on the left side of the page, select Elastic IPs, found under the Network & Security section.
  8. On the top right section of the page, select Allocate Elastic IP Address.
  9. 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.
  10. 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 select Associate Elastic IP address.
  11. Make the following selections in the new page:
    • Resource Type: Instance.
    • Instance: Search for and select the VaultWarden instance.
  12. Click the Associate button to associate the ip with the instance.
An Elastic IP is needed for us to point our domain to the VaultWarden installation.

Updating the instance and setting up docker & docker-compose Link to heading

  1. Open the EC2 Dashboard, then select Instances from the menu on the left.
  2. Click on the instance ID, to open information about it. Locate the Public IPv4 DNS section and save that address.
  3. 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.
  4. After connecting, run sudo apt update && sudo apt upgrade. This will update your instance with all the latest packages and core files.
  5. 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

  1. Run the following to make sure you’re in your home directory cd ~/.

  2. 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.

  3. Run ls and you should see the folder VaultWarden-Example listed. Lets rename it to VaultWarden by running the command mv ./VaultWarden-Example ./VaultWarden.

  4. Lets open the folder by running cd VaultWarden. Now let’s rename example.env to .env by running mv ./example.env ./.env. Once done run the command ls -a to make sure the .env file is in the folder.

  5. 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.

  6. 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, press ctrl + x and then y to save and exit.

    The ADMIN_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 run sudo apt install argon2 to install it.

  7. 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 press ctrl + x and then y to save and exit.

  8. 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 use ctrl + x to exit.

  9. In a browser window open your EC2 dashboard. On the menu located on the left side of the page, select Security Groups, found under the Network & Security section.

  10. 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 then Edit Inbound Rules.

  11. 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.

  12. Back in your SSH session, make sure you’re back in the VaultWarden folder by running cd ~/VaultWarden.

  13. 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 run id.
    • 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 then Image and templates and finally Create 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.
  • 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 then Create 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.
  • 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