Deploy Bludit + HTTPS trên EC2 free tier
Reading time: 6 minutes
Hướng dẫn từ EC2 trống tới một website Bludit chạy HTTPS thật, hoàn toàn trong giới hạn free tier của AWS. Toàn bộ bước dưới đây đã chạy thật để dựng chính trang này.
Bước 1: Khởi tạo EC2
Launch instance loại t3.micro (không phải t2.micro — t2.micro không được đánh dấu Free tier eligible ở một số tài khoản mới), chạy Amazon Linux 2023, chọn region gần nhất. Tạo key pair riêng, tải file .pem về máy.
Mở Security Group cho 2 port: 22 (SSH tạm thời) và 80 (HTTP).
Bước 2: Cài nginx và PHP-FPM
sudo dnf install -y nginx php-fpm php-cli php-json php-gd php-mbstring php-xml
sudo systemctl enable --now nginx
sudo systemctl enable --now php-fpm
Bước 3: Tải và cài Bludit
cd /usr/share/nginx/html
sudo curl -L -o bludit.zip https://github.com/bludit/bludit/archive/refs/heads/master.zip
sudo unzip bludit.zip
sudo cp -r bludit-master/* .
sudo rm -rf bludit-master bludit.zip
sudo chown -R nginx:nginx /usr/share/nginx/html
Bludit từ nhánh master đi kèm sẵn tài khoản demo admin/admin — đổi mật khẩu ngay sau lần đăng nhập đầu tiên.
Bước 4: Cấu hình nginx route qua PHP
Thêm vào block server trong /etc/nginx/nginx.conf:
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Kiểm tra cú pháp trước khi reload, luôn luôn:
sudo nginx -t
sudo systemctl reload nginx
Nếu gặp trang admin chỉ hiện dòng "Session initialization failed" — nguyên nhân gần như chắc chắn là PHP-FPM chạy dưới user nginx nhưng thư mục session PHP mặc định (/var/lib/php/session) chỉ cho group apache ghi. Sửa quyền:
sudo chgrp nginx /var/lib/php/session
sudo chmod 770 /var/lib/php/session
sudo systemctl restart php-fpm
Bước 5: Gắn Elastic IP
Gắn Elastic IP trước khi làm bất cứ điều gì khác — để IP không đổi mỗi lần restart instance. Nhưng việc gắn IP mới sẽ lập tức làm vỡ giao diện, vì Bludit lưu cứng IP cũ làm base URL trong site.php. Sửa bằng một dòng sed:
sudo sed -i 's/IP_CU/IP_MOI/g' /usr/share/nginx/html/bl-content/databases/site.php
Bước 6: Đăng ký domain miễn phí qua DuckDNS
Đăng ký subdomain miễn phí tại duckdns.org, trỏ về Elastic IP vừa gắn. Sau khi domain hoạt động, cập nhật server_name trong nginx.conf từ _; thành domain thật — bước này bắt buộc phải làm trước khi chạy Certbot.
Bước 7: HTTPS thật bằng Let's Encrypt
Amazon Linux 2023 không có sẵn gói Certbot trong repo — cài qua Python venv:
sudo dnf install -y python3-pip
sudo python3 -m venv /opt/certbot
sudo /opt/certbot/bin/pip install certbot certbot-nginx
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
sudo certbot --nginx -d your-domain.duckdns.org
Nếu Certbot báo "Could not automatically find a matching server block" — quay lại bước 6, server_name trong nginx.conf vẫn còn là _; (một giá trị thật, không phải chỗ để trống).
Sau khi bật HTTPS thành công, giao diện vỡ thêm lần nữa vì cùng lý do ở bước 5 — base URL trong site.php vẫn lưu http:// thay vì https://. Sed lại một lần nữa, lần này đổi giao thức.
Bài học rút ra
Bất cứ thứ gì lưu cứng base URL của site sẽ "cắn" bạn hai lần: một lần khi đổi IP, một lần khi đổi giao thức. Sau khi qua đủ 2 lần đó, mọi thứ ổn định và không cần đụng tới nữa.