---
title: "Nginx и Let's Encrypt: бесплатный HTTPS на VPS с Ubuntu и Debian"
description: "Как поставить nginx как reverse proxy для приложения, открыть 80/443 в UFW и получить бесплатный сертификат Let's Encrypt через certbot с автопродлением и редиректом."
url: https://tihost.io/blog/nginx-letsencrypt-https
language: ru
section: "Руководства"
published: 2026-10-05
updated: 2026-10-05
publisher: Tihost (https://tihost.io)
---

# Nginx и Let's Encrypt: бесплатный HTTPS на VPS с Ubuntu и Debian

> **Коротко:** Чтобы сайт на VPS открывался по HTTPS, установите nginx, опишите server block с вашим доменом и `proxy_pass` на приложение, откройте порты 80 и 443 и выполните `sudo certbot --nginx -d example.com`. Certbot сам получит бесплатный сертификат Let's Encrypt, настроит редирект на HTTPS и будет продлевать сертификат по таймеру systemd.

**Главное:**

- Бесплатный HTTPS на VPS получают связкой nginx и certbot: пакеты `certbot` и `python3-certbot-nginx` из apt, затем команда `sudo certbot --nginx -d example.com -d www.example.com`.
- Nginx работает как reverse proxy: принимает запросы на портах 80 и 443 и через `proxy_pass` передаёт их приложению на `127.0.0.1:порт`, так что само приложение не торчит в интернет.
- Сертификат Let's Encrypt действует 90 дней, а пакет certbot ставит таймер systemd, который продлевает его автоматически; проверка продления - `sudo certbot renew --dry-run`.
- Certbot получит сертификат, только если домен уже указывает на IP сервера и порт 80 открыт снаружи: в UFW это правило `sudo ufw allow 'Nginx Full'`.

> Команды проверены для Ubuntu 22.04/24.04 и Debian 12. До начала нужны две вещи: пользователь с sudo ([первая настройка VPS](https://tihost.io/blog/vps-first-setup)) и домен, A-запись которого указывает на IP сервера ([как привязать домен](https://tihost.io/blog/domain-to-vps)). В примерах `example.com` - ваш домен, `3000` - порт вашего приложения.

## Шаг 1. Установите nginx

Nginx есть в стандартных репозиториях Ubuntu и Debian. После установки служба сразу запускается и включается в автозапуск - статус должен быть `active (running)`:

```bash
sudo apt update
sudo apt install -y nginx
systemctl status nginx --no-pager
```

## Шаг 2. Откройте порты 80 и 443 в UFW

Порт 80 нужен для проверки домена Let's Encrypt и редиректа, 443 - для самого HTTPS. Профиль `Nginx Full` открывает оба:

```bash
sudo ufw allow 'Nginx Full'
sudo ufw status
```

Если UFW ответит, что профиля с таким именем нет (так бывает на Debian), откройте порты напрямую: `sudo ufw allow 80,443/tcp`. Правило для SSH при этом должно остаться - проверьте его в выводе `ufw status`.

## Шаг 3. Создайте server block для домена

Server block - это описание одного сайта в nginx. Создайте файл `/etc/nginx/sites-available/example.com` (например, `sudo nano /etc/nginx/sites-available/example.com`) с таким содержимым - nginx будет принимать запросы на домен и передавать их приложению на `127.0.0.1:3000`:

`/etc/nginx/sites-available/example.com`:

```
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}
```

- `Host` передаёт приложению имя домена из запроса - без него приложение увидит `127.0.0.1`.
- `X-Real-IP` и `X-Forwarded-For` несут настоящий IP посетителя, иначе в логах приложения все запросы будут от nginx.
- `X-Forwarded-Proto` сообщает, пришёл запрос по HTTP или HTTPS: по нему фреймворки строят правильные ссылки и не уходят в цикл редиректов.
- `Upgrade` и `Connection` вместе с блоком `map` нужны для WebSocket. Блок `map` объявляется один раз на сервер: для второго сайта копируйте только `server`.

> Приложение слушает только `127.0.0.1`, а не `0.0.0.0` - тогда снаружи до него можно добраться лишь через nginx. Контейнер Docker публикуйте так же: `127.0.0.1:3000:3000`, иначе порт откроется в обход UFW (подробнее - в [руководстве по Docker](https://tihost.io/blog/install-docker-ubuntu-debian)). Нужен просто статический сайт - замените `location` на `root /var/www/example.com;`.

## Шаг 4. Включите сайт и проверьте конфигурацию

Сайт включается ссылкой в `sites-enabled`. Стандартный сайт-заглушку `default` удалите, чтобы он не перехватывал запросы. `nginx -t` проверяет синтаксис до перезагрузки - если он пишет `syntax is ok` и `test is successful`, конфигурацию можно применять:

```bash
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
curl -I http://example.com
```

Последняя команда должна вернуть ответ вашего приложения по HTTP. Ответ `502 Bad Gateway` значит, что nginx работает, а приложение на порту 3000 не запущено.

## Шаг 5. Получите сертификат Let's Encrypt через certbot

Certbot - официальный клиент Let's Encrypt от EFF, плагин `python3-certbot-nginx` сам правит конфигурацию nginx. Укажите все имена, на которые должен действовать сертификат, флагом `-d`; `--redirect` сразу включает перенаправление с HTTP на HTTPS:

```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx --redirect -d example.com -d www.example.com
```

При первом запуске certbot спросит email и попросит принять условия Let's Encrypt. Затем он проверит, что домен ведёт на этот сервер (запрос на порт 80), получит сертификат и допишет в server block строки `listen 443 ssl` и пути к ключам. Подробнее о параметрах - на [certbot.eff.org](https://certbot.eff.org/).

## Шаг 6. Проверьте автопродление

Сертификат Let's Encrypt действует 90 дней. Пакет certbot из apt ставит таймер systemd, который дважды в день проверяет сертификаты и продлевает те, срок которых подходит к концу; после продления плагин сам перезагружает nginx. Убедитесь, что продление пройдёт:

```bash
sudo certbot renew --dry-run
systemctl list-timers | grep certbot
sudo certbot certificates
```

`--dry-run` проходит всю процедуру на тестовом сервере Let's Encrypt, не трогая настоящий сертификат. Вторая команда показывает таймер `certbot.timer` и время следующего запуска, третья - срок действия выпущенных сертификатов.

## Шаг 7. Проверьте HTTPS и редирект

Запрос по HTTP должен вернуть `301 Moved Permanently` с адресом `https://` в заголовке `Location`, а запрос по HTTPS - ответ приложения без ошибок сертификата:

```bash
curl -I http://example.com
curl -I https://example.com
```

## Частые ошибки certbot и nginx

| Что видите | Причина | Что сделать |
| --- | --- | --- |
| `DNS problem: NXDOMAIN` или проверка уходит на чужой IP | DNS ещё не обновился или A-запись указывает не туда | Проверьте `dig +short example.com` через публичный резолвер и дождитесь, пока он вернёт IP сервера |
| `Timeout during connect (likely firewall problem)` | Порт 80 закрыт снаружи: правило UFW, nginx не слушает 80 или домен проксируется Cloudflare с ошибкой | `sudo ufw allow 'Nginx Full'`, `sudo ss -tlnp` - nginx должен слушать `:80` |
| `too many certificates` или `too many failed authorizations` | Сработали лимиты Let's Encrypt на число выпусков или неудачных проверок | Эксперименты делайте с `--dry-run`, подождите снятия лимита; актуальные значения - в [документации Let's Encrypt](https://letsencrypt.org/docs/rate-limits/) |
| `502 Bad Gateway` | Приложение не запущено или слушает другой порт | `curl http://127.0.0.1:3000` на сервере; сверьте порт в `proxy_pass` |
| `conflicting server name` в `nginx -t` | Один домен описан в двух server block | Оставьте домен в одном файле в `sites-enabled` |

За nginx удобно прятать любые приложения: [Node.js-сервис](https://tihost.io/blog/nodejs-app-on-vps), вебхук [Telegram-бота](https://tihost.io/blog/telegram-bot-on-vps) (Telegram принимает вебхуки только по HTTPS) или контейнеры [Docker](https://tihost.io/blog/install-docker-ubuntu-debian). Для nginx с парой небольших сайтов хватает конфигурации с 1 vCPU и 2 ГБ памяти; VPS Tihost с полным root-доступом разворачивается примерно за 2 минуты.

**Запустите сервер за 2 минуты.** AMD Ryzen 9, NVMe и защита от DDoS в Германии, Финляндии и Польше. Оплата криптовалютой или картой. [Заказать сервер](https://tihost.io/login)

## Частые вопросы

### Сколько стоит сертификат Let's Encrypt?

Сертификат Let's Encrypt бесплатный: его выпускает некоммерческий центр сертификации, а certbot получает и продлевает его автоматически. Браузеры доверяют ему так же, как платным DV-сертификатам.

### Как часто нужно продлевать сертификат Let's Encrypt?

Сертификат Let's Encrypt действует 90 дней, но вручную его продлевать не нужно: таймер systemd из пакета certbot продлевает его заранее. Проверить продление можно командой `sudo certbot renew --dry-run`.

### Почему certbot пишет Timeout during connect?

Let's Encrypt не может достучаться до сервера по порту 80. Откройте порты командой `sudo ufw allow 'Nginx Full'`, проверьте, что nginx запущен, и что домен указывает на IP этого сервера.

### Можно ли получить сертификат на IP-адрес без домена?

Для обычной схемы с certbot и nginx нужен домен: сертификат выпускается на имя, которое указывает на сервер. Домен можно купить у любого регистратора и привязать A-записью за несколько минут.

### Чем certbot из apt отличается от certbot из snap?

Сайт certbot.eff.org рекомендует snap, где certbot обновляется быстрее. Пакеты `certbot` и `python3-certbot-nginx` из apt в Ubuntu и Debian тоже работают и обновляются вместе с системой - для одного сайта разницы нет.

### Что такое reverse proxy в nginx?

Reverse proxy - сервер, который принимает запросы из интернета и передаёт их приложению внутри сервера. В nginx за это отвечает директива `proxy_pass http://127.0.0.1:3000;`, а nginx при этом берёт на себя HTTPS, сжатие и статику.

---

Обновлено 2026-10-05 · https://tihost.io/blog/nginx-letsencrypt-https
