Руководства

SSL на VPS: бесплатный сертификат Let's Encrypt за 10 минут

SSL на VPS: бесплатный сертификат Let's Encrypt за 10 минут

На хостинге HTTPS включался галочкой в панели. На VPS сертификат нужно выпустить самому, но платить за него не придётся. Let's Encrypt бесплатно выдаёт сертификаты, которым доверяют все браузеры, а утилита certbot делает всё за одну команду и сама продлевает сертификат. Ниже: что подготовить, как выпустить сертификат для Nginx и Apache, как не пропустить продление и что делать, если что-то пошло не так.

Что проверить до выпуска

Let's Encrypt выдаёт сертификат, только убедившись, что домен действительно ваш: он обращается к домену по HTTP и ищет на сервере проверочный файл. Поэтому до запуска certbot должны выполняться три условия.

1. Домен указывает на сервер. С любой машины:

dig +short example.com A
dig +short www.example.com A
dig +short example.com AAAA

Первые две команды должны вернуть IP вашего VPS. Третья — либо IPv6 этого же сервера, либо ничего. Частая ловушка: у домена осталась AAAA-запись на старый хостинг, Let's Encrypt проверяет по IPv6 и не находит файл. Удалите лишнюю запись или пропишите IPv6 нового сервера.

Если домен только что перенесли, подождите, пока обновятся DNS: обычно это минуты, но может занять до нескольких часов.

2. Порты 80 и 443 открыты. Если включён ufw:

ufw allow 80/tcp
ufw allow 443/tcp

Порт 80 нужен и после выпуска: через него проходит проверка при каждом продлении. Закрывать его «ради безопасности» нельзя — достаточно перенаправлять с него на HTTPS.

3. Сайт описан в Nginx. В конфигурации сайта должна быть строка server_name example.com www.example.com;. По ней certbot найдёт, куда вписать сертификат. Как поднять Nginx и PHP с нуля — в статье «Как перенести сайт с хостинга на VPS».

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

Установка на Debian и Ubuntu:

apt update
apt install certbot python3-certbot-nginx

Выпуск сразу на оба имени — с www и без:

certbot --nginx --redirect -d example.com -d www.example.com

При первом запуске certbot спросит email и попросит принять условия. Дальше он сам:

  • подтвердит владение доменом;
  • получит сертификат и сохранит его в /etc/letsencrypt/live/example.com/;
  • допишет в конфигурацию Nginx блок на 443 порт с путями к сертификату;
  • благодаря флагу --redirect настроит перенаправление всех запросов с HTTP на HTTPS;
  • перезагрузит Nginx.

Обычно на всё уходит меньше минуты. Откройте сайт: в адресной строке должен быть замок.

Apache

То же самое, только плагин другой:

apt install certbot python3-certbot-apache
certbot --apache --redirect -d example.com -d www.example.com

Если сайт в Docker или на нестандартном сервере

Когда certbot не может сам править конфигурацию (Node.js, Caddy в контейнере, свой прокси), используйте режим, в котором он только получает сертификат:

certbot certonly --webroot -w /var/www/example -d example.com -d www.example.com

Здесь /var/www/example — папка, из которой веб-сервер отдаёт файлы по адресу http://example.com/.well-known/acme-challenge/. Пути к готовым файлам fullchain.pem и privkey.pem пропишите в конфигурацию сами.

Если веб-сервера нет совсем, есть режим --standalone. Certbot сам поднимет временный сервер на 80 порту, поэтому порт в этот момент должен быть свободен.

Если стоит панель

В ISPmanager, HestiaCP, aaPanel и других панелях Let's Encrypt выпускается кнопкой в настройках сайта, и продлением тоже занимается панель. Certbot вручную ставить не нужно, а смешивать два способа на одном домене не стоит. Чем панель отличается от работы в консоли — в статье «Панель управления или консоль».

Wildcard: один сертификат на все поддомены

Сертификат вида *.example.com покрывает shop.example.com, api.example.com и любые другие поддомены. Он нужен, когда поддомены создаются автоматически, например по одному на клиента. Если поддоменов три-четыре, проще перечислить их через -d в обычном сертификате.

Проверка у wildcard другая: через TXT-запись в DNS, а не через файл на сайте. Вручную это делается так:

certbot certonly --manual --preferred-challenges dns -d example.com -d '*.example.com'

Но вручную выпущенный сертификат сам не продлится: через несколько месяцев придётся снова добавлять TXT-запись. Для автоматики нужен DNS-плагин под вашего DNS-провайдера, например python3-certbot-dns-cloudflare. Он сам создаёт и удаляет запись через API.

Автопродление: настроить и проверить

Сертификат Let's Encrypt сейчас действует 90 дней, и срок будет сокращаться. С 10 февраля 2027 года он составит 64 дня, с 16 февраля 2028 года — 45 дней. Продлевать вручную при таких сроках нереально, поэтому продление должно работать без вас.

Пакет certbot в Debian и Ubuntu сам ставит таймер, который дважды в сутки проверяет сертификаты и продлевает те, срок которых подходит к концу. Убедитесь, что он есть:

systemctl list-timers | grep certbot

И прогоните пробное продление — оно ничего не меняет, но проходит все проверки:

certbot renew --dry-run

Если пробное продление проходит, настоящее тоже пройдёт.

Перезагрузка после продления. При выпуске через --nginx или --apache certbot перезагружает веб-сервер сам. При --webroot и --standalone он только кладёт новые файлы на диск, а Nginx продолжает отдавать старый сертификат из памяти, пока тот не истечёт. Добавьте хук:

cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh <<'EOF'
#!/bin/sh
systemctl reload nginx
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Скрипты из этой папки запускаются после каждого успешного продления. Если сертификат используют и другие службы, например почтовый сервер, их перезагрузку тоже добавьте сюда.

Уведомлений об истечении больше нет

Раньше Let's Encrypt присылал письмо, если сертификат скоро истекает. С 4 июня 2025 года эта рассылка отключена. Если продление тихо сломалось, узнаете вы об этом от посетителей, которые увидят предупреждение браузера.

Поэтому срок сертификата нужно проверять самим. Вручную это выглядит так:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -enddate

А надёжнее — мониторинг с проверкой срока сертификата и уведомлением за 1–2 недели до окончания.

Проверка после настройки

Все четыре варианта адреса должны вести в одно место:

curl -sI http://example.com/      | grep -iE '^(HTTP|location)'
curl -sI http://www.example.com/  | grep -iE '^(HTTP|location)'
curl -sI https://www.example.com/ | grep -iE '^(HTTP|location)'
curl -sI https://example.com/     | head -1

Первые три должны отвечать 301 с location: https://example.com/, последний — 200. Если оба варианта, с www и без, отдают 200, поисковики увидят два одинаковых сайта. Выберите основной адрес и перенаправляйте второй на него.

Ещё две проверки:

  • Смешанное содержимое. Откройте страницу, затем консоль браузера (F12). Предупреждения Mixed Content значат, что картинки или скрипты всё ещё грузятся по http://. Обычно это абсолютные ссылки в базе после переезда. В WordPress их заменяет wp search-replace 'http://example.com' 'https://example.com' (сначала сделайте бэкап базы).
  • Качество настройки. Бесплатный тест SSL Labs (ssllabs.com/ssltest) покажет цепочку сертификатов, поддерживаемые протоколы и ошибки. С настройками certbot по умолчанию обычно получается оценка A.

После перехода на HTTPS можно включить HTTP/2: это ускоряет загрузку страниц с большим числом файлов. Как это сделать — в статье «Как ускорить сайт на VPS».

Типичные ошибки

Что пишет certbot или браузерПричинаЧто делать
Timeout during connectПорт 80 закрыт файрволомufw allow 80/tcp, проверить файрвол в панели провайдера
unauthorized, 404 на /.well-known/acme-challenge/Домен смотрит на другой сервер, мешает AAAA-запись или редирект в конфигурацииПроверить dig по A и AAAA, временно убрать свои редиректы с 80 порта
too many certificates already issuedСработал лимит Let's Encrypt на повторные выпуски для одного набора имёнПодождать (лимит недельный); эксперименты делать с --dry-run
Бесконечный редирект после включения HTTPSДомен за Cloudflare в режиме SSL «Flexible»В Cloudflare: SSL/TLS → Full (strict)
Браузер: сертификат выдан на другое имяНе все имена указаны в -d или запрос попал в чужой блок serverПеревыпустить со всеми именами: certbot --nginx -d ... --expand
Сайт открывается, но сертификат истёкПродление прошло, а Nginx не перезагруженХук из раздела выше и systemctl reload nginx

Несколько сайтов на одном сервере

Один VPS спокойно обслуживает десятки доменов. Для каждого заводится свой блок server и выпускается свой сертификат той же командой certbot. Различает сайты Nginx по имени, которое браузер передаёт при подключении.

Добавьте заглушку на случай, когда запрос пришёл на имя, которого нет в конфигурации. Без неё Nginx отдаст первый попавшийся сайт: посетитель, ошибившийся адресом, или чужой домен, направленный на ваш IP, будет показывать ваш проект.

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}

ssl_reject_handshake (Nginx 1.19.4 и новее) позволяет обойтись без сертификата для заглушки: соединение по HTTPS к неизвестному имени просто обрывается.

Когда нужен платный сертификат

Шифрует платный сертификат ровно так же, как бесплатный, а замок в браузере выглядит одинаково. Платить имеет смысл в трёх случаях:

  • сертификат с проверкой организации (OV или EV) требуют договор, тендер или банк-партнёр;
  • нужна финансовая гарантия от удостоверяющего центра;
  • сертификат ставится туда, где нельзя автоматизировать продление, а выпускать его вручную раз в два месяца неудобно.

Учтите, что срок у платных сертификатов тоже сокращается: с марта 2026 года сертификат выдаётся максимум на 200 дней, а не на год, как раньше. Ручная замена раз в год ушла в прошлое и для них.

Если платный сертификат всё же нужен, подобрать и заказать его можно в разделе SSL-сертификаты.

Ещё нет сервера

Для сайта с HTTPS особых требований к тарифу нет: certbot почти не потребляет ресурсов. Для сайта на CMS хватит Start (2 vCPU, 2 ГБ). Финляндия даёт самый быстрый отклик из России, Нидерланды подойдут, если аудитория по всей Европе.

Start в Финляндии — $10/мес   Start в Нидерландах — $10/мес

Цены указаны на момент публикации, оплата у провайдера. Подробнее о площадках: VPS в Финляндии, VPS в Нидерландах. Что ещё настроить на новом сервере, кроме сертификата, — в статье «Как настроить VPS после покупки».

Коротко

  • До выпуска проверьте, что A-запись (и AAAA, если есть) ведёт на сервер, а порты 80 и 443 открыты.
  • Выпуск для Nginx одной командой: certbot --nginx --redirect -d example.com -d www.example.com.
  • Проверьте автопродление через certbot renew --dry-run. Для режимов webroot и standalone добавьте хук перезагрузки.
  • Писем об истечении от Let's Encrypt больше нет, а срок сертификата будет сокращаться до 45 дней. Срок нужно отслеживать мониторингом.
  • Все варианты адреса должны вести на один HTTPS-адрес, без смешанного содержимого.
  • Платный сертификат нужен только для OV/EV, гарантий или там, где продление не автоматизировать.