Сайт на VPS без HTTPS сегодня не «немного несерьёзно» — браузер пугает людей, формы паролей не должны идти открытым текстом, ЮKassa и многие API без TLS вас не возьмут. Let's Encrypt бесплатный. Ломается он не на цене, а на 80 порте, неверной A-записи и сломанном renewal.
Ниже — рабочая схема Nginx + Certbot на Ubuntu для одного домена и www. Предполагается первый вход, ключ, UFW. Перенос готового сайта — отдельный гайд. WordPress целиком — своя статья.
Что должно быть правдой до Certbot
- Домен куплен, A-запись смотрит на IP VPS. Проверка:
dig +short example.ru Aс телефона совпадает с карточкой сервера. - Нет старой AAAA, которая указывает на другой хостинг. IPv6 «хвост» — классика «у меня открывается, у клиента нет».
- UFW:
80/tcpи443/tcpразрешены, SSH не забыт. - Имя
example.ruне за Cloudflare proxy в режиме «оранжевое облако», пока выпускаете HTTP-01. Либо включайте DNS-only (серое), либо используйте DNS-challenge. Иначе Let's Encrypt ходит в Cloudflare, не к вам.
Пока DNS не на вас — не запускайте certbot «на удачу». Получите лимиты попыток и потеряете время.
Установка Nginx и Certbot
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
sudo systemctl enable --now nginx
Проверка снаружи: http://IP_СЕРВЕРА показывает заглушку Nginx. Если нет — файрвол, не «сломанный certbot».
Каталог сайта:
sudo mkdir -p /var/www/example
echo "ok" | sudo tee /var/www/example/index.html
sudo chown -R www-data:www-data /var/www/example
Виртуальный хост на HTTP
Файл /etc/nginx/sites-available/example.ru:
server {
listen 80;
listen [::]:80;
server_name example.ru www.example.ru;
root /var/www/example;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Сокет PHP подставьте свой: ls /run/php/. Если PHP ещё нет, уберите location ~ \.php$ и оставьте статику — сертификату всё равно.
sudo ln -s /etc/nginx/sites-available/example.ru /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
http://example.ru должен открыть ok. Если открывается заглушка default — ваш файл не в sites-enabled или default перехватывает. Отключите default, если мешает:
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Выпуск сертификата
sudo certbot --nginx -d example.ru -d www.example.ru
Укажите email для писем про истечение, согласитесь с условиями. Certbot сам допишет listen 443 ssl и редирект. Проверьте:
sudo nginx -t
curl -I https://example.ru
Должен быть HTTP/2 или 1.1, статус 200, сертификат Let's Encrypt. В браузере — замок, не «сертификат самоподписанный».
Принудительно www или без www — выберите одно и держитесь. Два канонических адреса вредят SEO. Canonical на сайте Tenku и у вас должен совпадать с редиректом.
Продление: не верьте, проверьте
Таймер Certbot ставится с пакетом. Проверка:
sudo certbot renew --dry-run
sudo systemctl list-timers | grep certbot
dry-run обязан пройти сегодня, не за 5 дней до истечения. Если не проходит — чините сейчас.
Типичный слом renewal: вы закрыли 80 порт «потому что HTTPS уже есть». HTTP-01 нужен 80. Либо оставьте 80 только для /.well-known/acme-challenge/, либо перейдите на DNS-challenge.
Минимально оставить 80 живым:
server {
listen 80;
server_name example.ru www.example.ru;
location /.well-known/acme-challenge/ { root /var/www/letsencrypt; }
location / { return 301 https://$host$request_uri; }
}
Каталог challenge должен реально существовать, если пойдёте этим путём. Штатный certbot --nginx обычно справляется сам, пока вы не «упростили» конфиг до неузнаваемости.
PHP-сайт за Nginx
Для Laravel root — это .../public. Для WordPress — корень WP. Не направляйте Nginx в каталог выше public: отдадите .env.
Таймауты для длинных админок:
fastcgi_read_timeout 120s;
client_max_body_size 32m;
Без второго загрузка фото в WP даёт невнятную ошибку сети. Без первого — 504 на тяжёлом плагине.
Логи, когда «белая страница»:
sudo tail -f /var/log/nginx/error.log /var/log/php8.1-fpm.log
Версию в имени лога подставьте свою.
Ошибки, которые все ловят
Could not bind to IPv6. В listen [::]:80 при выключенном IPv6. Уберите ipv6-listen или включите sysctl. Не маскируйте nginx -t.
Certbot: connection refused / timeout. 80 закрыт у UFW, у облачного фаервола (у Tenku для обычного VPS достаточно UFW), или A-запись не сюда. С другой сети: curl -v http://example.ru/.well-known/acme-challenge/test.
Сертификат выпустился на www, основной домен без SAN. Сразу -d example.ru -d www.example.ru. Иначе браузер на «не том» имени будет ругаться.
После выпуска редирект на HTTPS, сайт 404. Certbot мог создать второй server, root не тот. Откройте конфиг глазами, не верьте, что бот «всё настроил идеально». Один server_name, один root.
Срок истёк, вы в отпуске. Письма Certbot падают в спам. Мониторьте echo | openssl s_client -servername example.ru -connect example.ru:443 2>/dev/null | openssl x509 -noout -dates. Или любой внешний uptime с проверкой TLS.
Несколько сайтов на одном VPS
Копируйте файл хоста, меняйте server_name и root. Certbot вызывайте с новыми -d. Не пихайте десять server_name в один блок «пока мало». Потом невозможно отладить, чей сертификат истекает.
Ресурсов: каждый PHP-сайт ест RAM. Не кладите пять Bitrix на тариф «Старт». Счёт ресурсов — в выборе тарифа.
Что считать готовым
https://example.ruоткрывается без клика «дополнительно / принять риск».http://делает 301 на https той же канонической зоны.renew --dry-runзелёный.- 443 и 80 понимаете зачем открыты.
- Бэкап конфигов Nginx лежит не только на этом диске.
Дальше — приложение. Для WP: установка WordPress. Если после TLS сайт всё ещё медленный — диагностика, не «ещё сертификат подороже». TLS на современном NVMe VPS почти никогда не главный тормоз.