Certbot — Let's Encrypt TLS

If you like this project, consider supporting me on Buy Me a Coffee ☕️


tags:

Description

Certbot is the official EFF client for the ACME protocol (RFC 8555). It automates TLS certificate issuance, renewal, and revocation against public CAs such as Let's Encrypt, ZeroSSL, and Google Trust Services. / Certbot — официальный клиент ACME-протокола (RFC 8555) для автоматического выпуска, продления и отзыва TLS-сертификатов (Let's Encrypt, ZeroSSL, Google Trust Services).

Common use cases / Типовые сценарии:

Status: Actively maintained; production default for public TLS. Alternatives: acme.sh (POSIX shell), lego (Go), win-acme, Traefik/Caddy (built-in ACME). / Статус: Активно поддерживается; стандарт для публичного TLS. Альтернативы: acme.sh, lego, Caddy (встроенный ACME).

Default ports: ACME HTTP-01 80/tcp; DNS-01 53/tcp/udp (DNS provider).
Paths: certs /etc/letsencrypt/live/<NAME>/; renewal /etc/letsencrypt/renewal/<NAME>.conf.

Cross-reference: OpenSSL, OpenSSL CSR SAN, nginx, Apache.


Installation

Install Certbot / Установка Certbot

# Debian/Ubuntu (distro package)
apt update
apt install certbot python3-certbot-nginx   # or python3-certbot-apache

# RHEL/Rocky/Alma/Fedora
dnf install certbot python3-certbot-nginx

# Snap (often newest version + DNS plugins)
apt install snapd
snap install --classic certbot
snap install --classic certbot-dns-cloudflare   # example DNS plugin

# Pip (last resort; prefer distro/snap)
pip install certbot certbot-dns-cloudflare
certbot --version  # Verify install / Проверить установку

Nginx/Apache integration packages / Интеграция с веб-серверами

# Debian/Ubuntu
apt install python3-certbot-nginx
apt install python3-certbot-apache

Configuration

Main paths / Основные пути

/etc/letsencrypt/

/etc/letsencrypt/live/<CERT_NAME>/

/etc/letsencrypt/renewal/<CERT_NAME>.conf

/etc/letsencrypt/renewal-hooks/{pre,deploy,post}/

/etc/letsencrypt/keys/ (account keys; mode 0700)

# Certificate files per domain
ls -la /etc/letsencrypt/live/<HOST>/
# cert.pem      — leaf/server certificate
# chain.pem     — intermediates only
# fullchain.pem — leaf + intermediates (use this for nginx)
# privkey.pem   — private key (0600 root-only by default)

[!CAUTION] Never copy private keys out of /etc/letsencrypt into chat, tickets, or world-readable paths. Point webserver configs at /etc/letsencrypt/live/... symlinks. / Не копируйте приватные ключи в чаты и world-readable пути; настройте веб-сервер на симлинки.

Main client config / Основной конфиг клиента

/etc/letsencrypt/cli.ini

# Non-interactive production defaults
agree-tos = true
email = <EMAIL>
# key-type = ecdsa          # default for new certs (P-256)
# rsa-key-size = 4096       # only if you force RSA
# prefer-challenges = dns   # for wildcard-capable runs

DNS plugin credentials (Cloudflare example) / Учётные данные DNS-плагина

/etc/letsencrypt/dns-cloudflare.ini

dns_cloudflare_api_token = <SECRET_KEY>
chmod 600 /etc/letsencrypt/dns-cloudflare.ini  # Protect credentials / Ограничить доступ

Core Management

Issue certificates / Выпуск сертификатов

# Nginx auto-issue + install + redirect
certbot --nginx -d <HOST> -d www.<HOST>

# Apache auto-issue + install
certbot --apache -d <HOST>

# Certificate only (certbot certonly) — no webserver install
certbot certonly --standalone -d <HOST>

# Webroot (already-running webserver, no restart)
certbot certonly --webroot -w /var/www/html -d <HOST>

# DNS-01 (wildcard)
certbot certonly --dns-cloudflare -d <HOST> -d '*.<HOST>'

# Staging (test rate limits; trust chain not for production browsers)
certbot certonly --staging -d <HOST>

# Force RSA key
certbot certonly --nginx --key-type rsa --rsa-key-size 4096 -d <HOST>

List and inspect / Список и инспекция

certbot certificates                 # List known certs / Список сертификатов
certbot show                          # Alias-ish overview on some builds; prefer certificates
openssl x509 -in /etc/letsencrypt/live/<HOST>/cert.pem -noout -text  # Detail / Детали
openssl x509 -in /etc/letsencrypt/live/<HOST>/cert.pem -noout -enddate

Sample output:

Certificate Name: example.com
  Domains: example.com www.example.com
  Expiry Date: 2027-01-15 12:00:00+00:00 (VALID: 80 days)
  Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
  Key Type: ECDSA
  Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

Renew / Продление

certbot renew                         # Renew all due certs
certbot renew --dry-run               # Simulate against staging / Тестовое продление
certbot renew -q --quiet
certbot renew --cert-name <HOST> --force-renewal   # Force (watch rate limits!)

[!WARNING] --force-renewal counts against Let's Encrypt rate limits (typically 5 duplicate certs/week per registered domain set). Use only for key rotation or controlled migrations. / --force-renewal учитывается в rate limits Let's Encrypt; используйте только для ротации ключей и миграций.

Expand / change domains / Изменение доменов

certbot certonly --expand -d <HOST> -d www.<HOST> -d api.<HOST>
certbot certonly --cert-name <HOST> -d <HOST>   # Set exact domain set

# Modern preferred: reconfigure renewal params
certbot reconfigure --cert-name <HOST> --webroot-path /var/www/new

Revoke and delete / Отзыв и удаление

certbot revoke --cert-name <HOST>
certbot revoke --cert-path /etc/letsencrypt/live/<HOST>/cert.pem \
  --key-path /etc/letsencrypt/live/<HOST>/privkey.pem
certbot revoke --cert-name <HOST> --reason keycompromise

# Remove cert files after config references are gone
certbot delete --cert-name <HOST>

[!CAUTION] Deleting a cert without removing nginx/Apache references first breaks TLS on reload. Always grep -R live/<HOST> /etc/{nginx,apache2,httpd} first. / Удалите ссылки из конфигов веб-серверов до certbot delete.


Sysadmin Operations

Automated renewal timer / Автоматическое продление

# systemd timer (Debian/Ubuntu often ships this)
systemctl list-timers | grep -i certbot
cat /etc/cron.d/certbot 2>/dev/null || true

/etc/systemd/system/certbot-renew.service (optional explicit unit)

[Unit]
Description=Certbot renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook /usr/local/bin/reload-tls.sh

/etc/systemd/system/certbot-renew.timer

[Unit]
Description=Run certbot renew twice daily

[Timer]
OnCalendar=*-*-* 00,12:07:00
RandomizedDelaySec=3600
Persistent=true

[Install]
WantedBy=timers.target
systemctl enable --now certbot-renew.timer

Deploy hooks / Скрипты после продления

/etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

#!/bin/bash
# Reload TLS after cert change / Перезагрузить TLS после смены сертификата
systemctl reload nginx
# or: systemctl reload apache2
chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Pre/post hooks for standalone / Хуки для standalone

certbot renew \
  --pre-hook "systemctl stop nginx" \
  --post-hook "systemctl start nginx"

Permissions for non-root daemons / Права для нерутовых демонов

# Allow nginx worker user to read privkey
chgrp <WEB_GROUP> /etc/letsencrypt/live/<HOST>/privkey.pem
chmod 0640 /etc/letsencrypt/live/<HOST>/privkey.pem
# live/ and archive/ are 0700 by default — optional relax for non-root only
# chmod 0755 /etc/letsencrypt/{live,archive}   # only if you never downgrade Certbot

Export / convert / Экспорт и конвертация

# PEM → PKCS#12 for Windows/clients
openssl pkcs12 -export \
  -inkey /etc/letsencrypt/live/<HOST>/privkey.pem \
  -in /etc/letsencrypt/live/<HOST>/fullchain.pem \
  -out /tmp/<HOST>.p12 -name <HOST>

# Split fullchain into leaf + chain for some MTAs/load balancers
openssl crl2pkcs7 -nocrl -certfile /etc/letsencrypt/live/<HOST>/fullchain.pem | \
  openssl pkcs7 -print_certs -out /tmp/<HOST>-chain-only.pem

Logrotate / Ротация логов

/etc/logrotate.d/certbot

/var/log/letsencrypt/letsencrypt.log {
    monthly
    rotate 6
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
}

Note: most distro packages already manage logs under /var/log/letsencrypt/. / Обычно ротацию уже настраивает дистрибутивный пакет.


Security

Best practices / Рекомендации

# Expiry monitoring without waiting for CA email
certbot certificates | grep -A2 "Expiry Date"
# Or prometheus/blackbox style HTTP check on 443

Compromise response / Реакция на компрометацию ключа

  1. Revoke with --reason keycompromise / Отозвать сертификат с причиной keycompromise
  2. Delete compromised privkey.pem via certbot delete / Удалить приватный ключ
  3. Re-issue with new key (prefer ECDSA) / Выпустить новый сертификат
  4. Reload services; rotate any exported PKCS#12 / Перезагрузить сервисы, ротировать экспорты
  5. Investigate how the key was exposed / Разобраться в источнике утечки

Backup and Restore

Backup / Резервное копирование

# Backup certs + renewal configs + account keys (private data — encrypt!)
tar czf /var/backups/letsencrypt-$(date +%F).tar.gz \
  /etc/letsencrypt/{live,archive,renewal,accounts,cli.ini}
# Prefer age/GPG encryption for the archive

Restore / Восстановление

# Stop certbot timer
systemctl stop certbot-renew.timer

# Restore tree
tar xzf /var/backups/letsencrypt-<DATE>.tar.gz -C /

# Point webserver at restored live paths; reload
systemctl reload nginx

# Dry-run renew
certbot renew --dry-run
systemctl start certbot-renew.timer

[!NOTE] Restoring accounts/keys is preferred over re-issuing to stay under rate limits. Store backups encrypted; private keys are full material. / Восстанавливайте accounts/keys, а не перевыпускайте сертификаты; храните бэкапы в зашифрованном виде.


Troubleshooting

Common errors / Частые ошибки

Error Cause Fix
Unauthorized / 403 HTTP-01 Port 80 blocked, wrong vhost, /.well-known not served Open 80; fix webroot; check firewall
DNS problem: NXDOMAIN DNS-01 TXT not visible Wait for propagation; verify provider API token
RateLimited Too many duplicate issues Use staging; wait; stop --force-renewal
CertbotError: Invalid or insecure challenge TLS-only redirect before challenge Temporarily allow HTTP; disable force-HTTPS during issue
Renewal fails but manual works Wrong plugin args in renewal.conf certbot reconfigure --cert-name ... or dry-run with explicit plugin
nginx reload fails after renew Bad cert path or missing chain Check ssl_certificate points to fullchain.pem

Debug commands / Отладка

certbot renew --dry-run -v
certbot certificates --verbose
journalctl -u certbot-renew.service --no-pager -n 50
ss -lntp | grep -E ':80\b'   # Confirm HTTP-01 listener / Проверить порт 80
curl -I http://<HOST>/.well-known/acme-challenge/test

Comparison Tables

Auth plugins / Плагины аутентификации

Plugin Challenge Wildcard? Best for
nginx / apache HTTP-01 No Standard public web on that server / Обычный public web
webroot HTTP-01 No Existing webserver, no downtime / Уже работающий веб-сервер
standalone HTTP-01 No One-shot issue; needs port 80 free / Разовый выпуск, свободный порт 80
dns-cloudflare (etc.) DNS-01 Yes Wildcards, firewalled hosts / Вайлдкарды, закрытые хосты
manual HTTP/DNS Depends Emergency only / Только в крайнем случае

Certificate clients / Клиенты ACME

Client Language Pros Cons
Certbot Python Official, plugins, docs Heavier runtime
acme.sh POSIX shell Light, many DNS hooks Fewer server installers
lego Go Fast, good CI use No auto nginx config
Caddy Go Zero-touch ACME Tied to Caddy

Production Runbooks

Runbook: Issue cert for new site on nginx / Выпуск сертификата для нового сайта

  1. Confirm DNS A/AAAA for <HOST> points at this server / Проверить DNS-записи
  2. Confirm port 80 reachable from Internet / Проверить доступность 80/tcp
  3. Backup nginx config / Сделать бэкап конфига nginx
  4. Run certbot --nginx -d <HOST> -d www.<HOST> / Выпустить сертификат
  5. Verify TLS: curl -I https://<HOST> shows valid chain / Проверить цепочку
  6. Confirm timer exists: systemctl list-timers | grep certbot / Проверить автопродление
  7. Document cert name, domains, deploy hook / Задокументировать параметры

Runbook: Emergency renewal failure (expiring <7 days) / Экстренное продление

  1. certbot renew --cert-name <HOST> -v — capture full error / Собрать ошибку
  2. If HTTP-01 fails: temporarily allow port 80; disable force-HTTPS redirect / Открыть 80, отключить редирект
  3. If DNS-01 fails: verify API token, proxy settings (Cloudflare orange-cloud off for TXT) / Проверить DNS API
  4. Retry certbot renew --cert-name <HOST> --force-renewal (once) / Повторить принудительно один раз
  5. certbot certificates — confirm new expiry / Проверить дату
  6. systemctl reload nginx (or apache) / Перезагрузить веб-сервер
  7. File incident; fix automation before next window / Закрыть инцидент, починить автоматизацию

Runbook: Key rotation / Ротация приватного ключа

  1. certbot renew --cert-name <HOST> --key-type ecdsa --force-renewal / Выпустить новый ключ
  2. openssl x509 -in .../cert.pem -noout -text — verify Key Type / Проверить тип ключа
  3. Reload dependent services (nginx, postfix, openvpn) / Перезагрузить зависимые сервисы
  4. Re-export any PKCS#12/clients if used / Переэкспортировать клиентские артефакты
  5. Delete old archived key material after validation (retain short audit window) / Удалить старые ключи после проверки

On this page

linux 🔐 Certbot Cheatsheet (Let's Encrypt / ACME) Description Installation Install Certbot / Установка Certbot Nginx/Apache integration packages / Интеграция с веб-серверами Configuration Main paths / Основные пути Main client config / Основной конфиг клиента DNS plugin credentials (Cloudflare example) / Учётные данные DNS-плагина Core Management Issue certificates / Выпуск сертификатов List and inspect / Список и инспекция Renew / Продление Expand / change domains / Изменение доменов Revoke and delete / Отзыв и удаление Sysadmin Operations Automated renewal timer / Автоматическое продление Deploy hooks / Скрипты после продления Pre/post hooks for standalone / Хуки для standalone Permissions for non-root daemons / Права для нерутовых демонов Export / convert / Экспорт и конвертация Logrotate / Ротация логов Security Best practices / Рекомендации Compromise response / Реакция на компрометацию ключа Backup and Restore Backup / Резервное копирование Restore / Восстановление Troubleshooting Common errors / Частые ошибки Debug commands / Отладка Comparison Tables Auth plugins / Плагины аутентификации Certificate clients / Клиенты ACME Production Runbooks Runbook: Issue cert for new site on nginx / Выпуск сертификата для нового сайта Runbook: Emergency renewal failure (expiring &lt;7 days) / Экстренное продление Runbook: Key rotation / Ротация приватного ключа Documentation Links