Let's Encrypt на Nginx и IIS: выдача и продление без боли
Привет, я Евгений Семёнов, директор ITFresh. Знаете, за последние годы наша команда ITFresh внедрила 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-туннеле эта штука не шифрует ровным счётом ничего. А при реальных атаках, увы, она тоже не выручит. Именно поэтому мы, в ITFresh, за последние три года выдали нашим клиентам всего два «платных» сертификата. И знаете почему? Оба раза это были просто обязательные требования из тендерной документации — ну, обычная бумажная волокита, и ничего более.
Эти 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;
}
Теперь важно: сначала проверим синтаксис, а потом аккуратно перезагрузим Nginx. Только так, чтобы без разрыва текущих соединений!
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-чек срока действия сертификата. Если до окончания остаётся две недели, мне сразу же прилетает алерт — прямо в 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.
