· 15 мин чтения

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 + CertbotIIS + win-acme
Расположение сертификатов/etc/letsencrypt/live/C:\ProgramData\win-acme\…\Certificates\
Планировщикsystemd timer (снап)Task Scheduler
Хуки после продленияrenewal-hooks/deploy/Installation steps → Scripts
Поддержка wildcardда, через DNS-плагинда, через скрипты DNS
Интеграция с ОСфайлы + symlinkWindows 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 в ночь с воскресенья на понедельник.

Грабли, на которые я наступал лично

Мониторинг: узнать о проблеме раньше, чем клиент

У меня в 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.

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.