-
Notifications
You must be signed in to change notification settings - Fork 23
AWS VPC Network Setup Guide
This document provides a step-by-step reference for building the Unlocked VPC network and supporting AWS resources.
- 1. Create VPC
- 2. Create Subnets
- 3. Create Internet Gateway
- 4. Create Route Tables, NAT Gateway, PrivateLink and Lattice Endpoints
- 5. Create Load Balancer
- 6. Create Domain Name (Route 53)
- 7. Create Security Group for SSM
- 8. Create Certificate
- 9. Create Instance
- 10. Create RDS (Database)
- 11. Verify Database Connection
- 12. Add Listeners to Load Balancers
- 13. Register Instance with Target Group
- Click 'Create VPC'
- Name tag:
unlockedv2_<statename>-vpc - IPv4 CIDR block: IPv4 CIDR manual input
- IPv4 CIDR:
10.0.0.0/16 - IPv6 CIDR: Amazon-provided IPv6 CIDR block
- Network border group:
us-west-2 - Tenancy: Default
- Click Create VPC
Create 4 subnets (2 private, 2 public).
- Select VPC ID of the VPC created
- Subnet Name:
unlockedv2_<statename>-subnet-private1-us-west-2a - Availability Zone:
us-<region>-2a - IPv4 subnet CIDR block:
10.0.128.0/20 - IPv6 CIDR block: Manual input
- IPv6 subnet CIDR block: Select option and set as
/64(e.g.,2600:1f14:3228:f700::/64) - Click Add new subnet
- Select VPC ID of the VPC created
- Subnet Name:
unlockedv2_<statename>-subnet-private2-us-west-2b - Availability Zone:
us-<region>-2b - IPv4 subnet CIDR block:
10.0.144.0/20 - IPv6 CIDR block: Manual input
- IPv6 subnet CIDR block: Set as
/64(e.g.,2600:1f14:3228:f701::/64) - Click Add new subnet
- Select VPC ID of the VPC created
- Subnet Name:
unlockedv2_<statename>-subnet-public1-us-west-2a - Availability Zone:
us-<region>-2a - IPv4 subnet CIDR block:
10.0.0.0/20 - IPv6 CIDR block: Manual input
- IPv6 subnet CIDR block: Set as
/64(e.g.,2600:1f14:3228:f702::/64) - Click Add new subnet
- Select VPC ID of the VPC created
- Subnet Name:
unlockedv2_<statename>-subnet-public2-us-west-2b - Availability Zone:
us-<region>-2b - IPv4 subnet CIDR block:
10.0.16.0/20 - IPv6 CIDR block: Manual input
- IPv6 subnet CIDR block: Set as
/64(e.g.,2600:1f14:3228:f703::/64) - Click Create subnet
- Name tag:
unlockedv2_<statename>-igw - Click Create internet gateway
- Click Actions > Attach to VPC
- Available VPCs: select VPC created above
- Click Attach internet gateway
- Click 'Create route tables'
- Name:
unlockedv2_<statename>-rtb-public - VPC: select VPC created above
- Click Create route table
- Select Routes tab of the route table just created
- Click Edit routes
- Add route:
- Destination:
0.0.0.0/0 - Target: Internet Gateway -
igw-<created>
- Destination:
- Add route:
- Destination:
0.0.0.0/16 - Target: Internet Gateway -
igw-<created>
- Destination:
- Click Save changes
- Select Subnet associations tab
- Click Edit subnet associations
- Select both public subnets
- Click Save associations
- Name:
unlockedv2_<statename>-nat-public1-us-west-2a - Subnet: select public1 subnet
- Connectivity type: Public
- Elastic IP allocation ID: Click allocate Elastic IP
- Additional Settings - Primary private IPv4 address:
10.0.14.231 - Click Create NAT gateway
- Name:
unlockedv2_<statename>-rtb-private1-us-west-2a - VPC: select VPC created above
- Click Create route table
- Name:
unlockedv2_<statename>-rtb-private2-us-west-2b - VPC: select VPC created above
- Click Create route table
- Name:
unlockedv2_<statename>-vpce-s3 - Type: AWS services
- Services:
com.amazonaws.us-west-2.s3 | Gateway - VPC: select VPC created above
- Route tables: select both private route tables
- Policy: Full Access
- Click Create endpoint
- Select Subnet associations tab of
unlockedv2_<statename>-rtb-private1-us-west-2a- Click Edit subnet associations
- Select private1 subnet
- Click Save associations
- Select Routes tab
- Click Edit routes
- Add route:
- Destination:
0.0.0.0/0 - Target: NAT Gateway -
nat-<created>
- Destination:
- Click Save changes
- Select Subnet associations tab of
unlockedv2_<statename>-rtb-private2-us-west-2b- Click Edit subnet associations
- Select private2 subnet
- Click Save associations
- Select Routes tab
- Click Edit routes
- Add route:
- Destination:
0.0.0.0/0 - Target: NAT Gateway -
nat-<created>
- Destination:
- Click Save changes
- From EC2 select Load Balancers from side nav
- Click Create load balancer
- Load Balancer type: Application Load Balancer
- Load Balancer Name:
unlockedv2-<statename> - Scheme: Internet-facing
- Load balancer IP address type: Dualstack
- VPC: select VPC created above
- Availability Zones: select both regions and both public subnets
- Security Groups: select default (should already be selected)
-
Listeners and routing: Click Create target group
- Target type: Instances
- Target group name:
unlockedv2-<statename> - Protocol: HTTP
- Port: 80
- IP address type: IPv4
- VPC: select VPC created above
- Protocol version: HTTP1
- Health check protocol: HTTP
- Health check path:
/api/healthcheck - Click Next and Create target group
- Note: You will need to add instance here later
- Click Create load balancer
- From the Load Balancer you just created Listeners and rules tab, click 1 rule link
- Place check in the checkbox of the Default rule, click Action > Edit rule
- Default action - Routing action: Redirect to URL
- Protocol: HTTPS
- Port: 443
- Status Code: 301 Permanently moved
- Click Save Changes
Steps:
- From Route 53 select Hosted Zones from side nav
- Select the hosted zone you are going to add a new domain name to (production:
unlockedlabs.org/ test:unlockedlabs.xyz) - Click Create Record
- Routing Policy: Simple Routing
- Configure Records: Click Define simple record
- Record Name:
<statename> - Record Type: A - Routes traffic to IPv4 address and some AWS resources
- Value/Route Traffic to: Alias to Application and Classic Load Balancer
- Choose Region:
<region> - Select load balancer created above
- Click Define simple record
- Repeat for
*.<statename>- Record Name:
*.<statename> - Repeat steps 7-11 above
- Record Name:
- Click Create records
Steps:
- From EC2 select Security Groups from side nav
- Click Create security group
- Security group name:
unlockedv2_<statename>_deployment - Description: allow SSM connection and load balancer traffic
- VPC: Select VPC created above
- Inbound rules:
- Rule: HTTP
- Add rule
- Type: HTTP
- Source: Custom (select default / sg for your VPC)
- Description: ELB traffic - healthcheck
- Rule: SSH (IPv4)
- Add rule
- Type: SSH
- Source: Anywhere-IPv4
- Description: SSM
- Rule: SSH (IPv6)
- Add rule
- Type: SSH
- Source: Anywhere-IPv6
- Description: SSM
- Rule: HTTP
- Click Create security group
Steps:
- From AWS Certificate Manager click Request
- Certificate type: Request a public certificate | click Next
- Fully qualified domain name:
*.<statename>.unlockedlabs.org - Click Add another name to this certificate and add:
<statename>.unlockedlabs.org - Validation method: DNS validation
- Key algorithm: RSA 2048
- Click Request
- From the Domains section in the Certificate you created, click Create records in Route 53
- Click Create records
-
From EC2 select Instances
-
Click Launch instances
-
Name:
production_unlockedv2_<statename>_node -
Application and OS images: Debian
-
Architecture: 64-bit (x86)
-
Instance Type: t3.large
-
Key pair: Click Create new key pair
- Key pair name:
unlockedv2_<statename>-keys - Key pair type: RSA
- Private key file format:
.pem - Click Create ... (will download key file, keep this safe)
- Key pair name:
-
From Network Settings section click Edit
-
VPC: Select VPC created above
-
Subnet: select
private1subnet -
Make sure Auto-assign public IP and IPv6 IP settings are set to Disable
-
Firewall: Select existing security group
-
Select the one created in Section 7 above (
unlockedv2_<statename>_deployment) -
Configure storage: 50 GiB gp3
-
From Advanced Details, IAM instance profile: select
ec2_ssm_profile -
Metadata response hop limit: 3
-
Upload file. Create a new file named
setup.shand paste this content:#!/bin/bash
mkdir s3 mkdir -p /tmp/ssm cd /tmp/ssm wget https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb sudo dpkg -i amazon-ssm-agent.deb sudo systemctl enable amazon-ssm-agent curl -sfL https://get.k3s.io | sh - wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb sudo dpkg -i mount-s3.deb cat <<'EOF' > /usr/bin/mounts3.sh #!/bin/bash IS_MOUNTED=$(ls /s3 | wc -l) if [ $IS_MOUNTED -eq 0 ]; then mount-s3 unlockedv2 /s3 echo 'Mounted S3 bucket' exit 0 fi echo 'Bucket already mounted' EOF
chmod u+x /usr/bin/mounts3.sh
cat < /etc/systemd/system/mounts3.service [Unit] Description=Mount S3 bucket for videos + thumbnails Wants=network-online.target After=network-online.target
[Install] WantedBy=multi-user.target
[Service] RemainAfterExit=yes Type=oneshot ExecStart=/usr/bin/mounts3.sh EOF
sudo systemctl enable mounts3 ```
-
Click Launch instance
-
Connect to the instance and do the following:
sudo su systemctl restart mounts3 systemctl status mounts3 ls s3 # You should see folders/files sudo apt update sudo apt install cron crontab -e # (Add the following cron job at the bottom) 02 * * * * /usr/local/bin/kubectl delete secret --ignore-not-found ecr-secret && /usr/local/bin/kubectl create secret docker-registry ecr-secret --docker-username=AWS --docker-email=none --docker-password=$(/usr/bin/aws ecr get-login-password --region us-west-2) --docker-server 239442854891.dkr.ecr.us-west-2.amazonaws.com >> /var/log/ecr-secret-refresh.log 2>&1 systemctl enable cron systemctl start cron systemctl status cron apt install postgresql-client
Steps:
- From Aurora and RDS select Databases from the side nav
- Click Create database
- Select Standard create
- Engine type: Postgresql
- Engine version: PostgreSQL 17.4-R1
- Templates: Production
- Deployment options: Multi-AZ DB instance deployment (2 instances)
- DB instance identifier:
unlockedv2-<statename>-encrypted-backup - Master username:
<addusernamehere>(remember this value) - Credentials Management: Self managed
- Master password:
<addpasswordhere>(remember this value) - DB instance class: Burstable classes
- Select db.t3.micro
- Storage type: General Purpose SSD (gp3)
- Allocated storage: 200
- Additional storage configuration: Uncheck Enable storage autoscaling
- Compute resource: Connect to an EC2 compute resource
- EC2 instance: Select the EC2 instance created above
- Network type: IPv4
- DB subnet group: Automatic setup
- Public access: No
- VPC security group (firewall): Create new
- Certificate authority (optional): rds-ca-rsa2048-g1
- Database port: 5432
- Database authentication: Password authentication
- Monitoring: Database Insights - Advanced
- Additional monitoring settings:
- Enable Enhanced monitoring
- OS metrics granularity: 60 seconds
- Monitoring role for OS metrics: rds-monitoring-role
- Log exports: PostgreSQL log
- Uncheck DevOps Guru
- Initial database name: (leave blank)
- DB parameter group: (default.postgres17)
- Enable automated backups: Yes
- Backup retention period: 7 days
- Backup window:
- Start time: 10:17 UTC
- Duration: 0.5 hours
- Copy tags to snapshots: Yes
- Enable replication in another AWS Region: Uncheck
- Enable encryption: Yes
- Maintenance window: No preference
- Enable deletion protection: Yes
- Click Create database
-
Log on to the EC2 instance created above
-
Run:
sudo su psql -h <hostname> -U <username> -d postgres
-
Verify that
psqlprompt appears -
To close connection:
\q
- From EC2 select Load Balancers from side nav
- Select the load balancer created above and click its link name
- From Listeners and rules tab, click Add listener
- Protocol: HTTPS
- Port: 443
- Routing action: Forward to target groups
- Target group:
unlockedv2-<statename> - Target group stickiness: keep off
- Security category: All security policies
- Policy name: ELBSecurityPolicy-TLS...
- Certificate source: from ACM
- Certificate (from ACM): select the certificate created above
- Mutual authentication (mTLS): Uncheck
- Click Add
- Click the listener just created
HTTPS:443(link) - Click Add Rule
- Name:
<statename>-www - Click Add condition, select Host header
- Host header value:
www.<statename>.unlockedlabs.org - Routing action: Redirect to URL
- Check 'Custom host, path, query'
- Redirect to URL:
- Protocol: HTTPS
- Port: 443
- Host:
<statename>.unlockedlabs.org - Path:
/#{path} - Query:
#{query} - Status code: 301
- Priority: 1
- Click Create
- As above, but for host header:
<statename>.unlockedlabs.org - Routing action: Forward to target groups
- Target group:
unlockedv2-<statename> - Priority: 2
- Click Create
- As above, for host header:
*.<statename>.unlockedlabs.org - Routing action: Forward to target groups
- Target group:
unlockedv2-<statename> - Priority: 3
- Click Create
- From EC2 select Target Groups from side nav
- Select the target group created above and click its link name in the table
- Click Register targets
- From available instances, select the instance created above
- Click Include as pending below
- Click Register pending targets