ServerAID
Найти гайд, команду, тег… ⌘ K
Безопасность

Let's Encrypt и certbot на Ubuntu: бесплатный SSL для nginx

Let's Encrypt — бесплатные SSL/TLS-сертификаты для любого домена. На Ubuntu выпускаются через утилиту certbot одной командой; автообновление работает само через systemd-таймер. Разбираем установку, выпуск для nginx, DNS-challenge для wildcard-сертификатов и грабли с rate-limit.

Let's Encrypt на Ubuntu: certbot, автообновление, DNS-challenge

Let's Encrypt — бесплатные SSL/TLS-сертификаты для любого домена. На Ubuntu выпускаются через утилиту certbot одной командой; автообновление работает само через systemd-таймер. Разбираем установку, выпуск для nginx, DNS-challenge для wildcard-сертификатов и грабли с rate-limit.

Что такое Let's Encrypt

Let's Encrypt — это центр сертификации (CA), выдающий бесплатные SSL/TLS-сертификаты сроком на 90 дней. Запущен в 2016 году, сейчас покрывает большую часть HTTPS-сайтов в интернете. Принципы:

  • Бесплатно. Без скрытых тарифов и регистрации.
  • Автоматически. Выпуск через ACME-протокол: машинно-читаемый, скриптуемый.
  • 90-дневный срок. Сертификаты обновляются часто (стандарт — за 30 дней до истечения).
  • Любой домен. Работают и DV-сертификаты (Domain Validation) — подтверждение, что вы владелец.
  • Не работает для IP-адресов. Только полные доменные имена.

Не работает для:

  • IP-адресов и localhost (нужны самоподписные).
  • EV/OV-сертификатов с проверкой организации (для них берите коммерческие CA).
  • Подписи кода или email-сертификатов (LE только для TLS).

Стандартный клиент на Ubuntu — certbot, разработанный EFF.

Ставим certbot

На Ubuntu есть два пути установки. Snap-вариант рекомендуется самой EFF:

sudo apt install -y snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

--classic нужен для прямого доступа к файловой системе. Подробно про snapглоссарий snap.

Альтернатива — apt-репозиторий Ubuntu:

sudo apt install -y certbot python3-certbot-nginx

apt-вариант отстаёт по версии на полгода-год; для большинства задач этого хватает. Если вам нужен DNS-01 для wildcard или новые ACME-фичи — берите snap.

Проверка:

certbot --version

Выпускаем сертификат для nginx

Самый частый случай. У вас есть nginx-конфиг с server_name app.example.com, и вы хотите HTTPS.

Предусловия:

  • Домен app.example.com указывает A/AAAA-записями на ваш сервер.
  • Порт 80 открыт в UFW: sudo ufw allow 80/tcp.
  • nginx запущен и слушает 80-й порт для этого домена.

Команда:

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

Что произойдёт:

  1. certbot спросит email и согласие с TOS (только в первый раз).
  2. Сделает HTTP-01 challenge: создаст файл по /.well-known/acme-challenge/..., Let's Encrypt запросит его через 80-й порт.
  3. Получит сертификат и положит в /etc/letsencrypt/live/app.example.com/.
  4. Откроет ваш nginx-конфиг, добавит:
    • listen 443 ssl http2;
    • ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    • ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
  5. Перезагрузит nginx (systemctl reload nginx).

Готово — https://app.example.com работает с сертификатом.

Подробно про reverse proxy и nginx-конфигурацию — в гайде nginx reverse proxy на Ubuntu.

Структура /etc/letsencrypt/

После выпуска создаётся:

/etc/letsencrypt/
├── live/
│   └── app.example.com/
│       ├── cert.pem        — сам сертификат
│       ├── chain.pem       — промежуточные CA
│       ├── fullchain.pem   — cert + chain (используется в nginx)
│       ├── privkey.pem     — приватный ключ
│       └── README
├── archive/
│   └── app.example.com/    — все версии после обновлений
└── renewal/
    └── app.example.com.conf — настройки обновления

/live/ — симлинки на актуальные версии в /archive/. Используйте именно /live/ в nginx — после обновления симлинки обновятся, новый сертификат подхватится.

privkey.pem — режим 600, читать может только root. Не давайте этому файлу более широкие права.

Автообновление

certbot ставит systemd-таймер, который запускается дважды в день и обновляет сертификаты, у которых до истечения осталось меньше 30 дней:

systemctl status certbot.timer
systemctl list-timers | grep certbot

Принудительный тест обновления (без записи изменений):

sudo certbot renew --dry-run

--dry-run имитирует обновление, но не сохраняет результат. Рекомендуется запустить сразу после первого выпуска, чтобы убедиться: всё настроено корректно.

После реального обновления certbot сам перезагрузит nginx (через хук --deploy-hook или --post-hook). Если хук не настроен — добавьте:

# /etc/letsencrypt/renewal/app.example.com.conf
[renewalparams]
post_hook = systemctl reload nginx

Или глобально для всех сертификатов:

sudo mkdir -p /etc/letsencrypt/renewal-hooks/post
sudo bash -c 'cat > /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh' <<'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh

Подробно про systemd-таймеры и unit-файлы — в гайде systemctl enable.

DNS-01 challenge для wildcard

Сертификат *.example.com (wildcard) выпускается только через DNS-01 challenge — нужно подтвердить владение через TXT-запись в DNS, не через файл на сервере.

Установка DNS-плагина (зависит от провайдера DNS):

# Cloudflare
sudo snap install --classic certbot-dns-cloudflare
# или через apt:
sudo apt install -y python3-certbot-dns-cloudflare

# Hetzner Cloud DNS
sudo snap install certbot-dns-hetzner

# Прочие: route53 (AWS), digitalocean, gandi, godaddy и т. д.

Сохраняем API-токен провайдера в защищённый файл:

sudo tee /root/.cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = your_cloudflare_token_here
EOF
sudo chmod 600 /root/.cloudflare.ini

Выпускаем wildcard:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.cloudflare.ini \
  -d 'example.com' \
  -d '*.example.com'

certonly (вместо --nginx) — только получить сертификат, не править nginx-конфиг. Wildcard сертификаты часто используют в Kubernetes / Docker — там nginx-конфиги генерируются автоматически.

После выпуска — пропишите путь к сертификату в нужные конфиги вручную.

Standalone (если nginx ещё не настроен)

Если nginx не запущен (новый сервер), а сертификат нужен — certbot может стать временным веб-сервером:

sudo certbot certonly --standalone -d app.example.com

Запустит свой HTTP-сервер на 80-м порту, пройдёт challenge, выйдет. Никакой --nginx-конфигурации не делает — только получает сертификат в /etc/letsencrypt/live/.

Перед запуском убедитесь, что 80-й порт свободен (остановите nginx, если он работает).

Грабли certbot

Rate limits Let's Encrypt:

  • 50 сертификатов на домен в неделю.
  • 5 одинаковых выпусков в неделю.
  • 5 неудачных проверок в час на хост.

При тестировании используйте staging environment Let's Encrypt:

sudo certbot --staging --nginx -d test.example.com

Сертификат не доверенный, но лимиты на staging выше в 10–100 раз. Удалите тестовый: sudo certbot delete --cert-name test.example.com.

HTTP-01 за CDN. Cloudflare, Bunny, Selectel CDN могут перехватывать /.well-known/acme-challenge/. Решения:

  • Временно отключить proxy (Cloudflare: облачко серое = DNS only).
  • Использовать DNS-01 вместо HTTP-01.

Несколько серверов с одним доменом. Если домен указан на 2+ серверов через round-robin DNS, HTTP-01 может попасть не на тот сервер. Используйте DNS-01 или single-server-сценарий.

Не настроен AAAA. Если домен имеет AAAA-запись (IPv6), а сервер не слушает 80-й порт по IPv6 — challenge провалится. Либо настройте IPv6, либо удалите AAAA-запись на время выпуска.

Забыл --keep-until-expiring. Если запустите certbot повторно с теми же -d, он создаст новый сертификат, тратя rate-limit. Используйте sudo certbot renew (без -d) для штатных обновлений.

Closing port 80 после выпуска. Соблазнительно закрыть 80-й, оставить только 443. Но HTTP-01 challenge при обновлении использует именно 80-й порт. Альтернатива — TLS-ALPN-01 (требует поддержку, certbot её сделать сам не может) или DNS-01.

TLS-настройки nginx после certbot

certbot вставляет минимальные TLS-настройки. Для прода добавьте:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# HSTS — заставляет браузер всегда ходить по HTTPS
add_header Strict-Transport-Security "max-age=63072000" always;

Современные рекомендации (2026): отключайте TLS 1.0/1.1, оставляйте только 1.2 и 1.3. SSL Labs (ssllabs.com/ssltest) поможет проверить итог — целевой grade A+.

Удаление сертификата

sudo certbot delete --cert-name app.example.com

Удалит файлы из /etc/letsencrypt/live/ и /archive/, остановит автообновление этого сертификата. nginx-конфиг не правит — это нужно сделать руками (убрать listen 443 ssl; и пути к сертификату).

Частые вопросы

Что такое Let's Encrypt

Бесплатный центр сертификации (CA), выдающий SSL/TLS-сертификаты сроком на 90 дней. Запущен в 2016 году EFF/Mozilla/Akamai/Cisco. Работает через автоматизированный протокол ACME — выпуск и обновление можно полностью скриптовать. На Ubuntu стандартный клиент — certbot.

Бесплатно ли использовать Let's Encrypt в коммерческих целях

Да. Сертификаты бесплатные для любого использования — личное, коммерческое, корпоративное. Никаких лицензий, тарифов, ограничений по выручке. Единственные лимиты — rate-limits на количество выпусков в неделю.

Как часто обновляются сертификаты Let's Encrypt

Сертификаты живут 90 дней. certbot обновляет их автоматически за 30 дней до истечения через systemd-таймер (certbot.timer), который запускается дважды в день. Если автообновление работает — вмешательство не требуется.

Как выпустить сертификат для nginx через certbot

sudo certbot --nginx -d example.com -d www.example.com. certbot сделает HTTP-01 challenge, получит сертификат, отредактирует nginx-конфиг (добавит listen 443 ssl, пути к сертификату), перезагрузит nginx. Работает только если домен указывает на сервер и порт 80 открыт.

Как получить wildcard-сертификат через certbot

Только через DNS-01 challenge. Установите DNS-плагин (например, python3-certbot-dns-cloudflare), сохраните API-токен провайдера в файл, запустите sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cloudflare.ini -d 'example.com' -d '*.example.com'.

Что делать если certbot выдаёт rate limit

Подождать неделю или использовать staging environment: sudo certbot --staging ... — лимиты в 10+ раз выше. Сертификаты со staging не доверенные браузерами, но подходят для отладки конфига. После настройки — удалить staging-сертификат и выпустить настоящий.

Можно ли использовать Let's Encrypt без домена

Нет. LE выдаёт только DV-сертификаты для полноценных доменных имён. Для localhost, IP-адресов или внутренних имён используйте самоподписные сертификаты (openssl req) или внутренний CA (например, mkcert для разработки, step-ca для прода).

Что запомнить

  • certbot ставится через snap (рекомендация EFF) или apt (постарше). Команда sudo certbot --nginx -d example.com за 30 секунд выпускает сертификат и правит nginx-конфиг.
  • Сертификаты живут 90 дней, обновляются автоматически через certbot.timer. Запустите certbot renew --dry-run после первого выпуска.
  • Wildcard (*.example.com) — только через DNS-01 challenge с плагином DNS-провайдера. HTTP-01 не подходит.
  • 80-й порт должен оставаться открытым для обновлений HTTP-01. Не закрывайте его «потому что есть HTTPS».
  • Перед массовыми экспериментами — --staging, чтобы не упереться в rate-limit прода.
  • Подробно про SSL и TLS-настройки — гайд по nginx reverse proxy.

Обложка: фото Iain с Unsplash, лицензия Unsplash.

Похожие материалы

Безопасность

SSH-ключи на Ubuntu: вход без пароля, отключение паролей и смена порта

Заходить на сервер по SSH без пароля и при этом безопаснее, чем с паролем — главная польза от ключей. Разбираем `ssh-keygen ed25519`, `ssh-copy-id`, отключение парольного входа в `sshd_config`, смену SSH-порта, настройку `~/.ssh/config` на клиенте и генерацию ключей из Windows. Всё на Ubuntu 24.04 LTS.

Редакция
Безопасность

fail2ban на Ubuntu: защита SSH от перебора пароля

fail2ban читает /var/log/auth.log, ловит N неудачных попыток входа с одного IP за окно времени и временно банит этот IP через UFW или nftables. После UFW это второй слой защиты SSH: фаервол режет порты, fail2ban — назойливых ботов, которые подобрались к разрешённому 22/tcp. В статье — установка fail2ban на Ubuntu 24.04, дисциплина jail.local вместо jail.conf, готовый jail для sshd, диагностика fail2ban-client status и что делать, если забанили самого себя.

Редакция
Безопасность

UFW на Ubuntu: настройка фаервола за пять команд

UFW — обёртка над nftables, которая закрывает всю входящую сеть и оставляет открытыми только те порты, которые вам реально нужны. Пять команд — и сервер не отвечает на сканеры. Разбираем настройку UFW в Ubuntu Server и Desktop 24.04 LTS: как включить, как разрешить порт, как лимитировать SSH и как проверить статус, не закрыв сами себе доступ.

Редакция
Shell и скрипты

sed на Linux: замена строк, правка in-place и регулярки

sed (stream editor) — стандартная команда Linux для построчной обработки текста: замена, удаление, печать строк по шаблону. Работает с потоком (pipe) или файлами, поддерживает in-place редактирование. Базовый инструмент шелл-скриптов после `grep` и `awk`.

Редакция