Deploy Laravel to AWS via Console (Part 1): Architecture — VPC, Subnets & Security Groups

· 4 min read

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

  1. Search bar → type "VPC" → click VPC
  2. Left menu → Your VPCs
  3. 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

  1. VPC → Subnets → click public subnet 1
  2. Actions → Edit subnet settings
  3. Check "Enable auto-assign public IPv4 address"Save
  4. Repeat for public subnet 2

Step 2: Verify Internet Gateway & Route Tables

Public Route Table

  1. VPC → Route tables → click the public route table
  2. 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

  1. 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

  1. 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

  1. IAM → Roles → Create role
  2. Trusted entity: AWS serviceEC2
  3. Attach laravel-s3-access policy
  4. Role name: laravel-ec2-role

Step 5: Create SSH Key Pair

  1. 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:

Comments