خرابی تمدید خودکار معمولاً یکی از دو حالت دارد: client اصلاً اجرا نشده، یا اجرا شده اما challenge، ذخیره فایل یا reload سرویس شکست خورده است. تا زمانی که مشخص نشود کدام مرحله خراب است، صدور دستی گواهی جدید فقط بحران فعلی را عقب میاندازد و چرخه بعدی دوباره تکرار میشود.
پاسخ سریع: تاریخ انقضای گواهی ارائهشده، وضعیت timer/job و log آخرین اجرای renewal را ثبت کنید. سپس با dry-run همان client، همه دامنهها را آزمایش کنید. DNS، port challenge، webroot/proxy، credential DNS و hook reload را جدا بررسی کنید؛ در پایان گواهی واقعی اینترنت را دوباره بخوانید.
اول مشخص کنید چه چیزی منقضی میشود
گواهی روی disk، گواهی load balancer و certificate ارائهشده از اینترنت ممکن است متفاوت باشند. hostname، serial یا fingerprint، issuer و expiry را در هر لایه مقایسه کنید. اگر CDN TLS را terminate میکند، تمدید origin لزوماً گواهی کاربر را عوض نمیکند و برعکس.
چهار مرحله مستقل Renewal
- Scheduler باید client را اجرا کند.
- Client باید renewal configuration و account را بخواند.
- ACME challenge باید از بیرون موفق شود.
- گواهی تازه باید به سرویس درست برسد و reload شود.
عبارت «renewal کار نمیکند» بدون تعیین مرحله، تشخیص را طولانی میکند. برای هر مرحله خروجی و timestamp مستقل نگه دارید.
تاریخ انقضا و موجودی Certbot
sudo certbot certificates
sudo certbot renew --dry-run
اگر Certbot client فعال شماست، دستور اول lineageها و دوم شبیهسازی تمدید را بررسی میکند. در container یا client دیگر، از ابزار همان معماری استفاده کنید. dry-run ممکن است به staging CA وصل شود؛ موفقیت آن باید همراه تست hook و مسیر deployment تفسیر شود.
Scheduler اجرا نمیشود
نصب ممکن است systemd timer، cron یا scheduler container داشته باشد. وجود فایل timer ثابت نمیکند اجرا موفق است. زمان آخرین/بعدی اجرا، exit code و journal را ببینید. دو نصب موازی Certbot میتوانند binary، config و timer متفاوتی داشته باشند و هرکدام lineage دیگری را مدیریت کند.
Renewal Config قدیمی
پس از انتقال سرور، تغییر webroot، plugin یا نام دامنه، فایل renewal ممکن است به مسیر و authenticator قدیمی اشاره کند. آن را کور ویرایش نکنید؛ ابتدا backup و مستندات نسخه client را ببینید. حذف lineage برای «شروع تازه» ممکن است reference فعال وبسرور را بشکند.
DNS به سرور دیگری اشاره میکند
A و AAAA را برای تمام نامهای گواهی بررسی کنید. migration نیمهکاره یا IPv6 قدیمی باعث میشود challenge به host دیگری برسد. DNS split-horizon ممکن است از داخل درست و از اینترنت غلط باشد. resolverهای مستقل و authoritative response را مقایسه کنید.
HTTP-01 و مسیر Challenge
port 80 باید به client یا webroot درست برسد. redirect، rewrite، authentication، WAF یا CDN ممکن است مسیر /.well-known/acme-challenge/ را تغییر دهد. یک فایل بیخطر در webroot مورد انتظار بسازید و از بیرون route را آزمون کنید؛ پس از تست artifact را مدیریت کنید.
Firewall یا NAT
listener محلی سالم به معنی دسترسی CA نیست. cloud firewall، host firewall، NAT و security group را بررسی کنید. باز کردن port روی interface اشتباه یا فقط IPv4 کافی نیست. راهنمای Firewall سرور روش تست end-to-end را توضیح میدهد.
DNS-01 و Credential API
token منقضی، scope ناکافی، تغییر zone یا secret غیرقابلخواندن renewal را میشکند. log را بدون چاپ token بررسی کنید. فایل credential باید permission محدود داشته باشد. propagation رکورد TXT نیز زمان میخواهد؛ resolver client و authoritative server را جدا ببینید.
Wildcard و Apex
گواهی wildcard و نام اصلی ممکن است در یک lineage باشند. رکورد TXT برای نام challenge دقیق باید ساخته و پاک شود. automation چند درخواست همزمان میتواند TXTها را overwrite کند؛ plugin باید چند مقدار و concurrency را درست مدیریت کند.
Rate Limit و تلاشهای تکراری
تکرار بیبرنامه صدور production میتواند به محدودیت CA برسد. پیام دقیق خطا و زمان retry را بخوانید و مشکل challenge را ابتدا با dry-run/staging رفع کنید. تغییر مداوم نام گواهی برای دور زدن limit، lineageها و config را پیچیدهتر میکند.
رکورد CAA و محدودیت صدور
رکورد CAA میتواند مشخص کند کدام CA اجازه صدور برای دامنه را دارد. تغییر اشتباه آن ممکن است renewal را پس از ماهها کارکرد متوقف کند. پاسخ authoritative، نام دامنه والد و provider DNS را بررسی کنید؛ cache resolver محلی بهتنهایی معیار کافی نیست.
اگر سازمان عمداً CAA را محدود کرده، حذف آن برای عبور از خطا سیاست امنیتی را دور میزند. CA مجاز و نیاز wildcard را با مالک DNS هماهنگ کنید و تغییر را با TTL و زمان propagation در timeline incident ثبت کنید.
ساعت سرور
clock اشتباه میتواند اعتبار token، TLS و log correlation را خراب کند. وضعیت sync را بررسی و NTP را اصلاح کنید. ساعت را دستی برای عبور از خطا جابهجا نکنید؛ این کار cron، log، دیتابیس و session را مختل میکند.
Permission و فضای Disk
client برای نوشتن config، archive و log به permission و disk/inode نیاز دارد. پر بودن filesystem یا ownership تغییرکرده renewal را متوقف میکند. permission عمومی ندهید و directory کلید خصوصی را قابلخواندن برای برنامه نکنید. علت رشد disk را جدا رفع کنید.
گواهی تمدید شده ولی سایت قدیمی است
این حالت معمولاً از reload نشدن process، اشاره config به path دیگر، کپی ثابت certificate یا termination در لایه دیگر است. symlink lineage و path فعال Nginx را مقایسه کنید. سپس syntax test و reload کنترلشده انجام دهید. restart همه containerها بدون شناخت ضروری نیست.
Deploy Hook شکست میخورد
hook باید فقط پس از renewal موفق اجرا شود، exit code درست بدهد و secret چاپ نکند. path و environment در scheduler ممکن است با shell مدیر فرق داشته باشد. فرمان interactive یا وابسته به working directory در timer شکست میخورد. log hook و config test وبسرور را مستقل نگه دارید.
Certificate داخل Docker
اگر فایل host به container bind mount شده، symlink و path واقعی باید داخل container قابل مشاهده باشد. اگر certificate در image کپی شده، renewal host آن را عوض نمیکند. طراحی بهتر باید source of truth، mount و signal/reload مشخص داشته باشد و container با private key بیش از نیاز دسترسی نگیرد.
Load Balancer یا CDN
ممکن است provider certificate خودش را مدیریت کند و origin گواهی جدا داشته باشد. dashboard provider، CNAME/proxy mode و hostname origin را بررسی کنید. آپلود دستی هر چند ماه اتوماسیون نیست؛ API و secret باید با حداقل دسترسی و alert شکست طراحی شود.
ترتیب عیبیابی
- گواهی ارائهشده و expiry را ثبت کنید.
- client و scheduler واقعی را شناسایی کنید.
- log آخرین run و renewal config را بخوانید.
- dry-run را بدون تکرار بیرویه اجرا کنید.
- DNS و challenge را از بیرون تست کنید.
- write، disk و credential را بررسی کنید.
- path certificate و hook reload را تطبیق دهید.
- پس از اصلاح، گواهی اینترنت و alert را تأیید کنید.
اگر گواهی نزدیک انقضاست
دامنه اثر، زمان باقیمانده و روش rollback را مشخص کنید. ابتدا علت challenge را رفع و صدور کنترلشده انجام دهید؛ فایل کلید یا config فعال را بدون backup جایگزین نکنید. پس از renewal، Nginx و endpointهای حیاتی را smoke test کنید. incident را بعد از احیا با اصلاح automation ببندید.
اشتباههای رایج
- صدور دستی و رها کردن علت timer
- نادیده گرفتن AAAA یا proxy CDN
- تکرار production تا رسیدن به rate limit
- حذف renewal config و شکستن path فعال
- permission عمومی به private key
- فرض موفقیت چون فایل روی disk تازه است
- restart همه سرویسها به جای reload هدفمند
- مانیتورکردن job بدون expiry واقعی اینترنت
پیشگیری
dry-run دورهای، expiry probe بیرونی، alert شکست scheduler و reload، inventory دامنه و owner لازم است. تغییر DNS، migration و تعویض proxy باید شامل تست renewal باشد. راهنمای نصب Let’s Encrypt طراحی اولیه درست challenge و storage را پوشش میدهد.
چه زمانی کمک تخصصی لازم است؟
اگر تمدید میان DNS provider، CDN، Nginx و Docker پخش شده یا گواهی کمتر از چند روز اعتبار دارد، آزمون تصادفی ریسک rate limit و downtime دارد. مدیریت ماهانه سرور میتواند مسیر renewal را end-to-end اصلاح و مانیتور expiry واقعی را فعال کند.
پرسشهای متداول
چرا dry-run موفق است ولی سایت گواهی قدیمی دارد؟
احتمالاً deployment/reload یا path لایه TLS اشتباه است؛ certificate ارائهشده را با فایل renewal مقایسه کنید.
چرا فقط یک دامنه از چند دامنه تمدید نمیشود؟
DNS، route challenge یا webroot همان hostname ممکن است متفاوت باشد؛ هر SAN را جدا از بیرون بررسی کنید.
آیا restart Nginx لازم است؟
معمولاً reload کنترلشده برای خواندن گواهی تازه کافی است، اما روش دقیق به معماری و سرویس termination وابسته است.
آیا حذف و صدور دوباره بهترین راه است؟
نه؛ ممکن است referenceها را بشکند و علت automation باقی بماند. ابتدا config و challenge فعلی را تشخیص دهید.