SSL для простых смертных, или PunchSalad вам не нужен
Практический гайд: как выпустить бесплатный SSL-сертификат через Certbot, пройти ACME HTTP-проверку через .well-known и настроить продление без платного SSL-сервиса.

Почти у каждой хостинг-панели сейчас есть кнопка SSL, Let’s Encrypt или AutoSSL. Нажмите её. Если Cloudflare, cPanel, Plesk, ваш хостер или кто-то ещё уже сам продлевает сертификат, закрывайте статью и идите гулять. Вы победили.
Этот гайд для другого хостинга. Того, который продаёт SSL как платную опцию, выдаёт файловый менеджер из 2009 года и каким-то образом убеждает вас, что без PunchSalad замочек в браузере не выживет.
Выживет. PunchSalad проходит ту же ACME-проверку, которую Certbot делает бесплатно.
Совсем коротко: что такое SSL?
SSL — это старое название, которым все до сих пор называют TLS, шифрование, на котором работает HTTPS.
Когда браузер подключается, ваш сервер показывает ему сертификат, как паспорт на входе. Браузер проверяет три вещи: сертификат подписан центром сертификации, которому он доверяет, имя в нём совпадает с вашим доменом, и срок его действия не истёк. Если всё сходится, они договариваются о временных ключах и дальше общаются по старому доброму HTTP внутри зашифрованного туннеля.
Сертификат делает две полезные вещи:
- доказывает, что сервер, который отвечает за
example.com, действительно контролируетexample.com; - шифрует трафик между посетителем и этим сервером.
Он не доказывает, что владелец хороший человек, что сайт безопасен или что в установке WordPress нет плагина, который последний раз обновлялся при администрации Обамы.
Как работает ACME-проверка
Let’s Encrypt раздаёт сертификаты бесплатно, но сначала хочет убедиться, что домен ваш. ACME — это протокол, по которому идёт этот разговор.
На пещерном языке:
- Certbot просит у Let’s Encrypt сертификат для
example.com. - Let’s Encrypt говорит: положи этот странный текст в файл с этим странным именем.
- Вы кладёте его по адресу
http://example.com/.well-known/acme-challenge/WEIRD-NAME. - Let’s Encrypt скачивает файл и видит ожидаемый текст.
- Такое мог сделать только тот, кто управляет сайтом, поэтому сертификат выдаётся.
Certbot выдаёт вам файл:
Я всегда смотрю только в /.well-known/acme-challenge/. Каждый раз.
Это называется HTTP-01 challenge. Порт 80 должен быть доступен из интернета. Папка .well-known не магическая; это просто условленный шкафчик, в котором роботы, выдающие сертификаты, ищут доказательства.
Сначала попробуйте скучный автоматический вариант
Если у вас есть root-доступ и вы используете Nginx или Apache, Certbot сам пройдёт проверку, поправит конфиг веб-сервера и настроит продление:
sudo certbot --nginx
# orsudo certbot --apacheДля большинства серверов это правильный ответ. Один раз проверьте продление и больше не трогайте:
sudo certbot renew --dry-runБольшинство установок Certbot включают systemd-таймер или cron-задачу, которая запускает certbot renew. Вам не нужно помнить про сертификат и продлевать его раз в несколько месяцев. Компьютеры неплохо справляются с календарями.
Webroot, если хотите сами управлять конфигом
Иногда не хочется, чтобы Certbot лез в конфиг Nginx, или плагин веб-сервера просто не понимает вашу настройку. Плагин webroot доказывает владение доменом, записывая файл проверки в существующую папку сайта, без остановки сервера.
Допустим, сайт отдаётся из:
/var/www/example.com/publicУбедитесь, что Nginx отдаёт папку проверки по обычному HTTP:
server { listen 80; server_name example.com www.example.com; root /var/www/example.com/public;
location ^~ /.well-known/acme-challenge/ { default_type text/plain; try_files $uri =404; }
location / { return 301 https://$host$request_uri; }}Прежде чем связываться с сертификатами, проверьте шкафчик:
sudo mkdir -p /var/www/example.com/public/.well-known/acme-challengeecho works | sudo tee /var/www/example.com/public/.well-known/acme-challenge/testcurl http://example.com/.well-known/acme-challenge/testsudo rm /var/www/example.com/public/.well-known/acme-challenge/testЕсли curl напечатал works, запрашивайте сертификат:
sudo certbot certonly --webroot \ -w /var/www/example.com/public \ -d example.com \ -d www.example.comCertbot сохранит его здесь:
/etc/letsencrypt/live/example.com/fullchain.pem/etc/letsencrypt/live/example.com/privkey.pemУкажите эти файлы в HTTPS-сервере:
server { listen 443 ssl; server_name example.com www.example.com; root /var/www/example.com/public;
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;
# The rest of your site config goes here.}Потом проверьте конфиг и перезагрузите Nginx:
sudo nginx -tsudo systemctl reload nginxsudo certbot renew --dry-runПри продлении Certbot помнит, что вы использовали webroot, кладёт новую проверку в ту же папку, получает новый сертификат и подменяет файлы по этим путям. Но Nginx нужно перезагрузить, чтобы он заметил замену. Добавьте постоянный deploy-хук, который запускается только после успешного продления:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploysudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx >/dev/null <<'EOF'#!/bin/shsystemctl reload nginxEOFsudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
sudo certbot renew --dry-run --run-deploy-hooksдиск
- live/example.com/
- fullchain.pem
- privkey.pem
- archive/example.com/
- privkey1.pem
- fullchain1.pem
- privkey2.pem
- fullchain2.pem
истекает 2 дек. 2026 г.
память nginx
истекает 2 дек. 2026 г.
Больше 30 дней. Certbot проверил, пожал плечами, спит.
Совсем ручной способ для ужасного хостинга
Вот мы и добрались до сценария PunchSalad: сайт работает, но SSH-доступа нет, и кнопки Let’s Encrypt тоже нет. Вы всё равно можете запустить Certbot на другой Linux-машине и загрузить доказательство через FTP или файловый менеджер хостинга.
Другой Linux-машины тоже нет? Я сделал инструмент для SSL-сертификата, который ведёт тот же диалог прямо в браузере: выдаёт файлы (или DNS-записи), просит Let’s Encrypt их проверить и отдаёт сертификат, ключ и CA bundle. Шаги ниже это ровно то, что он делает за вас.
Запустите:
sudo certbot certonly --manual \ --preferred-challenges=http \ --agree-tos \ -m you@example.com \ -d example.com \ -d www.example.comCertbot покажет имя файла, его содержимое и URL примерно такого вида:
http://example.com/.well-known/acme-challenge/a1b2c3-weird-tokenПока не нажимайте Enter. В файловом менеджере хостинга:
- Откройте корневую папку сайта, обычно это
public_html. - Создайте в ней
.well-known. Папки с точкой в начале могут быть скрыты по умолчанию. - Создайте
acme-challengeвнутри.well-known. - Создайте ровно тот файл, который попросил Certbot, ровно с тем содержимым, которое он напечатал.
- Откройте URL в браузере или через
curlи убедитесь, что он возвращает только это значение. - Вернитесь в Certbot и нажмите Enter.
Если вы запросили и голый домен, и www, Certbot может попросить ещё одну проверку. Повторите всё заново. Каждое имя хоста должно указывать на этот хостинг-аккаунт и отдавать правильный файл.
После проверки Certbot выдаст вам такие файлы:
| Файл | Что это |
|---|---|
cert.pem | Сертификат вашего домена |
chain.pem | Промежуточные сертификаты центра сертификации |
fullchain.pem | cert.pem и chain.pem вместе |
privkey.pem | Ваш приватный ключ; никому его не давайте |
Панель хостинга может попросить отдельно Certificate, Private Key и CA Bundle. Дайте ей cert.pem, privkey.pem и chain.pem. Если она просит один файл с цепочкой сертификатов, используйте fullchain.pem.
live/example.com/
-----BEGIN CERTIFICATE-----
⋮ example.com
-----END CERTIFICATE----------BEGIN CERTIFICATE-----
⋮ Let's Encrypt
-----END CERTIFICATE----------BEGIN CERTIFICATE----- ⋮ example.com -----END CERTIFICATE----------BEGIN CERTIFICATE----- ⋮ Let's Encrypt -----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
⋮ только на вашей машине
-----END PRIVATE KEY------ Chrome
- Firefox
- curl, приложения
curl: (60) SSL certificate problem: unable to get local issuer certificate
Классика: пустой CA Bundle. curl заметит.
Подвох ручного режима
Сертификаты, полученные через --manual, не продлеваются автоматически, если только вы не напишете хуки аутентификации, которые сами загрузят проверку. Повторите ту же команду и переустановите новый сертификат заранее, задолго до истечения текущего.
Это не провал Certbot. Для автоматического продления нужен какой-то автоматический способ доказать владение доменом и установить результат. Человек, перетаскивающий секретный файл в public_html, к сожалению, не API.
Ваше подключение не является закрытым
NET::ERR_CERT_DATE_INVALID
- certbot certonly --manual
- залить токен в public_html
- вставить файлы в панель
ушли 0 · при ~140 посетителях в день
Продлить SSL для example.com
С 60-го дня таймер не справляется. Запасной план — вы.
Если хостер позже даст SSH-доступ, переходите на --webroot. Если добавит встроенную поддержку Let’s Encrypt, пользуйтесь ей. Если он продолжит каждый год брать деньги за привилегию вставлять бесплатные сертификаты в форму, подумайте о смене хостинга.
Когда не получается
Почти любая ошибка HTTP-01 — это что-то из списка:
- домен указывает на другой сервер;
- порт 80 заблокирован;
.well-knownсоздана не в настоящей корневой папке сайта;- WordPress, Nginx или какое-то правило безопасности перехватывает URL проверки;
- запросили хост
www, но у него нет DNS-записи; - IPv6-запись
AAAAуказывает не туда же, куда IPv4-записьA; - файловый менеджер услужливо дописал
.txtк имени токена.
Не перезапускайте Certbot снова и снова в надежде, что интернет передумает. Откройте точный URL проверки. Пока он не вернёт точное значение, Let’s Encrypt тоже не сможет его проверить.
Полезные ссылки
- Certbot: получение сертификатов и выбор плагинов
- Типы проверок Let’s Encrypt
- Почему Let’s Encrypt советует держать порт 80 открытым
Обложка: Питер Брейгель Старший, «Жатва», 1565, Метрополитен-музей, общественное достояние.
Комментарии
Комментарии живут в GitHub Discussions (через giscus), так что для участия нужен аккаунт GitHub.