Let's Encrypt SSL на VPS — установка и автопродление на Nginx
sudo certbot --nginx -d example.ru -d www.example.ru, проверяете sudo nginx -t && sudo systemctl reload nginx. Автопродление настраивается один раз — дальше Certbot регулярно запускает проверку командой certbot renew и обновляет сертификат только когда считает это нужным. Корректность автопродления проверяется командой sudo certbot renew --dry-run.Если вы подняли VPS под WordPress по гайду по настройке VPS с нуля, следующий шаг — HTTPS. Без него браузеры помечают сайт как небезопасный, а отдельные функции, платёжные системы, API, авторизация и современные возможности браузера могут работать некорректно или блокироваться. Let's Encrypt закрывает задачу бесплатно средствами ACME. Разбираем установку без панелей, только консоль.
Почему именно Let's Encrypt на VPS
Три причины, по которым его выбирают для VPS под WordPress.
Бесплатно и признаётся всеми браузерами. Сертификат типа Domain Validated обычно выпускается быстро и подходит для блогов, корпоративных сайтов, WooCommerce. Для большинства обычных сайтов DV-сертификата достаточно; платные сертификаты могут использоваться при дополнительных организационных или коммерческих требованиях — например, когда нужен OV/EV или особые условия поддержки.
Автоматизация из коробки. Certbot умеет получить сертификат и, при использовании плагина --nginx, автоматически настроить Nginx: добавит блок listen 443 ssl и редирект с 80 на 443.
Короткий срок — стимул к автоматизации. На 21 августа 2026 года стандартный профиль Let's Encrypt по-прежнему выдаёт сертификаты на 90 дней. Короткий срок — осознанное решение: чаще обновлять ключи и поощрять автоматизацию. Это текущее состояние; далее запланированы будущие изменения: 10 февраля 2027 года default classic profile должен перейти на 64 дня, 16 февраля 2028 года — на 45 дней, а отраслевое ограничение 47 дней вступает 15 марта 2029 года. Для владельца VPS это означает одно: настраивать нужно именно автопродление, а не ручное обновление.
Что проверить до установки
Четыре условия. Без них выпуск упадёт с ошибкой Failed to verify domain или Timeout during connect.
- Домен указывает на IP VPS. Команда
dig +short example.ruдолжна вернуть IP именно вашего сервера. Дождитесь обновления DNS после изменения A-записи. Проверка:curl -I http://example.ruдолжен отвечать с вашего сервера, а не с парковки регистратора. Если у домена есть AAAA-запись, убедитесь, что IPv6 на VPS реально настроен и Nginx доступен по IPv6. Частая ошибка — AAAA указывает на сервер, но firewall или Nginx слушает только IPv4, и HTTP-01-проверка не проходит. - Nginx уже отвечает на порту 80. Конфиг сайта должен быть подключён и проверяться без ошибок:
sudo nginx -t—syntax is ok,sudo systemctl status nginx—active. Расположение файла не принципиально: на Debian/Ubuntu традиционно используется/etc/nginx/sites-available/example.ruс симлинком вsites-enabled, на других сборках —/etc/nginx/conf.d/example.ru.conf. Важно, чтобы в активном блокеserver { server_name example.ru www.example.ru; }были именно те имена, для которых выпускаете сертификат. - Порты 80 и 443 доступны извне. Проверьте локальный firewall (
sudo ufw status,sudo iptables -L) и внешний firewall / security group в панели вашего VPS-провайдера. Для HTTP-01-проверки Let's Encrypt должен иметь возможность установить соединение на TCP 80. Для DNS-01 входящее соединение на 80 не требуется, но для типичного сайта на Nginx проще и надёжнее держать 80 открытым и настроенным на редирект. - CAA-записи. Если для домена заданы CAA-записи, они должны разрешать выпуск Let's Encrypt. При отсутствии CAA-записей ограничений нет. Ошибка в DNS, связанная с CAA (например, некорректный синтаксис или недоступность DNS для проверки CAA), также может привести к отказу выпуска. Проверка:
dig CAA example.ru. Если записи существуют, убедитесь, что среди них есть разрешение дляletsencrypt.orgили отсутствует запрет.
sudo не нужен. Не устанавливайте Certbot одновременно через snap и через apt — две параллельные установки приводят к запуску не той версии.Шаг 1 — Установка Certbot
Официальная рекомендация EFF — установка через snap, потому что snap всегда содержит свежую версию Certbot с актуальными профилями Nginx. Инструкцию для своей системы можно проверить на https://certbot.eff.org/instructions.
Если на сервере уже установлен Certbot из пакетов ОС, удалите его перед установкой snap, чтобы не конфликтовали две версии:
sudo apt-get remove certbot
Затем установите Certbot через snap:
sudo apt update
sudo apt install snapd -y
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --version
Путь /usr/local/bin/certbot используется в актуальной официальной инструкции — именно его предлагает создать Certbot после установки snap. Проверьте, что команда находится: which certbot должен указывать на snap-версию. Если вы предпочитаете установку из пакетов дистрибутива (sudo apt install certbot python3-certbot-nginx), используйте только её и не смешивайте с snap. Пакеты из apt на LTS-дистрибутивах могут отставать по версии, но функционально также выпускают и продлевают сертификаты.
Шаг 2 — Выпуск сертификата
Два рабочих сценария. Выберите один под свою конфигурацию.
Сценарий 1 — плагин Nginx (получение + установка). Подходит, когда сайт уже открывается по HTTP и вы хотите, чтобы Certbot сам настроил HTTPS. Плагин выполняет HTTP-01-проверку и правит конфиг Nginx.
sudo certbot --nginx -d example.ru -d www.example.ru
Certbot спросит email для уведомлений об истечении и согласие с условиями. Для неинтерактивного запуска добавьте --agree-tos -m admin@example.ru --redirect --non-interactive. После успешного выпуска сертификаты появятся в /etc/letsencrypt/live/example.ru/: fullchain.pem и privkey.pem. В конфиге Nginx появится секция с этими путями и редирект. Проверьте и перезагрузите:
sudo nginx -t
sudo systemctl reload nginx
Если хотите только получить сертификат, не меняя конфиг Nginx автоматически, используйте:
sudo certbot certonly --nginx -d example.ru -d www.example.ru
Сценарий 2 — webroot (только получение, без правки конфига). Полезен при кастомной структуре Nginx, когда вы не хотите, чтобы Certbot трогал конфиг. Укажите корень сайта — каталог, из которого Nginx отдаёт файлы:
sudo certbot certonly --webroot -w /var/www/example.ru -d example.ru -d www.example.ru
После этого пропишите пути к сертификатам в конфиге Nginx вручную и выполните sudo nginx -t && sudo systemctl reload nginx.
Тестовая проверка до боевого выпуска:
sudo certbot --nginx -d example.ru --dry-run
Флаг --dry-run тестирует процедуру renewal через staging/test ACME-окружение: реальные сертификаты не сохраняются. Успешный тестовый прогон показывает, что текущая конфигурация может пройти продление, но не гарантирует будущего продления — DNS, firewall, конфигурация Nginx и окружение могут измениться.
*.example.ru не подойдёт. Для DNS-01 требуется плагин, который умеет создавать TXT-запись _acme-challenge через API вашего DNS-провайдера, либо ручной режим --manual --preferred-challenges dns с ручным созданием TXT. Не используйте названия плагинов наугад — проверьте список официально поддерживаемых DNS-плагинов в документации Certbot и ставьте только тот, который соответствует вашему DNS-провайдеру. Для одного сайта WordPress wildcard чаще избыточен — достаточно перечислить конкретные имена example.ru и www.example.ru.Шаг 3 — Проверка Nginx и HTTPS
После выпуска убедитесь, что сервер отдаёт сертификат, а WordPress работает по HTTPS без mixed content.
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
TLS-проверка и HTTP-проверка — две разные вещи. Проверяйте их отдельно:
curl -I http://example.ru
curl -I https://example.ru
Для детальной диагностики TLS можно добавить curl -Iv https://example.ru — он покажет результат хендшейка (SSL certificate verify ok) и заголовки ответа. Сайт может легитимно отвечать не 200, а 301, 302, 403 или 404 в зависимости от настроек — это не признак проблемы с сертификатом. Отдельно убедитесь, что http:// делает редирект на https:// (ожидаем 301 на https://).
Если сайт на WordPress:
- Задайте
https://в адресахsiteurlиhome(Настройки — Общие). Если WordPress уже корректно настроен на HTTPS, отдельный массовый search-replace может не потребоваться. Когда замена нужна, делайте её через WP-CLI, предварительно сделав бэкап базы. WP-CLI корректно обрабатывает сериализованные данные, но команда должна соответствовать вашему сайту — не запускайте замену вслепую:
wp db export ~/backup-$(date +%F).sql
wp search-replace 'http://example.ru' 'https://example.ru' --all-tables --precise --recurse-objects
- Проверьте mixed content: откройте консоль браузера, ищите предупреждения
Mixed Content. Если есть — найдите в контенте и теме оставшиесяhttp://и замените наhttps://. - Если сайт работает за обратным прокси (например, Cloudflare), Nginx и WordPress могут видеть входящий запрос как HTTP. Редирект нужно настраивать осознанно: Nginx должен определять исходный протокол по заголовкам, которым вы доверяете. Не устанавливайте
$_SERVER['HTTPS'] = 'on'только по факту наличия произвольного заголовка без проверки, что запрос действительно пришёл от доверенного прокси. Корректный пример зависит от вашей схемы проксирования — сверьте его с документацией вашего CDN/прокси и WordPress.
Шаг 4 — Автопродление
Certbot регулярно запускает проверку командой certbot renew, а решение — нужно ли обновлять конкретный сертификат — принимает сам Certbot на основе оставшегося срока жизни. Certbot обычно устанавливается вместе с cron-задачей или systemd-таймером, который периодически запускает renew.
Логика Certbot 4.x и новее: для сертификатов обычной длительности обновление начинается, когда остаётся менее 1/3 от общего срока жизни. Для короткоживущих сертификатов сроком 10 дней и менее — менее 1/2 срока. Для текущего 90-дневного сертификата это примерно 30 дней до окончания. Так как проверка безопасно пропускает сертификаты, которым ещё рано обновляться, команду renew можно запускать ежедневно — обновление произойдёт только когда сертификат готов к renewal.
Let's Encrypt поддерживает ACME Renewal Information (ARI) — механизм, при котором CA сообщает клиенту рекомендуемое окно для продления. Продления, скоординированные через ARI, освобождены от всех rate limits.
Как понять, настроена ли автоматика:
systemctl list-timers
cat /etc/crontab
ls /etc/cron.*/*
Большинство современных установок Certbot уже содержат cron-задачу или systemd-таймер, который дважды в сутки запускает certbot renew. Точное имя таймера зависит от способа установки и версии — не полагайтесь на одно конкретное имя. Универсальный способ проверки — systemctl list-timers и поиск строки с certbot. Инструкции для вашей системы и метода установки опубликованы на https://certbot.eff.org/instructions.
Ручная проверка логики продления:
sudo certbot renew --dry-run
Команда тестирует процедуру продления через staging-окружение: если текущая конфигурация может пройти тестовое продление, вы увидите The dry run was successful. Это не абсолютная гарантия будущего продления — DNS, firewall, конфигурация Nginx и окружение могут измениться, поэтому исправляйте ошибки сейчас, а не за день до истечения.
Когда нужен deploy hook для перезагрузки Nginx:
Команда sudo certbot --nginx выполняет получение и установку сертификата через Nginx-плагин. Если вы получали сертификат способом, который не выполняет установку/перезагрузку Nginx (например, certonly --webroot или другой certonly), после обновления сертификата нужно обеспечить перезагрузку веб-сервера, чтобы он подхватил новые файлы из /etc/letsencrypt/live/.
Штатный способ — использовать каталог deploy-хуков. Любой исполняемый файл в /etc/letsencrypt/renewal-hooks/deploy/ запускается после успешного продления:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh >/dev/null <<'SH'
#!/bin/sh
systemctl reload nginx
SH
sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Проверить, что хуки будут запущены при реальном продлении, можно командой с флагом --run-deploy-hooks. Учтите: при обычном --dry-run deploy-хуки по умолчанию не выполняются, поэтому отдельная проверка хука требует этого флага:
sudo certbot renew --dry-run --run-deploy-hooks
Не редактируйте напрямую файлы в /etc/letsencrypt/renewal/*.conf как основной способ настройки хуков — ручная правка легко ломает возможность продления.
sudo openssl x509 -in /etc/letsencrypt/live/example.ru/fullchain.pem -noout -dates — поле notAfter должно сдвинуться. Логи Certbot — в /var/log/letsencrypt/letsencrypt.log, статус таймера — через systemctl list-timers и journalctl -u <timer>.Проверка результата
Четыре проверки после настройки. Выполняйте их с сервера или с локальной машины.
sudo openssl x509 -in /etc/letsencrypt/live/example.ru/fullchain.pem -noout -dates -issuer
echo | openssl s_client -connect example.ru:443 -servername example.ru 2>/dev/null | openssl x509 -noout -dates -issuer -fingerprint -sha256
curl -I https://example.ru
sudo nginx -T 2>&1 | grep -A2 ssl_certificate
Ожидаем:
- Локальный файл
fullchain.pemсодержит актуальныеnotBeforeиnotAfter(примерно +90 дней от выпуска для текущего стандартного профиля). - Сервер отдаёт сертификат: проверьте локальный файл и то, что реально отдаёт Nginx, раздельно. Для строгого сопоставления используйте fingerprint (
-fingerprint -sha256) или сравнивайте серийный номер — простое совпадение дат и issuer не доказывает, что Nginx использует именно файл изlive/. Конкретный промежуточный CA может меняться — не проверяйте жёстко строку вродеR11илиE6. curl -I https://example.ruвозвращает ожидаемый для вашего сайта HTTP-статус (не обязательно200— редирект или страница может отвечать иначе).nginx -Tпоказывает пути к/etc/letsencrypt/live/в активных server-блоках.
Дополнительная внешняя проверка — например, тест на https://www.ssllabs.com/ssltest/ — полезна как диагностический инструмент, но не является обязательным критерием «правильной» установки. Оценка SSL Labs зависит от множества настроек TLS в Nginx, а не только от наличия сертификата Let's Encrypt. Для базовой проверки достаточно локальных команд и браузера (замок без предупреждений).
Когда способ не сработает
Четыре типовых сценария, когда выпуск или продление падает.
1. Порт 80 недоступен или закрыт. Симптом: Timeout during connect (likely firewall problem) или Connection refused. HTTP-01-проверка использует TCP 80. Проверьте локальный firewall и внешний firewall / security group провайдера. Для обычного сайта на Nginx разумный подход — держать 80 открытым и настроить редирект return 301 https://$host$request_uri;. Важный нюанс: не каждое автоматическое продление обязательно выполняет новую полную HTTP-01-проверку — авторизации могут переиспользоваться в течение ограниченного времени, а DNS-01 вообще не требует входящего соединения на 80. Но рассчитывать на переиспользование не стоит — держите проверку через 80 работоспособной.
2. Прокси или CDN перед сервером (например, Cloudflare). Симптом: ошибка проверки или 403 от промежуточного узла. HTTP-01 может работать через CDN/proxy при корректной конфигурации — IP сервера должен быть достижим для проверки, а правила firewall/CDN не должны блокировать путь /.well-known/acme-challenge/. Переключение записи в режим "DNS only" (серое облако) не является обязательным — это один из вариантов диагностики. Альтернатива — перейти на DNS-01. Режим Cloudflare SSL Full (strict) сам по себе не «чинит» циклы редиректов — петля чаще возникает из-за того, как Nginx и WordPress определяют, что исходный запрос был HTTPS, когда TLS терминируется на прокси.
3. Wildcard или много имён без DNS-01. Попытка выпустить *.example.ru через HTTP-01 закончится ошибкой — wildcard требует DNS-01. Решение — использовать DNS-плагин для вашего провайдера либо выпускать только конкретные имена: sudo certbot --nginx -d example.ru -d www.example.ru -d shop.example.ru.
4. Лимиты Let's Encrypt. Симптом: too many certificates already issued for "example.ru" или too many certificates (5) already issued for exact set .... На 21 августа 2026 года для обычных сайтов актуальны два лимита: New Certificates per Registered Domain — до 50 новых сертификатов на один registered domain (например, example.ru) за 7 дней (пополнение bucket — 1 сертификат за 202 минуты) и New Certificates per Exact Set of Identifiers — до 5 сертификатов на точный набор имён за 7 дней. Продление без ARI (non-ARI renewal) освобождается от лимита New Certificates per Registered Domain, но остаётся под лимитом на exact set и под лимитом на ошибки авторизации; продления, скоординированные через ARI, освобождены от всех rate limits. Лимиты считаются глобально, независимо от аккаунта. Для тестирования используйте staging-окружение — например, --dry-run или для отдельного тестового сертификата --test-cert (получает тестовый сертификат staging, не подходит для реального сайта).
/etc/letsencrypt/, — но для стандартного сценария он не нужен и усложняет процесс.Частые вопросы
return 301 https://$host$request_uri;. DNS-01 не требует входящего 80, а авторизации могут некоторое время переиспользоваться, поэтому формально не каждая попытка продления приведёт к новому обращению на 80. Но рассчитывать на это как на постоянную схему не стоит.sudo certbot --nginx -d example.ru -d www.example.ru -d shop.example.ru. Получите один сертификат с перечисленными SAN. Стандартный профиль позволяет до 100 имён на один сертификат. Для разных проектов лучше выпускать отдельные сертификаты — проще управлять продлением и отзывом.sudo nginx -t — чаще всего ошибка в ручной правке после выпуска. Убедитесь, что файлы /etc/letsencrypt/options-ssl-nginx.conf и ssl-dhparams.pem на месте и доступны. Если вы правили конфиг вручную, сравните его с бэкапом. Для диагностики используйте sudo certbot certificates и логи /var/log/letsencrypt/letsencrypt.log. Переустановка Certbot — не универсальное решение и редко требуется.curl -I https://example.ru — убедитесь, что HTTPS отвечает корректно и видны актуальные даты сертификата. Если всё в порядке, убедитесь, что активный конфиг Nginx указывает на /etc/letsencrypt/live/. Старый сертификат можно оставить до окончательного перехода; удалять его необязательно. Если позже решите удалить — сначала убедитесь, что ни один активный конфиг Nginx на него не ссылается. При использовании панели хостинга сначала отключите её встроенное управление SSL, чтобы не было конфликта двух систем.Итог — держите на VPS связку Certbot + Nginx с настроенной регулярной проверкой продления. Она не зависит от панели и переживает перенос между провайдерами: меняются только DNS, firewall и структура конфига Nginx. Проверяйте продление командой sudo certbot renew --dry-run после каждого изменения.
Нужен HTTPS на VPS без сюрпризов?
Поставлю Let's Encrypt на Nginx, настрою редиректы, автопродление и проверю WordPress на mixed content.