This directory leverages terraform to deploy app infrastructure to AWS in the default Virtual Private Cloud (VPC).
The infrastructure defines an EC2 instance in the default VPC which can be configured using tailscale to act as a subnet router to enable private, securely encrypted communication on a tailnet between the developers local machine and the AWS VPC. This allows the developer to directly access the RDS PostgreSQL DB instance for development purposes.
- an AWS account in
us-west-2 - Terraform installed (
>=1.9.8) - a default VPC in AWS
- a Tailscale account (and a tailnet)
To set up the project for deployment, follow these steps:
-
Create
terraform.tfvarscd deployment/ cp terraform.tfvars.example terraform.tfvars -
Fill out missing fields in
terraform.tfvarsNote: At the moment it is advised to leave most of the default env vars. The app does not yet support too much configuration.
-
Initialise
terraform# This will install the hashicorp/aws provider terraform init -
Plan your deployment
# This won't do anything yet, it will just see what would happen terraform planNote: Deploying may incur fees in AWS.
-
Deploy!
terraform apply
Confirm with
yesif you are happy. -
Create
.env.prodin the root dir:cp .env.template .env.prod
-
Make amendments to
.env.prod# Set POSTGRES_HOST to the value from the terraform output # Remove/unset the LOCAL_DEV variable # You will probably also need to set the ECR_URL variable in build_and_push.sh -
Set up tailscale subnet router on the EC2 instance:
sshinto EC2 instance- Run these commands to install and run tailscale
sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://pkgs.tailscale.com/stable/amazon-linux/2/tailscale.repo sudo yum install -y tailscale sudo systemctl enable --now tailscaled echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf sudo sysctl -p /etc/sysctl.d/99-tailscale.conf sudo tailscale up --advertise-routes=172.31.0.0/16 --accept-dns=false
- Visit the link that appears in the terminal. Log into tailscale locally on the GUI to authorise the EC2 instance
- Login to https://login.tailscale.com/admin locally
- Follow all the steps in https://tailscale.com/kb/1019/subnets to configure the subnet router
- Add the AWS DNS to the tailnet to allow this:
pgcli -h terraform-20241109232645798400000002.cpzvybhopwhq.us-west-2.rds.amazonaws.com -U admin -d time_tracker
Defines an EC2 instance in the cloud with a static IP that runs the app in a docker container.
Currently only us-west-2 is supported but other AWS regions could be supported in future.
Adds an SSH key-pair to AWS such that you can SSH into the tailnet subnet router to manually setup tailscale.
Defines the networking resources required in AWS to wire up the VPC in a way that enables the RDS to communicate to other nodes in the VPC. For instance, this enables the tailscale subnet router to communicate with the AWS RDS PostgreSQL database.
Defines the AWS RDS PostgreSQL DB instance. This is your database. The database will not be accessible by the outside world directly. It will only be accessible via other nodes on the VPC such as the tailscale subnet router which is the point of access for public internet traffic.
Defines a rule which can be attached to nodes in the VPC (such as the tailscale subnet router) to allow you (and only you) to SSH into the node. This is provided for purposes of setting up tailscale on the subnet router manually.
You should notice that the rule is commented out in tailnet.tf. This is where the rule would be temporarily
enabled for setup purposes.
This is where a lot of the networking magic happens.
This file defines an EC2 instance in the VPC which acts as a tailscale subnet router
Read more: https://tailscale.com/kb/1021/install-aws
Essentially, this node acts as a router such that traffic on your tailnet can be routed into the VPC to access nodes such as the RDS DB.
The environment variable template file for the deployment.
The definition of environment variables mapped to terraform variables for use through the deployment.
Check out the /deployment/scripts/ci.sh script.
For the time being, a quick and dirty CI can be used to build, push and run a docker container in EC2 with:
./deployment/scripts/ci.shIt is slow and by no means full proof but at least we have an automated method for deploying to prod now!