SSL رایگان روی nginx با certbot و ریدایرکت به HTTPS

گواهی SSL باعث می‌شود سایت با HTTPS باز شود؛ برای سئو، امنیت و اعتماد کاربران ضروری است. Let's Encrypt گواهی رایگان با اعتبار ۹۰ روز می‌دهد و certbot آن را خودکار تمدید می‌کند.

وب‌سرور و SSLمقدماتی10 دقیقه

۱پیش‌نیازها

دامنه باید با رکورد A (و AAAA اگر IPv6 دارید) به IP سرور اشاره کند، پورت‌های ۸۰ و ۴۴۳ باز باشند و server block سایت با server_name درست از قبل وجود داشته باشد.

bash
dig +short example.com
dig +short www.example.com
sudo ufw allow 'Nginx Full'
sudo nginx -t

۲نصب certbot

روی اوبونتو از بستهٔ apt یا snap می‌توانید نصب کنید. روش snap همیشه نسخهٔ جدیدتری دارد.

bash
sudo apt update
sudo apt install -y certbot python3-certbot-nginx

۳دریافت گواهی و تنظیم خودکار nginx

certbot گواهی می‌گیرد، بلوک 443 را به کانفیگ اضافه می‌کند و در صورت تأیید شما ریدایرکت http به https را فعال می‌کند.

bash
sudo certbot --nginx -d example.com -d www.example.com

در پرسش ریدایرکت گزینهٔ 2 (Redirect) را انتخاب کنید تا همهٔ ترافیک HTTP به HTTPS برود.

۴کانفیگ نهایی (نمونهٔ آنچه certbot می‌سازد)

بعد از اجرا، فایل سایت شبیه این می‌شود. اگر می‌خواهید دستی بنویسید، همین ساختار را استفاده کنید. www هم به دامنهٔ اصلی هدایت می‌شود.

nginx
# HTTP -> HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

# www -> بدون www (HTTPS)
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

# سایت اصلی
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

در nginx نسخهٔ کمتر از ۱.۲۵.۱ به‌جای «http2 on;» باید در خط listen بنویسید: listen 443 ssl http2;

۵افزودن HSTS (اختیاری ولی توصیه‌شده)

HSTS به مرورگر می‌گوید همیشه از HTTPS استفاده کند. ابتدا با مقدار کم شروع کنید و بعد از اطمینان، مقدار را به یک سال افزایش دهید.

nginx
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

روی همهٔ زیردامنه‌ها باید HTTPS کار کند وگرنه includeSubDomains باعث از دسترس خارج شدن آن‌ها می‌شود.

۶بررسی تمدید خودکار

certbot یک تایمر systemd می‌سازد که دو بار در روز بررسی می‌کند. با شبیه‌سازی مطمئن شوید تمدید کار می‌کند.

bash
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
sudo certbot certificates

۷reload خودکار nginx بعد از تمدید

افزونهٔ nginx به‌صورت خودکار reload می‌کند؛ اگر از حالت certonly استفاده کرده‌اید یک hook اضافه کنید.

bash
sudo certbot renew --deploy-hook "systemctl reload nginx"

۸تست نهایی

با curl و openssl مطمئن شوید HTTPS درست کار می‌کند و تاریخ انقضا را ببینید.

bash
curl -I https://example.com
curl -I http://example.com   # باید 301 بدهد
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

پرسش‌های پرتکرار دربارهٔ SSL رایگان روی nginx با certbot و ریدایرکت به HTTPS

certbot خطای «Timeout during connect» می‌دهد، چرا؟

Let's Encrypt باید بتواند از اینترنت به پورت ۸۰ سرور برسد. DNS دامنه، فایروال (ufw و فایروال پنل ارائه‌دهنده) و اینکه nginx روی ۸۰ در حال اجراست را بررسی کنید.

آیا می‌شود یک گواهی برای چند دامنه گرفت؟

بله؛ با چند -d پشت‌سرهم. برای همهٔ زیردامنه‌ها (wildcard) باید از اعتبارسنجی DNS استفاده کنید (certbot --manual --preferred-challenges dns یا افزونهٔ DNS ارائه‌دهنده).

گواهی چند روز اعتبار دارد و تمدید چه زمانی انجام می‌شود؟

هر گواهی ۹۰ روز اعتبار دارد و certbot از ۳۰ روز مانده به انقضا شروع به تمدید می‌کند.