# 1. Generare certificat inițial (cu Cloudflare ca exemplu)
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
--dns-cloudflare-propagation-seconds 120 \
-d "domeniu.ro" \
-d "*.domeniu.ro" \
--deploy-hook "systemctl reload nginx"
# 2. Configurație securizată pentru fișierul de credențiale (/etc/letsencrypt/cloudflare.ini)
# dns_cloudflare_api_token = xxxx_TOKEN_CU_DREPTURI_RESTRICTIONATE_xxxx
# Important: chmod 600 /etc/letsencrypt/cloudflare.ini
# 3. Testare automatizată a procesului de renew fără a atinge producția
certbot renew --dry-runAm văzut prea mulți devs care își pun reminder în Google Calendar la fiecare 80 de zile ca să reînnoiască manual certificatele wildcard. Dacă ești pe Nginx sau Apache și gestionezi zeci de subdomenii, metoda clasică cu HTTP-01 challenge nu merge pentru *.domeniu.ro. Ai nevoie de DNS-01 challenge, iar făcut manual e o rețetă sigură pentru dezastru.
La o aplicație SaaS pe care o administrez, cu vreo 40 de subdomenii dinamice pentru clienți, am avut exact problema asta. Un fost coleg pusese un cron job simplu, dar care eșua tăcut pentru că recordul TXT nu se propaga la timp. Ne-am trezit într-o luni dimineață cu notificări de la 15 clienți că paginile lor sunt marcate ca "Not Secure".
Problema cu DNS-01 și de ce eșuează renew-ul automat
Spre deosebire de HTTP-01 (unde Let's Encrypt verifică un fișier pe serverul tău web), DNS-01 cere crearea unui record TXT numit _acme-challenge.domeniu.ro. Când încerci să automatizezi asta cu un script bash scris în grabă, dai peste două probleme majore:
- Propagarea DNS (Race condition): Scriptul tău adaugă recordul prin API-ul furnizorului (Cloudflare, AWS Route53, Hetzner), dar serverele DNS de la Let's Encrypt încearcă să-l citească înainte să se fi propagat global. Rezultat: validation failed.
- Reload-ul de server web: Înnoiești fișierele PEM de pe disc, dar Nginx sau Apache rămân cu vechiul cert încărcat în memorie până le dai un reload.
Soluția: Certbot cu DNS Plugin și propagation delay
Soluția matură nu este să scrii cURL-uri manuale către API-ul furnizorului tău de DNS. Folosește plugin-urile dedicate de Certbot (python3-certbot-dns-cloudflare, python3-certbot-dns-route53 etc.). Aceastea gestionează singure adăugarea și ștergerea recordului TXT.
Secretul ca să nu ai downtime este parametrul --dns-cloudflare-propagation-seconds. În funcție de provider, un TTL de 120 de secunde salvează totul. Certbot adaugă cheia TXT, așteaptă 2 minute ca nameserverele să fie sincronizate, și abia apoi trimite semnalul către ACME server că e gata de verificare.
Pentru serverul web, folosești --deploy-hook. Acesta rulează doar dacă certificatul a fost într-adevăr reînnoit cu succes, dând un reload la Nginx fără să oprească serviciul nicio secundă.
Trade-off-uri reale
Sistemul ăsta e aproape bulletproof, dar are două puncte slabe de care trebuie să fii conștient:
- Securitatea API Token-ului: Token-ul DNS salvat pe server are acces să-ți modifice zons-ele DNS. Dacă e compromis serverul web, atacatorul îți poate deturna domeniul. Recomand un token cu permisiuni restrictive (doar editare pe zona respectivă, fără drept de delete domain).
- Expirarea token-urilor: Token-urile API au uneori dată de expirare. Dacă expiră după 1 an, renew-ul eșuează tăcut până când te prinzi de ce nu mai merge cron-ul.
Nu uita să testezi întotdeauna cu opțiunea --dry-run înainte să lași cron-ul să își facă de cap. Un dry-run simulează tot procesul prin mediul de Staging de la Let's Encrypt și te scapă de rate-limiting-ul agresiv din producție.
Câștigul? Zero downtime, zero alerte la 3 dimineața și un setup pe care îl configurezi o singură dată și funcționează ani de zile.
Voi cum gestionați wildcard-urile în producție? Mergeți pe Certbot clasic cu plugin-uri de DNS sau ați trecut totul prin Caddy / Traefik care fac asta automat out-of-the-box?