Triển Khai Laravel Lên AWS (Phần 2): EC2 với Amazon Linux 2023 — Nginx + PHP-FPM Từ Đầu
·
6 min read
Ở Phần 1, chúng ta đã thiết lập VPC, subnets, và security groups. Giờ hãy khởi chạy server thực và chạy Laravel trên đó.
Khởi Chạy EC2 Instance
Qua AWS Console
- Vào EC2 → Launch Instance
- Cấu hình:
| Thiết lập | Giá trị |
|---|---|
| Name | laravel-web-01 |
| AMI | Amazon Linux 2023 |
| Instance type | t3.small (2 vCPU, 2GB RAM) |
| Key pair | laravel-production |
| VPC | laravel-production |
| Subnet | laravel-public-a |
| Auto-assign public IP | Enable |
| Security group | laravel-ec2-sg |
| IAM instance profile | laravel-ec2-profile |
| Storage | 20 GB gp3 |
Qua AWS CLI
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.small \
--key-name laravel-production \
--subnet-id subnet-public-a \
--security-group-ids sg-ec2 \
--iam-instance-profile Name=laravel-ec2-profile \
--block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs":{"VolumeSize":20,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=laravel-web-01}]' \
--associate-public-ip-address
SSH Vào Server
ssh -i laravel-production.pem ec2-user@<PUBLIC_IP>
Mẹo: Thêm vào
~/.ssh/config:Host laravel-prod HostName <PUBLIC_IP> User ec2-user IdentityFile ~/.ssh/laravel-production.pemRồi chỉ cần:
ssh laravel-prod
Thiết Lập Hệ Thống
# Cập nhật hệ thống
sudo dnf update -y
# Đặt múi giờ
sudo timedatectl set-timezone Asia/Tokyo
# Cài công cụ thiết yếu
sudo dnf install -y git vim htop unzip tar wget jq
Cài Đặt Nginx
sudo dnf install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
Cài Đặt PHP 8.4
# Cài PHP 8.4 và các extensions cần thiết
sudo dnf install -y \
php8.4-fpm \
php8.4-cli \
php8.4-common \
php8.4-mbstring \
php8.4-xml \
php8.4-curl \
php8.4-zip \
php8.4-gd \
php8.4-intl \
php8.4-bcmath \
php8.4-mysqlnd \
php8.4-pdo \
php8.4-opcache \
php8.4-redis \
php8.4-sodium
Lưu ý: Nếu PHP 8.4 không có trong repo mặc định, dùng Remi repository:
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm sudo dnf module reset php -y sudo dnf module enable php:remi-8.4 -y sudo dnf install -y php-fpm php-cli php-common php-mbstring php-xml \ php-curl php-zip php-gd php-intl php-bcmath php-mysqlnd php-pdo \ php-opcache php-redis php-sodium
Cấu Hình PHP-FPM
sudo vim /etc/php-fpm.d/www.conf
; Chạy với user nginx
user = nginx
group = nginx
; Dùng Unix socket (nhanh hơn TCP)
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; Quản lý process
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500
Cấu Hình php.ini Cho Production
; Cài đặt production
memory_limit = 256M
upload_max_filesize = 50M
post_max_size = 50M
max_execution_time = 60
; Bảo mật
expose_php = Off
display_errors = Off
log_errors = On
; OPcache (quan trọng cho hiệu năng)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 0 ; Tắt trong production!
Quan trọng:
opcache.validate_timestamps = 0nghĩa là PHP không kiểm tra file có thay đổi không. Tăng hiệu năng rất lớn nhưng cần restart PHP-FPM sau mỗi lần deploy. Script deploy ở Phần 5 tự động xử lý việc này.
sudo systemctl enable php-fpm
sudo systemctl start php-fpm
Cài Đặt Composer & Node.js
# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Node.js 20 LTS
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
Cấu Hình Nginx Cho Laravel
sudo vim /etc/nginx/conf.d/laravel.conf
server {
listen 80;
server_name your-domain.com;
root /var/www/laravel/current/public;
index index.php index.html;
charset utf-8;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml text/javascript image/svg+xml;
# File tĩnh — serve trực tiếp, cache lâu
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Cấu Trúc Thư Mục Zero-Downtime Deploy
sudo mkdir -p /var/www/laravel/{releases,shared}
sudo mkdir -p /var/www/laravel/shared/{storage,node_modules}
sudo mkdir -p /var/www/laravel/shared/storage/{app,framework,logs}
sudo mkdir -p /var/www/laravel/shared/storage/framework/{cache,sessions,views}
sudo chown -R ec2-user:nginx /var/www/laravel
sudo chmod -R 775 /var/www/laravel/shared/storage
/var/www/laravel/
├── current → releases/20260327_120000/ (symlink đến bản mới nhất)
├── releases/
│ ├── 20260327_120000/ (release hiện tại)
│ └── 20260326_150000/ (release trước)
└── shared/
├── .env (persistent)
└── storage/ (persistent)
Deploy Thủ Công Lần Đầu
cd /var/www/laravel
RELEASE=$(date +%Y%m%d_%H%M%S)
git clone git@github.com:your/repo.git releases/$RELEASE
cd releases/$RELEASE
# Cài dependencies
composer install --no-dev --optimize-autoloader --no-interaction
# Tạo .env (chỉ lần đầu)
cp .env.example /var/www/laravel/shared/.env
vim /var/www/laravel/shared/.env
# Link shared resources
rm -rf storage
ln -s /var/www/laravel/shared/storage storage
ln -s /var/www/laravel/shared/.env .env
# Build frontend
npm ci && npm run build && rm -rf node_modules
# Tối ưu Laravel
php artisan key:generate
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Kích hoạt release
cd /var/www/laravel
ln -sfn releases/$RELEASE current
sudo systemctl reload php-fpm
Cài Đặt Supervisor (Cho Queue)
sudo dnf install -y supervisor
sudo systemctl enable supervisord
sudo systemctl start supervisord
sudo vim /etc/supervisord.d/laravel-worker.ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/laravel/current/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
user=ec2-user
numprocs=2
redirect_stderr=true
stdout_logfile=/var/log/supervisor/laravel-worker.log
Cài Đặt Laravel Scheduler (Cron)
crontab -e
* * * * * cd /var/www/laravel/current && php artisan schedule:run >> /dev/null 2>&1
Tiếp Theo
Ở Phần 3, chúng ta sẽ thiết lập RDS MySQL trong private subnet, tạo S3 bucket cho lưu trữ file, cấu hình Laravel kết nối với cả hai, và thêm ElastiCache (Redis).
Điều hướng Series:
- ← Phần 0: Chuẩn Bị
- ← Phần 1: Kiến Trúc & VPC
- Phần 2: EC2 & Amazon Linux 2023 (Bạn đang ở đây)
- Phần 3: RDS, S3 & ElastiCache →
- Phần 4: ALB, CloudFront & SSL →
- Phần 5: CI/CD & Zero-Downtime Deploy →