Почему сертификат — это не опция

Если сайт работает по HTTP, Chrome показывает красный замок и надпись «Не защищено». Google понижает такие сайты в выдаче. Пользователи закрывают вкладку. Это не страшилка — это реальность 2026 года.

SSL-сертификат шифрует трафик между браузером и сервером. Без него данные передаются в открытом виде: логины, пароли, платёжные данные. Даже если у вас сайт-визитка без форм — сертификат всё равно нужен ради SEO и доверия.

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

Let's Encrypt — центр сертификации, который выдаёт SSL-сертификаты бесплатно. Запущен в 2016 году Mozilla, Cisco, EFF и рядом других организаций. Сегодня обслуживает более 300 миллионов сайтов.

Сертификаты выдаются на 90 дней. Это сделано специально — короткий срок мотивирует к автообновлению и снижает риски при компрометации ключа. Именно поэтому Let's Encrypt изначально проектировался под автоматизацию через протокол ACME.

Что важно знать:

  • Выдаётся Domain Validation (DV) — подтверждает только владение доменом
  • Wildcard-сертификаты (*.example.com) поддерживаются через DNS-01 challenge
  • Мультидоменные сертификаты (SAN) — до 100 доменов в одном
  • Не подходит для EV (Extended Validation) — если нужна строка с названием компании, придётся платить

Как работает выдача сертификата

Протокол ACME (Automatic Certificate Management Environment) — стандарт, по которому клиент на сервере договаривается с Let's Encrypt о выдаче сертификата. Процесс такой:

  1. Клиент (например, Certbot) отправляет запрос на сертификат для домена example.com
  2. Let's Encrypt отвечает: «Докажи, что домен твой»
  3. Клиент проходит challenge — HTTP-01 или DNS-01
  4. Let's Encrypt проверяет и выдаёт сертификат

HTTP-01 challenge — самый простой. Certbot создаёт файл по пути /.well-known/acme-challenge/токен, Let's Encrypt обращается к нему по HTTP. Работает только если сервер доступен из интернета на 80-м порту.

DNS-01 challenge — для wildcard и случаев, когда 80-й порт закрыт. Certbot добавляет TXT-запись _acme-challenge.example.com в DNS. Let's Encrypt проверяет запись. Занимает чуть больше времени из-за DNS propagation.

Устанавливаем Certbot

Certbot — официальный клиент Let's Encrypt. Поддерживает Nginx, Apache, standalone-режим.

На Ubuntu/Debian:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Получаем сертификат для Nginx:

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

Certbot сам найдёт конфиг Nginx, допишет нужные директивы и перезагрузит сервер. После этого в /etc/letsencrypt/live/example.com/ появятся файлы:

  • fullchain.pem — цепочка сертификатов
  • privkey.pem — приватный ключ
  • cert.pem — только сертификат (обычно не нужен отдельно)
  • chain.pem — промежуточные сертификаты

Настраиваем Nginx вручную

Если хочется контроля, а не «пусть Certbot всё сделает сам» — настраиваем конфиг руками. Получаем сертификат в standalone-режиме (Nginx при этом должен быть остановлен):

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

Конфиг Nginx:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=63072000" always;

    location / {
        root /var/www/example.com;
        index index.html;
    }
}

Несколько пояснений:

  • TLSv1.2 TLSv1.3 — TLS 1.0 и 1.1 давно устарели и небезопасны
  • ssl_session_cache — кешируем сессии, чтобы не делать полный handshake при каждом запросе
  • HSTS — говорим браузеру всегда использовать HTTPS; осторожно, после включения откатить сложно

Автообновление — самое важное

Let's Encrypt выдаёт сертификат на 90 дней. Certbot рекомендует обновлять за 30 дней до истечения. Если забыть — сайт начнёт показывать ошибку, и вы об этом узнаете от клиентов, а не от мониторинга.

Certbot при установке создаёт systemd-таймер или запись в cron. Проверить:

sudo systemctl list-timers | grep certbot

Стандартная запись в /etc/cron.d/certbot:

0 */12 * * * root certbot renew --quiet

Certbot проверяет сертификаты дважды в день и обновляет те, которым осталось менее 30 дней. Даже если одна проверка упадёт, следующая сработает через 12 часов.

Проверить, что автообновление работает:

sudo certbot renew --dry-run

Если всё хорошо, увидите:

Congratulations, all renewals succeeded.

Хук после обновления

После обновления сертификата Nginx нужно перезагрузить, иначе он продолжит отдавать старый. Создаём файл /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh:

#!/bin/bash
systemctl reload nginx

Делаем исполняемым:

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Теперь после каждого успешного обновления Nginx сам перезагрузится. Аналогично работает для Apache (systemctl reload apache2) и любого другого сервиса.

Wildcard-сертификат через DNS

Если нужен сертификат для *.example.com — только DNS-01 challenge. HTTP-01 для wildcard не работает.

sudo certbot certonly \
  --manual \
  --preferred-challenges dns \
  -d "*.example.com" \
  -d example.com

Certbot попросит добавить TXT-запись в DNS. Добавляете, ждёте распространения (обычно 1–5 минут, иногда до 30), подтверждаете.

Проблема ручного wildcard: при обновлении снова нужно вручную добавлять TXT-запись. Поэтому для wildcard лучше использовать DNS-плагины — они автоматически управляют записями через API регистратора. Плагины есть для большинства популярных провайдеров:

# Cloudflare
sudo apt install python3-certbot-dns-cloudflare

# DigitalOcean
sudo apt install python3-certbot-dns-digitalocean

Пример для Cloudflare — создаём /etc/letsencrypt/cloudflare.ini:

dns_cloudflare_api_token = ВАШ_API_ТОКЕН

Ограничиваем права и получаем сертификат:

sudo chmod 600 /etc/letsencrypt/cloudflare.ini

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "*.example.com" \
  -d example.com

Теперь автообновление полностью автоматическое — Certbot сам обновит TXT-запись через API.

acme.sh как альтернатива Certbot

acme.sh — легковесная альтернатива на bash. Не требует root, работает в cron пользователя, поддерживает десятки DNS-провайдеров.

Установка:

curl https://get.acme.sh | sh -s email=admin@example.com

Получение сертификата через Cloudflare DNS:

export CF_Token="ВАШ_ТОКЕН"
export CF_Account_ID="ВАШ_АККАУНТ"

~/.acme.sh/acme.sh --issue --dns dns_cf \
  -d example.com \
  -d "*.example.com"

Установка в Nginx:

~/.acme.sh/acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.pem \
  --reloadcmd "systemctl reload nginx"

acme.sh сам добавляет запись в cron и при обновлении выполняет reloadcmd.

Мониторинг сертификатов

Автообновление может сломаться — DNS-провайдер поменял API, кончилось место на диске, изменился IP сервера. Нужно следить за сроком действия.

Простейшая проверка через openssl:

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

Скрипт для ежедневного оповещения:

#!/bin/bash
DOMAIN="example.com"
DAYS_THRESHOLD=14

EXPIRY=$(echo | openssl s_client -connect $DOMAIN:443 2>/dev/null | \
  openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)

EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

if [ $DAYS_LEFT -lt $DAYS_THRESHOLD ]; then
  echo "ВНИМАНИЕ: сертификат $DOMAIN истекает через $DAYS_LEFT дней" | \
    mail -s "SSL alert: $DOMAIN" admin@example.com
fi

Из внешних сервисов — UptimeRobot умеет следить за сроком SSL-сертификатов и присылать уведомления. Бесплатный тариф покрывает базовые нужды.

Ограничения Let's Encrypt

Важно знать лимиты, чтобы не попасть в ситуацию, когда сертификат не выдаётся:

  • 50 сертификатов в неделю на один зарегистрированный домен
  • 5 дубликатов в неделю — если несколько раз запрашивать один и тот же набор доменов
  • 5 неудачных попыток в час для одного аккаунта и домена

На практике лимиты мешают только при массовой автоматизации или при ошибочном написании скрипта, который циклит запросы. Для тестирования используйте staging-окружение:

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

Staging выдаёт сертификаты без лимитов, но они не доверенные — браузер покажет предупреждение. Зато можно спокойно отлаживать автоматизацию.

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

Let's Encrypt закрывает 95% задач. Но бывают исключения:

EV-сертификат — Extended Validation. Раньше давал зелёную строку с названием компании. Chrome и Firefox убрали это визуальное отличие ещё в 2019–2020 годах. Сегодня нужен разве что для специфического корпоративного комплаенса.

OV-сертификат — Organization Validation. Подтверждает существование организации. Нужен для некоторых B2B-клиентов и государственных тендеров.

Сервер без доступа из интернета — если сервер в закрытом контуре и нет возможности настроить DNS-API, автообновление Let's Encrypt не сработает.

Для большинства проектов — корпоративных сайтов, интернет-магазинов, лендингов — Let's Encrypt полностью достаточен.

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

Забытый renewal-хук. Certbot обновил сертификат, но Nginx читает старый. Сайт работает, пока старый сертификат не истечёт — тогда всё сломается. Всегда настраивайте хук на reload.

80-й порт закрыт файрволом. HTTP-01 challenge не пройдёт. Либо откройте порт, либо используйте DNS-01.

Несоответствие доменов. Сертификат выдан для example.com, а Nginx настроен на www.example.com. Всегда запрашивайте сертификат для всех вариантов домена.

Права на файлы ключей. Приватный ключ должен быть доступен только root. Если что-то поменяли в правах на /etc/letsencrypt/ — Certbot может не смочь прочитать файлы при обновлении.

Staging-сертификат в проде. Если тестировали через --staging, перед переходом в прод удалите staging-сертификат и получите новый без флага.


В REEXY настройка SSL — один из первых шагов перед сдачей любого проекта. Даже простой сайт-визитка от 2 000 ₽ сдаётся с работающим HTTPS: это базовая гигиена, без которой выпускать сайт просто неприлично.

Автообновление через Certbot с правильными хуками и мониторингом срока — это то, что должно работать тихо годами. Один раз настроить правильно и забыть об этой задаче навсегда.