Сайт на VPS с nginx и Let's Encrypt: от домена до HTTPS
Как поднять сайт или API на VPS: настроить DNS, открыть порты 80 и 443, проксировать приложение через nginx и получить бесплатный сертификат Let's Encrypt с автопродлением.
Содержание 19
- Коротко
- Что нужно до начала
- Шаги
- Фаервол в кабинете EGN
- Что должно быть открыто наружу
- Примеры
- Симптом → причина → решение
- Пример: WebSocket через nginx
- Как проверить настройку
- Что дальше
- Частые ошибки
- Итог
- Чек-лист после выпуска сертификата
- Пример: один адрес вместо двух
- Вопросы и ответы
- Нужен ли платный сертификат?
- Можно ли обойтись без nginx?
- Почему certbot пишет, что домен не прошёл проверку?
- Что делать, если нужен только IPv4?
Сайт на VPS нужен не только владельцам сайтов. Страница статистики сервера, панель бота, форма заявок и API для модов — всё это веб-сервисы, которым нужны домен и HTTPS. Схема одна и та же: приложение слушает внутри машины, nginx принимает запросы из интернета и передаёт их дальше, а Let’s Encrypt выдаёт бесплатный сертификат.
Коротко
Направьте A-запись домена на IP вашего VPS, поставьте nginx и certbot, настройте proxy_pass на приложение, которое слушает 127.0.0.1:8000, и выпустите сертификат командой sudo certbot --nginx -d example.com. Снаружи открыты только порты 22, 80 и 443, а приложение недоступно напрямую. Продление certbot делает автоматически. На ноябрь 2026 Let’s Encrypt выдаёт сертификаты на 90 дней.
Что нужно до начала
Нужен VPS с Ubuntu 24.04 и домен, которым вы управляете. Сначала создайте у регистратора или DNS-провайдера запись типа A: имя домена указывает на IPv4 вашего сервера. Let’s Encrypt проверяет владение доменом, обращаясь на порт 80, поэтому порт должен быть доступен. Пока DNS не обновился, сертификат не выпустится.
Если у сервера есть IPv6, добавьте и запись AAAA, но только если nginx слушает IPv6. Иначе часть пользователей получит ошибку подключения.
Шаги
- Установите nginx и certbot. Certbot рекомендует установку через snap, но пакет из репозитория Ubuntu тоже работает с плагином nginx:
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx- Откройте порты. Это сразу ограничивает поверхность атаки: SSH, HTTP и HTTPS, всё остальное закрыто.
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw statusВнимание: сначала разрешите SSH, потом включайте ufw, иначе потеряете доступ к серверу.
-
Запустите приложение на локальном порту. Пример — Python-сервис на порту 8000, который слушает только
127.0.0.1. Так приложение не видно снаружи. -
Создайте конфиг сайта
/etc/nginx/sites-available/example.com:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}- Включите сайт и проверьте конфиг:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx- Выпустите сертификат. Certbot сам добавит блок
listen 443 ssl, пути к сертификату и редирект с HTTP на HTTPS:
sudo certbot --nginx -d example.com -d www.example.com- Проверьте продление. Certbot ставит таймер или cron-задание, которое обновляет сертификат, когда до конца срока остаётся меньше 30 дней. Проверка в тестовом режиме:
sudo certbot renew --dry-runФаервол в кабинете EGN
На вкладке «Фаервол» карточки VPS есть два режима: «Всё открыто» (входящие подключения на любые порты, ограничивать их нужно внутри системы) и «Свои правила» (разрешено только то, что в списке, остальное блокируется ещё до сервера). Для сайта в режиме «Свои правила» есть быстрые пресеты SSH, HTTP и HTTPS, то есть порты 22, 80 и 443. Если вы убрали порт 22, консоль в панели продолжит работать, и доступ можно вернуть. Либо пользуйтесь одним ufw внутри системы, либо облачным фаерволом, но понимайте, что правила действуют на двух уровнях и должны совпадать.
Что должно быть открыто наружу
Правильная схема выглядит так: снаружи доступны только 22, 80 и 443. Приложение на 8000 и база данных на 5432 закрыты, даже если они запущены на том же сервере. Таблица ниже показывает, что видит интернет:
Порт 80 оставляйте открытым и после выпуска сертификата. Через него Let’s Encrypt продлевает сертификат, а nginx перенаправляет пользователей на HTTPS.
Примеры
Сайт на WordPress или статическая страница. Схема та же, только proxy_pass не нужен: корень сайта указывается через root и index. Certbot всё равно выпускает сертификат тем же способом.
API для мода или бота. Если бот работает через webhook, как описано в статье Telegram-бот на VPS: long polling или webhook, адрес webhook должен быть HTTPS на одном из портов 443, 80, 88 или 8443. Удобнее всего 443 через nginx.
Несколько доменов на одном VPS. Для каждого домена создаётся свой блок server с server_name. Certbot принимает несколько -d в одной команде или выпускает отдельные сертификаты.
Симптом → причина → решение
| Симптом | Частая причина | Что сделать |
|---|---|---|
Connection refused от nginx |
Приложение не запущено или слушает другой порт | Проверьте ss -tlnp и порт в proxy_pass |
| 502 Bad Gateway | Приложение упало или не отвечает | Смотрите журнал приложения и /var/log/nginx/error.log |
| 413 Request Entity Too Large | Загрузка больше лимита nginx | Добавьте client_max_body_size 20m; в блок server |
| Ошибка WebSocket | Не переданы заголовки Upgrade | Добавьте заголовки из примера ниже |
| Сертификат есть, но браузер пишет «небезопасно» | Смешанный контент или старый кеш | Проверьте адреса ресурсов на https:// и очистите кеш |
| Certbot не продлевает сертификат | Порт 80 закрыт или таймер отключён | Проверьте ufw status и systemctl list-timers |
Пример: WebSocket через nginx
Если приложение работает с WebSocket, nginx нужно передавать заголовки обновления соединения. Добавьте в блок location такие строки:
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 300s;
}Без proxy_http_version 1.1 и заголовка Upgrade соединение обрывается сразу после рукопожатия. Таймаут proxy_read_timeout не даёт nginx закрыть долгое соединение через минуту простоя.
Как проверить настройку
После изменений выполните три проверки. Первая — синтаксис конфига, вторая — ответ сервера, третья — срок сертификата:
sudo nginx -t
curl -I https://example.com
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddateКоманда openssl покажет дату окончания сертификата. Если она близка, а certbot renew --dry-run проходит, проблема в таймере, а не в конфиге.
Что дальше
Срок сертификатов будет сокращаться (см. вопрос про платный сертификат ниже), поэтому автоматическое продление нужно проверять регулярно: sudo certbot renew --dry-run раз в месяц и systemctl list-timers | grep certbot после обновлений системы.
Когда сайт заработал, полезно подумать о резервных копиях конфигов и сертификатов. Копии /etc/nginx и /etc/letsencrypt занимают мало места, их стоит включать в общий бэкап VPS, как описано в статье Бэкапы VPS: снапшоты, S3 и restic.
Частые ошибки
- certbot не может проверить домен. Проверьте A-запись командой
dig +short example.com: адрес должен совпадать с IP сервера. Проверьте, что порт 80 открыт, и что другой веб-сервер не занимает порт. - Ошибка
nginx: [emerg] bind() to 0.0.0.0:80 failed. На порту 80 уже работает другой процесс. Найдите его командойsudo ss -tlnp | grep ':80'. - 502 Bad Gateway. nginx не может достучаться до приложения. Проверьте, что приложение запущено и слушает порт из
proxy_pass. - Приложение видно на порту 8000 из интернета. Оно слушает
0.0.0.0, а не127.0.0.1. Поправьте адрес в настройках приложения. - Сертификат истёк. Проверьте таймер
systemctl list-timers | grep certbotи результатcertbot renew --dry-run. Если они не работают, ищите причину в журнале/var/log/letsencrypt/. - Приложение не видит IP пользователя. Без заголовка
X-Forwarded-Forв приложении все запросы идут с адреса 127.0.0.1. Передавайте заголовки, как в примере.
Итог
Сайт на VPS за nginx — это простая и надёжная схема: приложение закрыто, nginx принимает HTTPS, certbot продлевает сертификат сам. Главное — не открывать порт приложения и порт базы наружу, а порт 80 оставить для проверки и продления. Если сайту нужна база данных, переходите к статье База данных на VPS: MySQL или PostgreSQL без утечек в интернет, а если сервисов несколько — к Docker Compose на VPS.
Чек-лист после выпуска сертификата
После команды certbot --nginx проверьте сайт по пунктам:
- Открывается
https://example.comбез предупреждений браузера. http://example.comперенаправляет на HTTPS.wwwи основной домен ведут на один и тот же сайт, либо один из них перенаправляет на другой.- В
sudo nginx -tнет предупреждений. sudo certbot renew --dry-runпроходит без ошибок.- Порт 80 открыт в ufw и не занят другим процессом.
Пример: один адрес вместо двух
Чтобы www.example.com всегда вёл на example.com, добавьте отдельный блок server, который делает постоянный редирект:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
return 301 https://example.com$request_uri;
}Сертификат для www должен быть в том же запросе certbot, иначе браузер покажет ошибку имени. Поэтому выпускайте сертификат сразу для обоих имён через -d example.com -d www.example.com.
Вопросы и ответы
Нужен ли платный сертификат?
Нет. Let’s Encrypt выдаёт бесплатные сертификаты, certbot продлевает их автоматически. Сейчас срок 90 дней, с 10 февраля 2027 года по умолчанию будет 64 дня, а с 16 февраля 2028 года 45 дней. Если вы пользуетесь certbot с таймером, ничего менять не нужно; свои скрипты с жёстким «продлевать раз в 60 дней» пересмотрите.
Можно ли обойтись без nginx?
Можно, если приложение само умеет HTTPS, но nginx проще для нескольких сервисов и даёт удобную настройку заголовков и редиректов.
Почему certbot пишет, что домен не прошёл проверку?
Чаще всего A-запись ещё не обновилась или порт 80 закрыт фаерволом. Проверьте оба пункта до повторного запуска.
Что делать, если нужен только IPv4?
Ничего, запись AAAA не обязательна. Главное, чтобы A-запись вела на правильный адрес.
Сервер под игры за пару минут — egnetwork.ru
Читать далее
Вся рубрика →Мониторинг ресурсов VPS: htop, iotop и vnstat
Как за несколько минут понять, что тормозит VPS: процессор, память, диск или сеть. Команды htop, iotop, vnstat, free и df с примерами вывода и таблицей симптомов.
Трафик VPS: как посчитать объём и не получить сюрприз в конце месяца
Что считается трафиком, как перевести скорость канала в терабайты за месяц, как читать счётчик входящего и исходящего трафика в кабинете EGN и что делать, если лимит закончился.
IPv6 на VPS: как пользоваться префиксом /64
Что значит /64, как проверить адрес на сервере, назначить дополнительные адреса, настроить ufw для IPv6 и не выпасть из сети. Примеры команд и типичные ошибки.