Triển Khai Laravel Lên AWS (Phần 4): ALB, CloudFront CDN & SSL Với ACM

· 5 min read

Phần 3, chúng ta đã kết nối Laravel với RDS, S3, và Redis. Giờ hãy đặt cửa trước production: ALB cho cân bằng tải và SSL, CloudFront cho CDN, và Route 53 cho DNS.

Chứng Chỉ SSL Với ACM

AWS Certificate Manager cung cấp chứng chỉ SSL miễn phí — nhưng phải dùng với dịch vụ AWS (ALB, CloudFront), không trực tiếp trên EC2.

Xin Chứng Chỉ Cho ALB (Regional)

aws acm request-certificate \
  --domain-name your-domain.com \
  --subject-alternative-names "*.your-domain.com" \
  --validation-method DNS \
  --region ap-northeast-1

Xin Chứng Chỉ Cho CloudFront (Bắt buộc us-east-1!)

CloudFront yêu cầu chứng chỉ ở us-east-1, bất kể app chạy ở đâu:

aws acm request-certificate \
  --domain-name your-domain.com \
  --subject-alternative-names "*.your-domain.com" \
  --validation-method DNS \
  --region us-east-1

ACM sẽ cho bạn CNAME record để thêm vào DNS. Sau đó tự động xác thực trong vài phút.

Application Load Balancer (ALB)

Tạo Target Group

aws elbv2 create-target-group \
  --name laravel-tg \
  --protocol HTTP \
  --port 80 \
  --vpc-id vpc-xxxx \
  --target-type instance \
  --health-check-path "/up" \
  --health-check-interval-seconds 30 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3 \
  --matcher HttpCode=200

Tạo ALB

aws elbv2 create-load-balancer \
  --name laravel-alb \
  --subnets subnet-public-a subnet-public-c \
  --security-groups sg-alb \
  --scheme internet-facing \
  --type application

Tạo Listeners

HTTPS listener (port 443):

aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:... \
  --protocol HTTPS \
  --port 443 \
  --certificates CertificateArn=arn:aws:acm:ap-northeast-1:xxxx:certificate/xxxx \
  --default-actions Type=forward,TargetGroupArn=arn:... \
  --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06

HTTP listener (port 80) — redirect sang HTTPS:

aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:... \
  --protocol HTTP \
  --port 80 \
  --default-actions Type=redirect,RedirectConfig='{Protocol=HTTPS,Port=443,StatusCode=HTTP_301}'

Cách ALB + EC2 Hoạt Động

Client → HTTPS :443 → ALB (SSL termination) → HTTP :80 → EC2 (Nginx)

ALB xử lý SSL. Traffic giữa ALB và EC2 là HTTP thuần trong VPC (mạng riêng).

Laravel: Trust ALB Proxy

Vì ALB terminate SSL và forward HTTP, Laravel cần biết protocol gốc là HTTPS:

// bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(
        at: '*',
        headers: Request::HEADER_X_FORWARDED_FOR |
                 Request::HEADER_X_FORWARDED_HOST |
                 Request::HEADER_X_FORWARDED_PORT |
                 Request::HEADER_X_FORWARDED_PROTO |
                 Request::HEADER_X_FORWARDED_AWS_ELB,
    );
})

Không có config này, url(), asset(), và redirect() sẽ tạo URL http:// thay vì https://.

Route 53 — DNS

aws route53 create-hosted-zone \
  --name your-domain.com \
  --caller-reference $(date +%s)

Cập nhật nameservers của domain registrar trỏ về Route 53 NS records.

Trỏ Domain Về ALB

aws route53 change-resource-record-sets \
  --hosted-zone-id ZXXXXX \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "your-domain.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z14GRHDCWA56QT",
          "DNSName": "laravel-alb-xxxx.ap-northeast-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'

CloudFront CDN

CloudFront cache assets tĩnh (CSS, JS, ảnh) ở edge locations toàn cầu, giảm latency cho người dùng xa region AWS.

Tạo Distribution Qua Console

  1. Vào CloudFront → Create distribution
  2. Origin: ALB domain, Protocol HTTPS only
  3. Default cache behavior:
    • Viewer protocol: Redirect HTTP to HTTPS
    • Cache policy: CachingDisabled (cho nội dung động)
  4. Thêm cache behavior cho assets tĩnh:
    • Path pattern: /build/*
    • Cache policy: CachingOptimized (TTL dài)
  5. Settings:
    • Alternate domain: your-domain.com
    • SSL certificate: Chọn ACM cert ở us-east-1

Chiến Lược Cache

Path Cache Tại sao
/build/* Cache 1 năm Vite hash filenames — immutable
/img/* Cache 1 ngày Ảnh tĩnh
* (mặc định) Không cache Response PHP động

Cập Nhật Route 53 Trỏ Về CloudFront

Giờ domain trỏ đến CloudFront thay vì ALB trực tiếp:

aws route53 change-resource-record-sets \
  --hosted-zone-id ZXXXXX \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "your-domain.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "DNSName": "dxxxxx.cloudfront.net",
          "EvaluateTargetHealth": false
        }
      }
    }]
  }'

Luồng Traffic Hoàn Chỉnh

User → CloudFront Edge → Cache HIT  → Response (nhanh!)
                        → Cache MISS → ALB → EC2 → Response

CloudFront còn cung cấp bảo vệ DDoS (AWS Shield Standard miễn phí).

Kiến Trúc Cập Nhật

            Route 53
               │
               ▼
        CloudFront (CDN)
        ├── /build/*  → Cached (1 năm)
        └── /*        → Pass-through
               │
               ▼
        ALB (HTTPS → HTTP)
        ├── SSL termination (ACM cert)
        └── Health check: /up
               │
               ▼
        EC2 (Nginx + PHP-FPM)
        ├── → RDS MySQL
        ├── → ElastiCache Redis
        └── → S3

Tiếp Theo

Phần 5 (cuối cùng), chúng ta sẽ tự động hóa mọi thứ với GitHub ActionsLaravel Envoy cho zero-downtime deployments, bao gồm cache invalidation, queue restart, và rollback tự động.


Điều hướng Series:

Bình luận