· 15 мин чтения

Let's Encrypt на Nginx и IIS: выдача и продление без боли

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 + 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-чек срока действия сертификата. Если до окончания остаётся две недели, мне сразу же прилетает алерт — прямо в 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С, безболезненных миграций, надёжных резервных копий. И, конечно, только проверенные лайфхаки из наших реальных IT-проектов – всё, чтобы облегчить вашу работу!

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

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