Table of Contents
When working on side projects, I used to deploy my back end services on heroku. Well, heroku removed their free tier on November 28, 2022. I recently tried using render but for some reason my backend does not work as expected. And well, they have cold starts.
So I thought: Heck, let me run my own server.
- Terraform (to understand the syntax)
- or you can get an intro here
- Docker (used to simplify deployment of services)
- or you can get an intro here
- Brief knowledge of AWS
- or you can get an intro with my guide on medium
The goal for this setup:
- Host a web server on Amazon
- Enable HTTPS connection because many web clients require you to
load all resources via HTTPS to improve the security of your site
This repo contains the minimum setup (well, the simplest for me at least) to host your own HTTPS web server on Amazon
- An EC2 instance hosts your web server.
- The EC2 instance resides in a VPC.
- An Application Load Balancer routes incoming traffic to your instances.
- Amazon provisions a TSL certificate for your domain name.
- Create a record to map your Load balancer's domain name to your own domain name, enabling HTTPS connections to your services.
Also, we use terraform because its easier to manage your resources. (can start them up or shut them down with just 1 command, instead of going through the AWS console)
A simplistic view of how traffic is managed in this set up
- (1) Client from the internet sends a request to your domain
- (2) The
Application Load Balancer
receives the requests, determines which target to route the traffic to. - (3) The
Route Table
routes the traffic locally between the load balancer to the ec2 instance - (4, 5) The
EC2 Instance
returns a response, following the path back the way it came - (6, 7, 8) The Route Table has a default route pointing to the
Internet Gateway
, which routes traffic back out to the internet
A more detailed traffic routing can be found here, provided by AWS Docs.
- The current set up allows us to establish a
HTTPS
connection to your server via your provided domain name through the load balancer, or aHTTP
connection by direcly accessing the public IP of your ec2 instance.- Makes it easy for testing and development since we can ssh directly with the public IP.
- For the next step, to make it more secure. You can
- move your ec2 instances to private subnets
- use NAT gateway + private route table to enable internat access for instances in private subnets
- add security group rules to only allow traffic from the load balancer.
- Example youtube video on setting this up
- Adding NAT tables incur additional costs and more steps, which is why I didn't include it here.
- Have followed the steps in rest_server to create and publish a docker image of your web server to Amazon ECR
- Tutorial found here
- Create a
key pair
that can be used later for SSH access into your ec2 instance. - Tutorial found here
- Create an IAM user to run Terraform, with the following Permissions policies. Tutorial found here. (Disclaimer: we are using AWS managed policies to make it easy to create the resources required for our set up. Do fine tune the permissions according to your needs for production):
- AmazonEC2ContainerRegistryFullAccess
- AmazonEC2FullAccess
- AmazonRoute53FullAccess
- AWSCertificateManagerFullAccess
- IAMFullAccess
- Create an Access Key under IAM -> Access management -> Users -> Security credentials -> Access keys
- Get the "Access Key Id" and "Secret Access Key" and set in environment variables using the following commands in your terminal.
export AWS_ACCESS_KEY_ID=<your ACCESS KEY ID> export AWS_SECRET_KEY_ID=<your SECRET KEY ID>
- Initialize terraform workspace
cd terraform terraform init
- Update values in locals.tf specific to your project
- Create resources. (there should be 25 to add)
terraform apply
- Verify if your web server is running on the ec2 instance
- ssh into your ec2_instance
- cd into the directory with your key-pair.pem obtained from the key-pair Prequisite step above.
- Connect to your ec2 instance:
EC2 -> Instances -> Select Instance -> Click
Connect
-> Copy the ssh command - Run the command in the terminal. (in the directory with your .pem file)
- In my case, its:
ssh -i "crumble-server.pem" [email protected]
- In my case, its:
- run
sudo docker image ls
to check if your image has been successfully pulled - run
sudo docker ps
to check if a docker container for your image is running - query your endpoints to verify if its serving requests. e.g.
curl localhost:80/healthcheck
- ssh into your ec2_instance