Việc duy trì chứng chỉ SSL đồng bộ trên hệ thống máy chủ phân tán thường gây ra nhiều phiền toái: quên cập nhật, lỗi cấu hình, hoặc thậm chí downtime do hết hạn. Giải pháp kết hợp acme.sh và Rsync dưới đây sẽ giúp bạn tự động hóa toàn bộ quy trình — từ cấp phát, gia hạn đến đồng bộ và khởi động lại dịch vụ.
Nguyên lý hoạt động
- acme.sh: Tự động yêu cầu và gia hạn chứng chỉ thông qua giao thức ACME (Let’s Encrypt, ZeroSSL...).
- Rsync: Đồng bộ tập tin chứng chỉ mới đến các máy chủ đích một cách hiệu quả.
- Cron + Hook: Kích hoạt đồng bộ ngay sau khi chứng chỉ được làm mới.
- SSH key: Đảm bảo kết nối an toàn và không cần mật khẩu giữa các máy chủ.
Chuẩn bị môi trường
Đảm bảo tất cả máy chủ đều cài đặt:
# Ubuntu/Debian
sudo apt update && sudo apt install -y rsync openssl
# CentOS/RHEL
sudo yum install -y rsync openssl
Thiết lập SSH key để đăng nhập không cần mật khẩu từ máy chủ chính sang các máy chủ đích:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
ssh-copy-id deploy@server-web-01
ssh-copy-id deploy@server-web-02
Cài đặt và cấu hình acme.sh
Trên máy chủ trung tâm (nơi cấp chứng chỉ):
curl https://get.acme.sh | sh -s email=your@email.com
source ~/.bashrc
Ví dụ cấp chứng chỉ cho tên miền myapp.dev bằng phương thức Webroot:
acme.sh --issue -d myapp.dev -w /var/www/html --renew-hook "/home/deploy/scripts/sync-cert.sh"
Script đồng bộ chứng chỉ
Tạo thư mục cấu hình:
mkdir -p ~/scripts/certs
Tạo file cấu hình ~/scripts/certs/config:
CERT_DOMAIN="myapp.dev"
CERT_PATH="$HOME/.acme.sh/$CERT_DOMAIN"
TARGETS=(
"deploy@server-web-01:/etc/ssl/myapp"
"deploy@server-web-02:/etc/ssl/myapp"
)
FILES=("fullchain.cer" "$CERT_DOMAIN.key")
SERVICE_CMD="sudo systemctl reload nginx"
Tạo script đồng bộ ~/scripts/sync-cert.sh:
#!/bin/bash
CONFIG="$HOME/scripts/certs/config"
[ ! -f "$CONFIG" ] && { echo "❌ Config not found"; exit 1; }
source "$CONFIG"
for target in "${TARGETS[@]}"; do
host=$(echo "$target" | cut -d: -f1)
path=$(echo "$target" | cut -d: -f2-)
ssh "$host" "mkdir -p $path" >/dev/null
for cert_file in "${FILES[@]}"; do
local_file="$CERT_PATH/$cert_file"
[ ! -f "$local_file" ] && { echo "❌ Missing $cert_file"; continue; }
rsync -az -e ssh "$local_file" "$host:$path/"
done
ssh "$host" "$SERVICE_CMD" >/dev/null && \
echo "✅ Synced and reloaded on $host" || \
echo "⚠️ Failed to reload service on $host"
done
Cấp quyền thực thi:
chmod +x ~/scripts/sync-cert.sh
Kiểm tra và tự động hóa
Thử chạy thủ công để kiểm tra:
~/scripts/sync-cert.sh
acme.sh đã tự động thêm hook vào cron, nhưng bạn có thể kiểm tra lại:
crontab -l | grep acme.sh
Giám sát và cảnh báo
Tạo script kiểm tra thời hạn chứng chỉ ~/scripts/check-expiry.sh:
#!/bin/bash
CERT_FILE="$HOME/.acme.sh/myapp.dev/fullchain.cer"
[ ! -f "$CERT_FILE" ] && exit 1
DAYS_LEFT=$(openssl x509 -checkend $((30*86400)) -noout -in "$CERT_FILE" 2>&1 | grep -c "not after")
if [ "$DAYS_LEFT" -eq 0 ]; then
echo "🚨 Certificate expires in less than 30 days!"
# Gửi cảnh báo qua mail, Slack, Telegram...
fi
Lập lịch kiểm tra hàng ngày:
crontab -e
# Thêm dòng:
0 8 * * * /home/deploy/scripts/check-expiry.sh
Xử lý tình huống nâng cao
- SSH cổng khác: Thêm cổng vào định dạng
user@host:port:pathvà chỉnh sửa script dùngssh -p PORT. - Qua jump server: Dùng tùy chọn
-e "ssh -J jump-user@jump-host"trong lệnh rsync. - Nhiều domain: Viết vòng lặp đọc danh sách domain từ file hoặc dùng mảng cấu hình riêng.
Gỡ lỗi thường gặp
- ❌ Không tìm thấy chứng chỉ: Kiểm tra đường dẫn và tên domain trong cấu hình.
- ❌ Không reload được service: Cấp quyền sudo không cần mật khẩu cho user deploy:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx - ❌ Gia hạn thất bại: Xem log tại
~/.acme.sh/acme.sh.log, kiểm tra quyền truy cập webroot hoặc DNS.