Deploy Laravel to AWS via Console (Part 1): Architecture — VPC, Subnets & Security Groups
In Part 0, you created your AWS account, secured root, and set up an IAM user. Now let's build the network foundation for the entire infrastructure.
Every action in this post is performed in the AWS Console — no terminal needed.
What We're Building
After all 5 parts, you'll have:
| Component | AWS Service | Purpose |
|---|---|---|
| Network | VPC + Subnets | Isolated network with public/private zones |
| Compute | EC2 (Amazon Linux 2023) | PHP-FPM + Nginx web server |
| Database | RDS (MySQL 8.0) | Managed database in private subnet |
| Storage | S3 | File uploads, backups, assets |
| Load Balancer | ALB | Traffic distribution, SSL termination |
| CDN | CloudFront | Global static asset caching |
| SSL | ACM | Free SSL certificates |
| DNS | Route 53 | Domain management |
| Deploy | GitHub Actions + Envoy | Zero-downtime deployment |
Architecture Overview
┌───────────────────────────────────────┐
│ Route 53 (DNS) │
└──────────────────┬────────────────────┘
│
┌──────────────────┴────────────────────┐
│ CloudFront (CDN) │
└──────────────────┬────────────────────┘
│
┌──────────────────┴────────────────────┐
│ ALB (Application Load Balancer) │
│ SSL termination (ACM Certificate) │
└───┬──────────────────────────────┬────┘
│ VPC 10.0.0.0/16 │
┌───────────┴───────────┐ ┌─────────────┴──────────┐
│ Public Subnet A │ │ Public Subnet C │
│ 10.0.1.0/24 │ │ 10.0.2.0/24 │
│ AZ: ap-northeast-1a │ │ AZ: ap-northeast-1c │
│ ┌─────────────────┐ │ │ ┌─────────────────┐ │
│ │ EC2 Instance │ │ │ │ (scale later) │ │
│ │ Nginx+PHP-FPM │ │ │ │ │ │
│ └─────────────────┘ │ │ └─────────────────┘ │
└───────────────────────┘ └────────────────────────┘
┌───────────────────────┐ ┌────────────────────────┐
│ Private Subnet A │ │ Private Subnet C │
│ 10.0.11.0/24 │ │ 10.0.12.0/24 │
│ ┌─────────────────┐ │ │ │
│ │ RDS MySQL 8.0 │ │ │ (RDS Standby - │
│ │ Primary │ │ │ Multi-AZ replica) │
│ └─────────────────┘ │ │ │
└───────────────────────┘ └────────────────────────┘
Step 1: Create VPC
1a. Open VPC Console
- Search bar → type "VPC" → click VPC
- Left menu → Your VPCs
- Click "Create VPC"
1b. Select "VPC and more"
Choose the "VPC and more" tab — creates VPC with subnets, route tables, and IGW in one step.
1c. Fill In Details
| Setting | Value |
|---|---|
| Name tag auto-generation | laravel-production |
| IPv4 CIDR block | 10.0.0.0/16 |
| IPv6 CIDR block | No IPv6 CIDR block |
| Tenancy | Default |
| Number of Availability Zones | 2 |
| Number of public subnets | 2 |
| Number of private subnets | 2 |
| NAT gateways | None |
| VPC endpoints | S3 Gateway |
1d. Review Preview & Create
The right panel shows a visual network diagram. Verify it matches the architecture above, then click "Create VPC".
1e. Enable Auto-assign Public IP
- VPC → Subnets → click public subnet 1
- Actions → Edit subnet settings
- Check "Enable auto-assign public IPv4 address" → Save
- Repeat for public subnet 2
Step 2: Verify Internet Gateway & Route Tables
Public Route Table
- VPC → Route tables → click the public route table
- Routes tab should have:
| Destination | Target |
|---|---|
10.0.0.0/16 |
local |
0.0.0.0/0 |
igw-xxxx |
Private Route Table
Only has 10.0.0.0/16 → local. No internet route — by design.
Step 3: Create Security Groups
3a. ALB Security Group
- VPC → Security groups → Create security group
| Setting | Value |
|---|---|
| Name | laravel-alb-sg |
| Description | ALB - Allow HTTP/HTTPS from internet |
| VPC | laravel-production-vpc |
Inbound rules: HTTP (80) from 0.0.0.0/0, HTTPS (443) from 0.0.0.0/0
3b. EC2 Security Group
| Setting | Value |
|---|---|
| Name | laravel-ec2-sg |
| VPC | laravel-production-vpc |
Inbound rules: HTTP (80) from laravel-alb-sg, SSH (22) from My IP
3c. RDS Security Group
| Setting | Value |
|---|---|
| Name | laravel-rds-sg |
| VPC | laravel-production-vpc |
Inbound rules: MYSQL/Aurora (3306) from laravel-ec2-sg
3d. ElastiCache Security Group
| Setting | Value |
|---|---|
| Name | laravel-redis-sg |
| VPC | laravel-production-vpc |
Inbound rules: Custom TCP (6379) from laravel-ec2-sg
Step 4: Create IAM Role for EC2
4a. Create Policy
- IAM → Policies → Create policy → JSON tab:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::your-laravel-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::your-laravel-bucket"
}
]
}
Policy name: laravel-s3-access
4b. Create Role
- IAM → Roles → Create role
- Trusted entity: AWS service → EC2
- Attach
laravel-s3-accesspolicy - Role name:
laravel-ec2-role
Step 5: Create SSH Key Pair
- EC2 → Key Pairs → Create key pair
| Setting | Value |
|---|---|
| Name | laravel-production |
| Type | RSA |
| Format | .pem |
The .pem file downloads automatically. Move it:
mv ~/Downloads/laravel-production.pem ~/.ssh/
chmod 400 ~/.ssh/laravel-production.pem
Cost Estimate
| Service | Spec | Monthly (Tokyo) |
|---|---|---|
| EC2 | t3.small | ~$19 |
| RDS | db.t3.micro | ~$16 |
| ALB | Fixed + traffic | ~$18 |
| S3 | 10GB | ~$0.25 |
| CloudFront | 50GB transfer | ~$4 |
| Route 53 | 1 zone | $0.50 |
| ACM | SSL cert | Free |
| Total | ~$58/month |
Series Navigation:
- ← Part 0: Prerequisites
- Part 1: Architecture & VPC (You are here)
- Part 2: EC2 & Amazon Linux 2023 →
- Part 3: RDS, S3 & ElastiCache →
- Part 4: ALB, CloudFront & SSL →
- Part 5: CI/CD & Zero-Downtime Deploy →