This section covers Steps 2–7 of the deployment: creating the VPC, subnets, internet gateway, NAT gateway, route tables, security groups, and IAM roles.
Console: VPC Dashboard → Your VPCs → Create VPC
| Field | Value |
|---|---|
| Resources to create | VPC and more |
| Name tag | smartinvoice-vpc |
| IPv4 CIDR | 10.0.0.0/16 |
| Tenancy | Default |

Console: VPC → Subnets → Create subnet (click Add new subnet to create all at once)
| # | Name | AZ | CIDR |
|---|---|---|---|
| 1 | smartinvoice-public-1a | ap-southeast-1a | 10.0.1.0/24 |
| 2 | smartinvoice-public-1b | ap-southeast-1b | 10.0.2.0/24 |
| 3 | smartinvoice-private-1a | ap-southeast-1a | 10.0.3.0/24 |
| 4 | smartinvoice-private-1b | ap-southeast-1b | 10.0.4.0/24 |
For each public subnet: Actions → Edit subnet settings → Enable auto-assign public IPv4
Console: VPC → Internet Gateways → Create internet gateway
| Name tag | smartinvoice-igw |
|---|
→ Actions → Attach to VPC → smartinvoice-vpc → Attach ✅
NAT Gateway allows Private Subnets to access the Internet (outbound). Cost ~$32/month.
Console: VPC → NAT Gateways → Create NAT gateway
| Field | Value |
|---|---|
| Name | smartinvoice-nat-gw |
| Subnet | smartinvoice-public-1a (must be in a Public Subnet!) |
| Connectivity | Public |
| Elastic IP | Click Allocate Elastic IP |
Wait for status Available (2–3 minutes).
Console: VPC → Route Tables → Create route table
| Name | VPC |
|---|---|
smartinvoice-public-rt | smartinvoice-vpc |
Routes → Edit → Add: 0.0.0.0/0 → Target: smartinvoice-igw
Subnet associations: tick smartinvoice-public-1a + smartinvoice-public-1b
| Name | VPC |
|---|---|
smartinvoice-private-rt | smartinvoice-vpc |
Routes → Add: 0.0.0.0/0 → Target: smartinvoice-nat-gw
Subnet associations: tick smartinvoice-private-1a + smartinvoice-private-1b
Console: VPC → Security Groups → Create security group (VPC: smartinvoice-vpc)
smartinvoice-alb-sg)| Inbound | Port | Source |
|---|---|---|
| HTTP | 80 | 0.0.0.0/0 |
| HTTPS | 443 | 0.0.0.0/0 |

smartinvoice-backend-sg)| Inbound | Port | Source |
|---|---|---|
| HTTP | 80 | smartinvoice-alb-sg |
| Custom TCP | 8080 | smartinvoice-alb-sg |

smartinvoice-rds-sg)| Inbound | Port | Source |
|---|---|---|
| PostgreSQL | 5432 | smartinvoice-backend-sg |
| PostgreSQL | 5432 | smartinvoice-ocr-sg |
smartinvoice-ocr-sg)| Inbound | Port | Source |
|---|---|---|
| Custom TCP | 5000 | smartinvoice-backend-sg (Direct internal) |
All SGs: Outbound = All traffic →
0.0.0.0/0
You need to create 4 IAM Roles. The general procedure for each:
General Steps:
AWS service. Select the corresponding service. Click Next.Grants EC2 instances in the Backend the right to access other AWS resources.
AmazonS3FullAccessAmazonSQSFullAccessAmazonCognitoPowerUserAmazonSSMReadOnlyAccessAmazonEC2ContainerRegistryReadOnlyCloudWatchLogsFullAccess
Allows Elastic Beanstalk to call AWS services on your behalf.
AWSElasticBeanstalkEnhancedHealthAWSElasticBeanstalkManagedUpdatesCustomerRolePolicy
Allows ECS Fargate to pull images from ECR and write logs to CloudWatch.
AmazonECSTaskExecutionRolePolicyCloudWatchLogsFullAccessGrants direct permissions to the OCR application running in the container.
AmazonS3FullAccessAmazonSQSFullAccessAmazonSSMReadOnlyAccess