Let's Encrypt на Nginx и IIS: выдача и продление без боли
Семёнов Евгений Сергеевич, директор АйТи Фреш. За последние годы мы закрыли десятки корпоративных сайтов Let's Encrypt — от бухгалтерских кабинетов на Debian до RDS Gateway-шлюзов на Windows Server. И каждый раз первый вопрос клиента одинаков: «А точно бесплатно и нормально?». Точно. Ниже — как мы это делаем у себя в практике, без плагиата с официальных гайдов: Certbot для Nginx, win-acme для IIS, wildcard-сертификаты, автопродление и два-три сценария, когда всё ломается.
Почему DV-сертификата от Let's Encrypt достаточно 90% офисов
На корпоративном сайте ООО «Ромашка» клиенту не нужен EV-сертификат с зелёной строкой — её в современных браузерах вообще больше нет. Нужен валидный TLS, который не вызывает красного замка. Let's Encrypt даёт ровно это: RSA 2048 или ECDSA P-256, цепочка через ISRG Root X1, поддержка TLS 1.2/1.3. Браузерами принимается без единого щелчка.
Я всегда объясняю заказчикам так: платный сертификат за 18 000 рублей в год отличается от бесплатного Let's Encrypt одной графой в свойствах — «Organization Validation». В HTTPS-туннеле она ничего не шифрует. В реальных атаках она тоже не помогает. Поэтому за последние три года мы выпустили клиентских «платных» сертификатов ровно два — оба были требованиями тендерной документации, чисто бумажная формальность.
Короткий срок в 90 дней — не баг, а фича. Если ключ утёк, злоумышленник получит максимум три месяца окна. Крупные CA тоже двигаются в эту сторону: CA/Browser Forum уже голосует за сокращение сроков и для платных сертификатов.
Certbot на Ubuntu для Nginx: быстрый путь
На чистой Ubuntu 22.04 или Debian 12 я всегда ставлю Certbot из snap. Пакет в apt отстаёт на версии и лечение ошибок через него — лотерея.
sudo apt remove certbot python3-certbot* -y
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
certbot --version
Дальше — одна команда и Nginx уже говорит по HTTPS.
sudo certbot --nginx -d crm.example.ru -d www.crm.example.ru \
--email admin@example.ru --agree-tos --redirect --non-interactive
Флаг --redirect добавит серверный блок return 301 https://... в конфиг — HTTP сразу перекидывается на HTTPS. Это экономит десять минут на ручной правке.
Файлы сертификата лежат в /etc/letsencrypt/live/crm.example.ru/. Для упрощённой поддержки я советую ссылаться именно на fullchain.pem и privkey.pem — это симлинки, которые Certbot автоматически перецепляет на новые файлы при каждом продлении.
Боевой конфиг Nginx с A+ на SSL Labs
Автоматический конфиг Certbot — это база. Для продакшена я всегда переписываю его вручную, чтобы выжать A+ на ssllabs.com. Вот рабочий шаблон, который у нас на восьми серверах Dell Xeon Platinum 8280 в дата-центре МТС отдаёт сотни сайтов клиентов.
server {
listen 80;
server_name crm.example.ru www.crm.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name crm.example.ru www.crm.example.ru;
ssl_certificate /etc/letsencrypt/live/crm.example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/crm.example.ru/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/crm.example.ru/chain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
root /var/www/crm.example.ru;
}
Проверяем синтаксис и мягко перезагружаем — без разрыва соединений.
sudo nginx -t && sudo systemctl reload nginx
Автопродление: systemd-таймер и хуки
Snap-версия Certbot ставит systemd-таймер автоматически, проверять его так:
sudo systemctl list-timers | grep certbot
sudo certbot renew --dry-run
Главное — добавить deploy-хук для перезагрузки Nginx. Без него новый сертификат появится в папке, а веб-сервер продолжит отдавать старый.
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh <<'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
В моей практике именно забытый хук — самая частая причина внезапной «протухшей HTTPS» через четыре месяца после настройки.
Wildcard и DNS-01: когда поддоменов много
Один клиент — сеть салонов оптики, 14 городов, 14 поддоменов spb.lenses.ru, kzn.lenses.ru и так далее. Ставить 14 сертификатов — больно. Выпускаем один *.lenses.ru через DNS-01.
sudo certbot certonly --manual \
--preferred-challenges dns \
-d lenses.ru -d '*.lenses.ru' \
--agree-tos -m admin@lenses.ru
Certbot печатает TXT-запись, её нужно руками прописать в DNS-зоне. Но для продакшена ручной режим не годится — продление всё равно потребует человека. Ставим DNS-плагин, если провайдер поддерживает API. Для Cloudflare:
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d lenses.ru -d '*.lenses.ru'
win-acme на IIS: привычный инструмент Windows-админа
На Windows Server стандарт — утилита win-acme (раньше называлась letsencrypt-win-simple). Лежит на win-acme.com, качаем zip, распаковываем в C:\tools\win-acme\. Запускаем от Administrator.
C:\tools\win-acme\wacs.exe
Мастер пошаговый: N — новый сертификат, 1 — Single binding of an IIS site, выбираем сайт, подтверждаем. Win-acme сам поднимет HTTP-01-валидацию в папке сайта, получит сертификат, импортирует в хранилище WebHosting и перепривяжет binding. Плюс создаст задание в Task Scheduler: win-acme renew (acme-v02.api.letsencrypt.org), которое запускается ежедневно.
| Параметр | Nginx + Certbot | IIS + win-acme |
|---|---|---|
| Расположение сертификатов | /etc/letsencrypt/live/ | C:\ProgramData\win-acme\…\Certificates\ |
| Планировщик | systemd timer (снап) | Task Scheduler |
| Хуки после продления | renewal-hooks/deploy/ | Installation steps → Scripts |
| Поддержка wildcard | да, через DNS-плагин | да, через скрипты DNS |
| Интеграция с ОС | файлы + symlink | Windows Cert Store |
Реальный кейс: юридическая фирма, 11 сайтов и RDS-шлюз
Весной 2025 года мы забирали на поддержку юрфирму в Москве — 11 поддоменов (www, cabinet, mail, portal, docs и другие), все в одном домене, плюс Remote Desktop Gateway для 27 юристов на удалёнке. До нас коллеги каждый квартал вручную покупали и ставили сертификаты от платного CA — общая стоимость на сайте 52 000 руб/год и ещё 11 000 руб/год на RDS.
За полтора рабочих дня мы развернули: один wildcard *.lawfirm.ru через Cloudflare API, отдельный сертификат на RDS Gateway и скрипт PowerShell, который после продления автоматически перецепляет thumbprint к RDS. В результате — 63 000 рублей годовой экономии, ноль ручных операций и никаких «а у нас опять красный замок» по понедельникам. Скрипт для RDS ниже.
# ImportRDGateway_Cert.ps1 — цепляет свежий cert к RD Gateway
$site = "Default Web Site"
$bind = Get-WebBinding -Name $site -Protocol "https"
$cert = Get-ChildItem Cert:\LocalMachine\WebHosting |
Where-Object { $_.Thumbprint -eq $bind.certificateHash }
Import-Module RemoteDesktopServices
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $cert.Thumbprint
Restart-Service TSGateway
Скрипт вызывается из win-acme как post-install. Перезапуск TSGateway рвёт RDP-сессии — ставим задание на 03:40 в ночь с воскресенья на понедельник.
Грабли, на которые я наступал лично
- Порт 80 закрыт файрволом «чтобы безопасно». HTTP-01 валидация летит. Либо пробросьте 80/tcp, либо переходите на DNS-01. Проверка:
curl -I http://yoursite/.well-known/acme-challenge/test. - Rate limit 50 сертификатов в неделю на домен. Если отлаживаетесь — используйте
--staging, это отдельный тестовый CA с почти бесконечными лимитами, но без реального доверия браузером. - Сертификат продлился, но сервис отдаёт старый. Значит, забыт deploy-хук. Проверьте:
openssl s_client -connect host:443 < /dev/null 2>/dev/null | openssl x509 -noout -dates. - Certbot ругается на DNS A-запись. Зонтик CDN или DNSSEC сломан на стороне провайдера. Попросите отдел DNS временно отключить CNAME flatten.
- В win-acme исчезли привязки после IIS-обновления. Так бывает после накатов апдейтов Windows Server 2019 → 2022. Запустите
wacs.exe --renew --force— win-acme перевыпустит и заново привяжет. - HSTS включён, а сертификат протух. Браузер показывает жёсткую ошибку без «Продолжить». Урок: включайте HSTS только когда уверены, что автопродление работает хотя бы один цикл.
Мониторинг: узнать о проблеме раньше, чем клиент
У меня в LibreNMS на каждом клиентском сервере настроен SNMP-чек срока действия сертификата. Алерт за 14 дней — в Telegram. Минимальный вариант для тех, у кого нет NMS — shell-скрипт в cron:
#!/bin/bash
for host in crm.example.ru portal.example.ru; do
end=$(echo | openssl s_client -servername $host -connect $host:443 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 ))
[ $days -lt 14 ] && echo "WARN: $host истекает через $days дней"
done
Скрипт запускается утром раз в сутки и пишет в лог-файл. Всё, что там появилось — повод зайти и разобраться до того, как клиент позвонит.
Поставим SSL на весь ваш зоопарк сервисов
Закроем Let's Encrypt всё, что говорит по HTTPS: Nginx, Apache, IIS, RDS Gateway, почтовики, 1С-Битрикс, WireGuard UI. С автопродлением, мониторингом, хукам перезапуска сервисов и A+ на SSL Labs. Работаем в Москве и удалённо, стандартный срок внедрения — 1–3 рабочих дня.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — Let's Encrypt в корпоративной среде
- Подходит ли Let's Encrypt для корпоративного сайта и интернет-магазина?
- Да. DV-сертификат Let's Encrypt криптографически не отличается от платного — тот же RSA/ECDSA, та же длина ключа. Разница только в валидации организации (OV/EV), которая для обычного сайта роли не играет.
- Почему срок жизни сертификата — 90 дней?
- Короткий срок заставляет автоматизировать процесс, а также ограничивает ущерб при утечке приватного ключа. С Certbot и win-acme всё продлевается по таймеру, без участия человека.
- Как получить wildcard на *.company.ru?
- Только через DNS-01: Let's Encrypt проверяет TXT-запись _acme-challenge.company.ru. Для автоматизации ставится DNS-плагин (cloudflare, route53, регрулир и другие) — тогда certbot сам создаёт и удаляет записи при каждом продлении.
- Что делать, если у меня IIS за NAT без прямого 80-го порта?
- Либо пробросить 80/tcp до IIS только на время валидации, либо полностью перейти на DNS-01 — тогда входящий трафик вообще не нужен, достаточно API DNS-провайдера.
- Можно ли поставить один сертификат сразу на несколько поддоменов?
- Да, SAN-сертификат в Let's Encrypt поддерживает до 100 имён в одном сертификате. Для Certbot — просто перечислите -d name1 -d name2; для win-acme — выберите несколько сайтов на шаге bindings.