امنیت وب

نصب گواهی SSL رایگان با Certbot — فعال‌سازی HTTPS در ۱۰ دقیقه

نصب SSL رایگان با Certbot و فعال‌سازی HTTPS روی سرور لینوکس با گواهی Let's Encrypt

نصب SSL رایگان با Certbot امروز نه پول می‌خواهد، نه تماس با پشتیبانی و نه دانش عمیق رمزنگاری؛ با Certbot و Let's Encrypt در حدود ۱۰ دقیقه برای دامنه‌ی خود گواهی SSL معتبر می‌گیرید، قفل کنار نوار آدرس روشن می‌شود و تمدیدش هم برای همیشه به یک تایمر خودکار سپرده می‌شود. در این راهنما کل مسیر را قدم‌به‌قدم می‌رویم: نصب Certbot روی اوبونتو، دبیان و آلمالینوکس، صدور گواهی با پلاگین Nginx و Apache، روش webroot و wildcard، بکاپ فایل‌های گواهی، آزمون تمدید خودکار، ری‌دایرکت ۳۰۱ و جدول خطاهایی که معمولاً کار را نیمه‌تمام می‌گذارند. دستورها با Certbot 5.8 (سپتامبر ۲۰۲۶) روی اوبونتو ۲۴.۰۴ و آلمالینوکس ۹ بازبینی شده‌اند.

SSL/TLS دقیقاً چه کاری انجام می‌دهد؟

وقتی سایت روی HTTPS است، بین مرورگر بازدیدکننده و سرور شما یک کانال رمزنگاری‌شده با پروتکل TLS برقرار می‌شود — SSL نام نسل قدیمی همین پروتکل است که هنوز سر زبان‌ها مانده و اصطلاح «گواهی SSL» هم از همان‌جا آمده. این کانال هم‌زمان سه ضمانت می‌دهد: محرمانگی (هیچ‌کس در مسیر — نه اپراتور، نه وای‌فای کافه — محتوای ردوبدل‌شده را نمی‌خواند)، یکپارچگی (کسی نمی‌تواند وسط راه به صفحه‌ی شما اسکریپت یا تبلیغ تزریق کند) و احراز هویت (بازدیدکننده مطمئن است واقعاً با سرور شما حرف می‌زند، نه با یک واسطه‌ی جعلی).

اما ماجرا فقط امنیت نیست؛ فعال کردن HTTPS سه پیامد عملی و قابل‌اندازه‌گیری هم دارد:

  • اعتماد کاربر. مرورگرها صفحه‌های HTTP را با برچسب «Not Secure» نشان می‌دهند و روی فرم رمز عبورِ بدون HTTPS صریحاً هشدار می‌گذارند. برای فروشگاه یا هر سایتی که فرم ورود دارد، این هشدار یعنی خداحافظی با بخشی از بازدیدکننده‌ها پیش از اولین کلیک.
  • سیگنال رتبه‌بندی. گوگل از سال ۲۰۱۴ رسماً HTTPS را جزو سیگنال‌های رتبه‌بندی اعلام کرده است؛ وزنش بزرگ نیست، ولی بین دو نتیجه‌ی هم‌سطح به نفع نسخه‌ی امن تمام می‌شود.
  • HTTP/2 و قابلیت‌های مدرن. مرورگرها HTTP/2 را فقط روی اتصال TLS پیاده کرده‌اند؛ سایت HTTP عملاً از multiplexing و فشرده‌سازی هدر محروم می‌ماند. سرویس‌ورکر، PWA، اعلان وب و خیلی از APIهای دیگر هم فقط در بستر امن (secure context) کار می‌کنند.

چرا Let's Encrypt رایگان است — و چرا می‌شود به آن اعتماد کرد

Let's Encrypt یک مرجع صدور گواهی (CA) غیرانتفاعی است که از سال ۲۰۱۵ با پشتیبانی مالی سازمان‌هایی مثل موزیلا، سیسکو، کروم و بنیاد EFF کار می‌کند و امروز از نظر تعداد گواهی فعال، بزرگ‌ترین CA دنیاست. ریشه‌ی آن (ISRG Root X1) در همه‌ی مرورگرها و سیستم‌عامل‌های مطرح به‌صورت پیش‌فرض معتبر است؛ یعنی گواهی SSL آن از نظر رمزنگاری و اعتبار مرورگر هیچ فرقی با گواهی پولی ندارد و بازدیدکننده هم هیچ تفاوتی نمی‌بیند.

رایگان‌بودنش هم ترفند بازاریابی نیست؛ نتیجه‌ی حذف کامل نیروی انسانی از فرایند صدور است. همه‌چیز با پروتکل استاندارد ACME (مصوب RFC 8555) خودکار شده: کلاینت ACME — که محبوب‌ترینش همین Certbot ساخته‌ی EFF است — به‌جای شما به CA ثابت می‌کند که کنترل دامنه در دست شماست، از یکی از این دو راه:

  • چالش HTTP-01: کلاینت فایل کوچکی در مسیر /.well-known/acme-challenge/ سایت می‌گذارد و سرورهای Let's Encrypt آن را از روی پورت ۸۰ می‌خوانند. اگر فایل سر جایش بود، مالکیت ثابت شده است.
  • چالش DNS-01: کلاینت از شما می‌خواهد یک رکورد TXT با نام _acme-challenge بسازید؛ این تنها راه معتبر برای گواهی wildcard است.

نکته‌ی مهم برای سرورهای داخل ایران: Let's Encrypt هر چالش را از چند نقطه‌ی جغرافیایی جدا (multi-perspective validation) می‌خواند و از ۱۵ سپتامبر ۲۰۲۵ همه‌ی CAها به این کار موظف‌اند؛ پس پورت ۸۰ سرور — یا در DNS-01، سرور DNS دامنه — باید از خارج کشور هم قابل‌دسترس باشد، وگرنه صدور با خطای During secondary validation شکست می‌خورد.

و اما عمر ۹۰ روزه‌ی گواهی‌ها، برخلاف تصور اول، نقطه‌ضعف نیست؛ عمداً کوتاه انتخاب شده تا اگر کلید خصوصی سروری لو رفت، پنجره‌ی سوءاستفاده کوچک بماند و — مهم‌تر — همه به تمدید خودکار عادت کنند. وقتی تمدید را یک تایمر انجام می‌دهد، ۹۰ روز و ۹۰۰ روز هیچ فرقی با هم ندارند.

نصب Certbot روی سرور

فرض این راهنما یک سرور لینوکسی با دسترسی root و وب‌سرور Nginx است. اگر هنوز وب‌سرورتان بالا نیامده، اول راه‌اندازی وب‌سایت روی اوبونتو با Nginx را انجام دهید و برگردید؛ پلاگین Certbot دقیقاً روی همان کانفیگ سوار می‌شود. اگر هنوز با ترمینال سرور راحت نیستید، آموزش اتصال به سرور با SSH را پیش از شروع بخوانید؛ همه‌ی دستورهای این مقاله در همان ترمینال زده می‌شوند.

اوبونتو و دبیان — روش رسمی: snap

تیم Certbot نسخه‌ی snap را روش پیشنهادی نصب اعلام کرده، چون همیشه آخرین نسخه را می‌گیرید، پلاگین‌های nginx و apache داخلش هستند و تمدید خودکار از همان اول درست تنظیم می‌شود:

sudo apt update
sudo apt install snapd -y
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
certbot --version
# certbot 5.8.0

اگر قبلاً نسخه‌ی مخزن را نصب کرده‌اید، اول با sudo apt remove certbot حذفش کنید تا دو نسخه با هم تداخل نکنند.

نمودار مراحل صدور گواهی SSL رایگان از Let's Encrypt با چالش HTTP-01 پروتکل ACME روی پورت 80 بین سرور و مرجع صدور گواهی

مسیر جایگزین: apt

روی سرورهایی که snapd ندارند یا نمی‌خواهید اضافه‌اش کنید، بسته‌ی مخزن هم کاملاً کار می‌کند — فقط معمولاً چند نسخه عقب‌تر است. اوبونتو ۲۴.۰۴ در مخزن universe نسخه‌ی 2.9.0 را دارد و تا پایان عمر این نسخه‌ی اوبونتو همان می‌ماند:

sudo apt update
sudo apt install certbot python3-certbot-nginx -y
apt policy certbot
# certbot:
#   Installed: 2.9.0-1
#   Candidate: 2.9.0-1

آلمالینوکس و راکی — dnf و مخزن EPEL

در خانواده‌ی RHEL بسته‌ی Certbot داخل مخزن EPEL است، پس اول آن را فعال کنید. EPEL 9 در حال حاضر نسخه‌ی 3.1.0 را می‌دهد:

sudo dnf install epel-release -y
sudo dnf install certbot python3-certbot-nginx -y
certbot --version
# certbot 3.1.0

اگر وب‌سرورتان Apache است

همه‌چیز عین Nginx است، فقط نام پلاگین عوض می‌شود: در snap از قبل هست، در apt و dnf بسته‌ی python3-certbot-apache را نصب کنید و به‌جای --nginx بنویسید --apache؛ بلاک VirtualHost پورت ۴۴۳ را خودش می‌سازد:

sudo apt install python3-certbot-apache -y     # only for the apt route
sudo certbot --apache -d example.com -d www.example.com

صدور گواهی SSL با پلاگین Nginx

قبل از اجرای فرمان، دو پیش‌نیاز را چک کنید. اول این‌که رکورد A دامنه (و اگر www هم می‌خواهید، رکورد www) به IP همین سرور اشاره کند — با dig +short example.com مطمئن شوید؛ اگر با رکوردها راحت نیستید، آموزش رکوردهای DNS به زبان ساده را ببینید. دوم این‌که در کانفیگ Nginx یک بلاک server با server_name درست وجود داشته باشد، چون پلاگین از روی همین نام، بلاک مناسب را پیدا و ویرایش می‌کند.

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

در اولین اجرا یک آدرس ایمیل برای حساب ACME می‌پرسد (از نسخه‌ی ۳.۳ اختیاری است و با Enter خالی رد می‌شود) و تأیید توافق‌نامه را می‌خواهد؛ بعد چالش HTTP-01 را خودش پاس می‌کند و چند ثانیه بعد چیزی شبیه این می‌بینید:

Requesting a certificate for example.com and www.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-11-04.

Deploying certificate
Successfully deployed certificate for example.com to /etc/nginx/sites-enabled/example.com
Congratulations! You have successfully enabled HTTPS on https://example.com

پلاگین بعد از گرفتن گواهی، بلاک server شما را ویرایش می‌کند: گوش‌دادن روی پورت ۴۴۳ را اضافه می‌کند، مسیر گواهی و کلید خصوصی را می‌نشاند و تنظیمات امن TLS را include می‌کند — همه با کامنت «managed by Certbot»، تا همیشه معلوم باشد کدام خط‌ها دست او بوده:

server {
    server_name example.com www.example.com;
    root /var/www/example.com;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
💡 نکته: هر صدور موفق در سهمیه‌ی Let's Encrypt حساب می‌شود — برای مجموعه‌ی نام‌های دقیقاً یکسان فقط ۵ گواهی در هفته، و برای هر دامنه‌ی ثبت‌شده در مجموع ۵۰ گواهی در هفته. اگر می‌خواهید مسیر را آزمایش کنید یا با اسکریپت ور می‌روید، سوییچ --dry-run را اضافه کنید تا درخواست به سرور آزمایشی (staging) برود و سهمیه‌ی واقعی نسوزد.

روش webroot — وقتی نمی‌خواهید سرویس بایستد یا کانفیگ دست بخورد

روش standalone که در آموزش‌های قدیمی زیاد دیده می‌شود، خودش روی پورت ۸۰ گوش می‌دهد و مجبورید وب‌سرور را موقتاً خاموش کنید؛ روی سایت زنده منطقی نیست. روش webroot همان چالش HTTP-01 را از طریق وب‌سرورِ درحال‌کار پاس می‌کند: Certbot فایل چالش را داخل روت سایت می‌گذارد و Let's Encrypt آن را مثل هر فایل استاتیک دیگری می‌خواند — بدون یک ثانیه قطعی و بدون دست‌زدن به هیچ کانفیگی:

sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com

certonly یعنی «فقط گواهی را بگیر و به کانفیگ کاری نداشته باش»؛ در این حالت دو خط ssl_certificate و ssl_certificate_key را خودتان به بلاک server اضافه می‌کنید و با nginx -t && systemctl reload nginx اعمالش می‌کنید. مسیر webroot در پرونده‌ی تمدید ذخیره می‌شود، پس تمدیدهای بعدی هم به همین شکل خودکار و بی‌قطعی انجام می‌شوند. پیش از اجرا، با یک فایل آزمایشی مطمئن شوید Nginx واقعاً از همین روت سرو می‌کند:

sudo mkdir -p /var/www/example.com/.well-known/acme-challenge
echo ok | sudo tee /var/www/example.com/.well-known/acme-challenge/test
curl -s http://example.com/.well-known/acme-challenge/test
# ok

گواهی wildcard: فقط با چالش DNS-01

اگر ساب‌دامنه‌های زیاد یا نامشخصی دارید، گواهی wildcard مثل *.example.com همه را یک‌جا پوشش می‌دهد؛ ولی Let's Encrypt برای آن فقط چالش DNS-01 را می‌پذیرد، چون کنترل کل DNS دامنه باید ثابت شود:

sudo certbot certonly --manual --preferred-challenges dns \
     -d example.com -d "*.example.com"

Certbot یک مقدار متنی نشان می‌دهد که باید به‌عنوان رکورد TXT با نام _acme-challenge در پنل DNS ثبت کنید. قبل از زدن Enter مطمئن شوید رکورد منتشر شده است:

dig TXT _acme-challenge.example.com +short
# should print the exact value certbot asked for

نکته‌ی مهم برای کاربران ایرانی: اگر DNS دامنه روی سرویسی باشد که پلاگین API برای Certbot دارد (مثل certbot-dns-cloudflare)، ساخت رکورد و تمدید هر دو خودکار می‌شوند. اما بیشتر پنل‌های DNS ایرانی API و پلاگینی ندارند و همین روش دستی (--manual) تنها راه می‌ماند — که تمدید خودکار هم ندارد و هر دوره باید تکرارش کنید. جمع‌بندی عملی: تا مجبور نشده‌اید wildcard نگیرید؛ برای چند ساب‌دامنه‌ی مشخص، همه را با چند -d در یک گواهی عادی بگیرید — یک گواهی تا ۱۰۰ نام جا دارد.

فایل‌های گواهی کجا ذخیره می‌شوند و چطور از آن‌ها بکاپ بگیرم؟

هر چیزی که Certbot می‌سازد زیر /etc/letsencrypt است و فهرستش را از خودش بگیرید:

sudo certbot certificates
# Found the following certs:
#   Certificate Name: example.com
#     Serial Number: 4f3a9c1e0b7d2a8f6c5e4d3b2a1f0e9d8c7
#     Key Type: ECDSA
#     Domains: example.com www.example.com
#     Expiry Date: 2026-11-04 07:15:21+00:00 (VALID: 89 days)
#     Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
#     Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

سه پوشه مهم‌اند. live/example.com/ فقط لینک نمادین (symlink) است و همیشه به آخرین نسخه اشاره می‌کند؛ فایل‌های واقعی در archive/example.com/ با شماره‌ی نسخه (cert1.pem، cert2.pem، …) می‌نشینند و با هر تمدید یک شماره بالا می‌روند؛ و renewal/example.com.conf حافظه‌ی تمدید است — نوع چالش، مسیر webroot، پلاگین نصب و نوع کلید از همین فایل خوانده می‌شوند. به همین دلیل وب‌سرور را همیشه به مسیر live/ وصل کنید تا گواهی تازه بدون تغییر کانفیگ سرو شود. کلید پیش‌فرض از نسخه‌ی ۲.۰ به بعد ECDSA P-256 است؛ فقط برای کلاینت‌های خیلی قدیمی با --key-type rsa برگردید.

⚠️ هنگام انتقال به سرور جدید فقط پوشه‌ی live/ را کپی نکنید — لینک‌های نمادین به archive/ شکسته می‌رسند و Nginx با خطای «cannot load certificate» بالا نمی‌آید. کل /etc/letsencrypt را یک‌جا با tar ببرید، یا ساده‌تر روی سرور جدید گواهی تازه بگیرید. برای این‌که این پوشه در بکاپ‌های شبانه جا نماند، راهنمای بکاپ سرور لینوکس را ببینید.

تمدید خودکار SSL — گواهی ۹۰ روزه‌ای که هیچ‌وقت منقضی نمی‌شود

Certbot هنگام نصب یک تایمر systemd می‌سازد که روزی دو بار اجرا می‌شود و هر گواهی‌ای را که به آستانه‌ی تمدید رسیده، تمدید می‌کند. این آستانه از نسخه‌ی ۴.۰ «کمتر از یک‌سوم عمر باقی‌مانده» است (برای گواهی ۹۰ روزه همان ۳۰ روز) و از نسخه‌ی ۴.۱ اگر Let's Encrypt از طریق ARI بگوید زودتر تمدید کن — مثلاً وقتی گواهی باید باطل شود — زودتر انجام می‌شود. نسخه‌های apt (۲.۹) و EPEL (۳.۱) هنوز قانون ثابت ۳۰ روز را دارند. روی snap و بسته‌ی apt اوبونتو/دبیان این تایمر از همان اول فعال است؛ بسته‌ی EPEL فایل تایمر را می‌سازد ولی روشنش نمی‌کند و خودش هنگام نصب هشدار می‌دهد (Certbot auto renewal timer is not started by default) — روی آلمالینوکس و راکی حتماً یک بار enable --now بزنید:

systemctl list-timers | grep -i certbot
# snap.certbot.renew.timer   -> snap install
# certbot.timer              -> apt install (Ubuntu / Debian)
# certbot-renew.timer        -> dnf / EPEL install (AlmaLinux / Rocky)

sudo systemctl enable --now certbot-renew.timer   # AlmaLinux / Rocky only

بعد همین امروز — نه ۸۹ روز دیگر — کل مسیر تمدید را شبیه‌سازی کنید:

sudo certbot certificates      # list certs and expiry dates
sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)

اگر گواهی را با پلاگین nginx گرفته‌اید، Certbot بعد از هر تمدید خودش Nginx را reload می‌کند تا گواهی تازه سرو شود. اگر با certonly و webroot رفته‌اید، این کار را به یک هوک بسپارید؛ اسکریپت‌های renewal-hooks/deploy فقط بعد از تمدیدِ موفق اجرا می‌شوند، نه در هر اجرای تایمر:

printf '#!/bin/bash\nsystemctl reload nginx\n' \
  | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

و برای اطمینان از بیرون، تاریخ انقضای گواهیِ درحال‌سرویس را مستقیم از خود سرور بپرسید:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
     | openssl x509 -noout -dates
# notBefore=Aug  6 07:15:22 2026 GMT
# notAfter=Nov  4 07:15:21 2026 GMT

curl -vI https://example.com 2>&1 | grep "expire date"
#  expire date: Nov  4 07:15:21 2026 GMT
💡 نکته: Let's Encrypt از ۴ ژوئن ۲۰۲۵ دیگر ایمیل هشدار انقضا نمی‌فرستد. اگر تمدید خودکار بی‌صدا بشکند، اولین کسی که می‌فهمد بازدیدکننده‌ی سایت شماست؛ پس همین چک openssl را در مانیتورینگ دوره‌ای سرور بگذارید تا مثلاً ۱۵ روز مانده به انقضا هشدار بگیرید. رسیدن به ۱۵ روز یعنی تمدید دو هفته است که شکست می‌خورد؛ علتش در /var/log/letsencrypt/letsencrypt.log است.

ری‌دایرکت ۳۰۱ و آزمون نهایی

Certbot از نسخه‌ی ۱.۰ هنگام نصب گواهی با پلاگین nginx یا apache، ری‌دایرکت HTTP به HTTPS را هم به‌صورت پیش‌فرض فعال می‌کند. اگر با webroot رفته‌اید یا می‌خواهید مطمئن شوید، بلاک پورت ۸۰ باید فقط یک کار انجام دهد:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

کد ۳۰۱ (دائمی) مهم است، نه ۳۰۲: به موتورهای جست‌وجو می‌گوید نسخه‌ی HTTPS آدرس اصلی است و اعتبار لینک‌های قدیمی به آن منتقل شود. بعد از تغییر، مثل همیشه nginx -t && systemctl reload nginx. چالش تمدید هم نمی‌شکند: Let's Encrypt ری‌دایرکت به HTTPS را دنبال می‌کند و برای /.well-known استثنا لازم نیست.

یک تله‌ی رایج بعد از مهاجرت، محتوای مختلط (mixed content) است: صفحه از HTTPS می‌آید ولی عکس‌ها و اسکریپت‌ها هنوز با آدرس http:// صدا زده می‌شوند و مرورگر یا قفل را برمی‌دارد یا آن منابع را بلاک می‌کند. در وردپرس باید آدرس سایت در تنظیمات و آدرس‌های ذخیره‌شده در دیتابیس هر دو به https اصلاح شوند — روش درستش را در راهنمای نصب و انتقال وردپرس روی سرور مجازی آورده‌ایم.

در پایان، دامنه را در آزمون رایگان SSL Labs وارد کنید؛ چند دقیقه صبر می‌خواهد ولی گزارش کاملی از زنجیره‌ی گواهی، پروتکل‌ها و نقاط ضعف می‌دهد. با کانفیگی که Certbot می‌سازد معمولاً بدون هیچ کار اضافه نمره‌ی A می‌گیرید.

⚠️ هدر HSTS (Strict-Transport-Security) به مرورگر می‌گوید تا ماه‌ها فقط با HTTPS سراغ دامنه‌ی شما بیاید — و مرورگر این قول را فراموش نمی‌کند. تا وقتی ری‌دایرکت، تمدید خودکار و همه‌ی ساب‌دامنه‌ها چند هفته بی‌مشکل کار نکرده‌اند، فعالش نکنید؛ اگر بعد از فعال‌کردن آن HTTPS بشکند، کاربران قبلی حتی نمی‌توانند موقتاً از نسخه‌ی HTTP استفاده کنند و سایت برایشان کاملاً بسته می‌شود.

خطاهای رایج گواهی SSL و راه‌حل سریع

اگر صدور گواهی شکست خورد یا بعد از نصب رفتار عجیبی دیدید، مشکل شما تقریباً همیشه یکی از این هفت مورد است:

نشانه / پیام خطاعلت واقعیراه‌حل
Timeout during connect یا Connection refused در چالش HTTP-01پورت ۸۰ در فایروال بسته استپورت‌های ۸۰ و ۴۴۳ را در ufw یا firewalld باز کنید (دستورها پایین‌تر)
During secondary validation: … Timeoutپورت ۸۰ فقط از داخل ایران باز است و نقاط اعتبارسنجی خارجی به سرور نمی‌رسندمحدودیت جغرافیایی فایروال را بردارید یا به DNS-01 بروید
Invalid response from …/.well-known/acme-challenge/…: 404مسیر -w با روت واقعی بلاک server یکی نیست، یا درخواست به بلاک دیگری می‌رسدبا فایل آزمایشی curl بالا مسیر را پیدا کنید؛ server_name را چک کنید
no valid A records found یا NXDOMAINدامنه هنوز به IP سرور اشاره نمی‌کند یا انتشار DNS کامل نشدهرکورد A را بسازید، با dig +short چک کنید و به انتشار فرصت بدهید
too many certificates already issuedسقف ۵ گواهی در هفته برای مجموعه‌ی نام‌های یکسان پر شدهچند روز صبر کنید (هر ۳۴ ساعت یک واحد آزاد می‌شود)؛ برای تست همیشه --dry-run بزنید
CAA record prevents issuanceرکورد CAA دامنه اجازه‌ی صدور به Let's Encrypt نمی‌دهدرکورد CAA را با مقدار 0 issue "letsencrypt.org" اصلاح کنید
خطای «too many redirects» بعد از نصب گواهیسایت پشت کلادفلر است و حالت SSL روی Flexible ماندهحالت رمزنگاری کلادفلر را روی Full (strict) بگذارید

شایع‌ترینِ همه، پورت بسته است. چالش HTTP-01 حتماً باید از اینترنت — و از چند کشور مختلف — به پورت ۸۰ سرور شما برسد؛ اگر طبق چک‌لیست امنیت سرور لینوکس فایروال را سفت‌وسخت بسته‌اید، این دو سرویس باید استثنا باشند:

sudo ufw allow 'Nginx Full'                        # Ubuntu / Debian
sudo firewall-cmd --permanent --add-service=http   # AlmaLinux / Rocky
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

مورد CAA هم یک چک یک‌خطی دارد؛ اگر خروجی خالی بود مشکلی نیست و اگر رکوردی بود، باید letsencrypt.org در آن مجاز باشد:

dig CAA example.com +short
# 0 issue "letsencrypt.org"

و اما کلادفلر، که بخش بزرگی از سایت‌های ایرانی پشت آن نشسته‌اند: در حالت Flexible، کلادفلر با بازدیدکننده HTTPS حرف می‌زند ولی با سرور شما HTTP؛ حالا که ری‌دایرکت ۳۰۱ گذاشته‌اید، سرورتان همان درخواست HTTP را دوباره به HTTPS می‌فرستد و یک حلقه‌ی بی‌پایان ساخته می‌شود — همان «too many redirects» معروف. راه‌حل درست، حذف ری‌دایرکت نیست: حالا که با Certbot گواهی معتبر روی سرور اصلی دارید، حالت را روی Full (strict) بگذارید تا مسیر کاربر تا سرور سرتاسر رمزنگاری‌شده و معتبر باشد. ناهماهنگی SSL بین کلادفلر و سرور اصلی معمولاً خودش را به شکل خطاهای خانواده‌ی 52x نشان می‌دهد — 526 یعنی کلادفلر گواهی سرور را نپذیرفته، مثلاً چون منقضی شده یا به‌جای fullchain.pem فقط cert.pem سرو می‌شود؛ تفکیک کامل این خانواده در راهنمای رفع خطای 502 آمده است.

سؤالات پرتکرار

آیا گواهی SSL رایگان Let's Encrypt از گواهی پولی ضعیف‌تر است؟

نه. سطح رمزنگاری، اعتبار در مرورگرها و ظاهر قفل دقیقاً یکسان است. گواهی‌های پولی در نوع اعتبارسنجی (سازمانی OV و EV)، بیمه‌ی صدور و پشتیبانی فرق دارند که برای اکثریت مطلق سایت‌ها هیچ ارزش عملی اضافه‌ای ندارد؛ به همین دلیل بخش بزرگی از وب امروز روی همین گواهی‌های رایگان می‌چرخد.

چرا گواهی Let's Encrypt فقط ۹۰ روزه است؟

عمداً؛ عمر کوتاه یعنی اگر کلید خصوصی لو برود، مهاجم مدت کمی فرصت سوءاستفاده دارد، و یعنی همه مجبور می‌شوند تمدید را خودکار کنند. با تایمر systemd که Certbot می‌سازد، تمدید حدود ۳۰ روز مانده به انقضا خودش انجام می‌شود و شما عملاً هیچ‌وقت متوجه آن نمی‌شوید. کل صنعت هم به همین سمت می‌رود: سقف عمر گواهی‌های پولی از مارس ۲۰۲۶ به ۲۰۰ روز رسیده و تا مارس ۲۰۲۹ به ۴۷ روز می‌رسد.

از کجا مطمئن شوم تمدید خودکار SSL واقعاً کار می‌کند؟

سه چک: systemctl list-timers نشان بدهد تایمر certbot فعال است؛ sudo certbot renew --dry-run بدون خطا تمام شود؛ و تاریخ انقضای واقعی را با openssl s_client یا curl -vI ببینید. چون Let's Encrypt دیگر ایمیل هشدار انقضا نمی‌فرستد، این چک آخر را در مانیتورینگ دوره‌ای بگذارید.

برای چند دامنه و ساب‌دامنه چند گواهی لازم دارم؟

معمولاً فقط یک گواهی: هر گواهی می‌تواند تا ۱۰۰ نام داشته باشد، کافی است همه را با -d پشت سر هم بدهید. اگر تعداد ساب‌دامنه‌ها نامشخص یا متغیر است، گواهی wildcard بگیرید که چالش DNS-01 می‌خواهد؛ برای دامنه‌های کاملاً جدا هم گواهی‌های مستقل تمیزتر و امن‌تر است.

روی هاست اشتراکی cPanel یا DirectAdmin چطور SSL رایگان فعال کنم؟

روی هاست اشتراکی به Certbot و SSH نیازی نیست؛ خود پنل همین کار را با Let's Encrypt انجام می‌دهد. در مهران هاست از تب «گواهی SSL» پنل فارسی دکمه‌ی «درخواست صدور گواهی» را بزنید تا گواهی صادر و خودکار نصب شود؛ در cPanel و DirectAdmin هم همین کار را AutoSSL یا گزینه‌ی ACME Provider انجام می‌دهد. پیش‌نیاز این است که رکورد A دامنه به همان هاست اشاره کند؛ تمدید را پنل خودش انجام می‌دهد و فقط ری‌دایرکت ۳۰۱ می‌ماند که در .htaccess می‌گذارید.

قدم بعدی

مسیر کامل همین بود: Certbot را نصب کنید، با پلاگین nginx گواهی بگیرید، همان روز اول renew --dry-run را تست کنید و در آخر نمره‌تان را از SSL Labs بگیرید؛ روی هاست اشتراکی مهران هاست همین کار را تب «گواهی SSL» پنل فارسی انجام می‌دهد. اگر می‌خواهید قبل از دست‌زدن به سایت اصلی یک بار کامل و بی‌استرس تمرین کنید، یک سرور ابری ساعتی در مهران هاست بسازید — تحویلش حدود ۶۰ ثانیه است — یک ساب‌دامنه‌ی آزمایشی به آن بدهید، کل مسیر از نصب تا خراب‌کردن و درست‌کردنِ دوباره را بروید و فقط هزینه‌ی همان یکی‌دو ساعت تمرین را بپردازید.

آموزش‌های مرتبط

آماده‌ی تمرین عملی هستید؟

سرور ابری ساعتی مهران هاست در ۶۰ ثانیه تحویل می‌شود — تمرین کنید و فقط بابت همان ساعت‌ها پرداخت کنید. هزینه را پیش از ثبت‌نام با محاسبه‌گر برآورد کنید.