Add reverse proxy SSL guides for Caddy, Nginx, and Traefik.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,10 +7,11 @@
|
||||
- Go 1.23 (веб-админка)
|
||||
- PostgreSQL 17
|
||||
- Docker Compose
|
||||
- Reverse proxy + SSL: **Caddy** / **Nginx** / **Traefik**
|
||||
|
||||
## Быстрый старт (Dokploy / Docker)
|
||||
|
||||
1. Скопируйте `.env.example` → `.env` и задайте пароли.
|
||||
1. Скопируйте `.env.example` → `.env` и задайте пароли + `DOMAIN`.
|
||||
2. В Dokploy создайте приложение типа **Docker Compose**, укажите этот репозиторий.
|
||||
3. Deploy — поднимутся сервисы `app` и `postgres`.
|
||||
|
||||
@@ -30,6 +31,151 @@ docker compose up -d --build
|
||||
|
||||
При первом запуске админ создаётся автоматически из этих переменных.
|
||||
|
||||
---
|
||||
|
||||
## Reverse proxy + SSL (Let's Encrypt)
|
||||
|
||||
Примеры лежат в `deploy/`. Сеть Docker: `vpn-panel-net`.
|
||||
|
||||
### Что нужно до выпуска сертификата
|
||||
|
||||
1. **DNS**: A (и при необходимости AAAA) запись `DOMAIN` → публичный IP сервера.
|
||||
2. **Порты**: `80` и `443` открыты на firewall / security group (TCP; для Caddy HTTP/3 ещё `443/udp`).
|
||||
3. **Домен в `.env`**:
|
||||
```env
|
||||
DOMAIN=panel.example.com
|
||||
ACME_EMAIL=admin@example.com
|
||||
```
|
||||
4. **Не светить панель наружу на `:8080`** — только через proxy:
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f deploy/compose.behind-proxy.yml up -d
|
||||
```
|
||||
Либо в Dokploy / compose закомментируйте `ports` у `app`, оставьте доступ по внутренней сети `app:8080`.
|
||||
5. Прокси обязан передавать заголовки `Host`, `X-Forwarded-Proto`, `X-Forwarded-For` (уже есть в примерах).
|
||||
|
||||
> Let's Encrypt не выпустит сертификат на `localhost` / приватный IP. Нужен реальный домен с публичным DNS.
|
||||
|
||||
---
|
||||
|
||||
### Вариант A — Caddy (самый простой, SSL автоматом)
|
||||
|
||||
Caddy сам получает и продлевает сертификат.
|
||||
|
||||
1. В `deploy/caddy/Caddyfile` домен берётся из `{$DOMAIN:...}` (или задайте в `.env`).
|
||||
2. Запуск вместе с панелью:
|
||||
|
||||
```bash
|
||||
# из корня репозитория
|
||||
docker compose \
|
||||
-f docker-compose.yml \
|
||||
-f deploy/compose.behind-proxy.yml \
|
||||
-f deploy/caddy/docker-compose.caddy.yml \
|
||||
up -d --build
|
||||
```
|
||||
|
||||
3. Откройте `https://panel.example.com`.
|
||||
|
||||
Файлы: `deploy/caddy/Caddyfile`, `deploy/caddy/docker-compose.caddy.yml`.
|
||||
|
||||
---
|
||||
|
||||
### Вариант B — Nginx + Certbot
|
||||
|
||||
1. Подставьте свой домен в `deploy/nginx/nginx.conf` (`server_name` и пути к сертификатам).
|
||||
2. Поднимите стек (сначала HTTP + ACME webroot):
|
||||
|
||||
```bash
|
||||
docker compose \
|
||||
-f docker-compose.yml \
|
||||
-f deploy/compose.behind-proxy.yml \
|
||||
-f deploy/nginx/docker-compose.nginx.yml \
|
||||
up -d --build
|
||||
```
|
||||
|
||||
3. Выпустите сертификат:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/nginx/docker-compose.nginx.yml run --rm certbot certonly \
|
||||
--webroot -w /var/www/certbot \
|
||||
-d panel.example.com \
|
||||
--email admin@example.com \
|
||||
--agree-tos --no-eff-email
|
||||
```
|
||||
|
||||
4. В `deploy/nginx/nginx.conf`:
|
||||
- раскомментируйте блок `server { listen 443 ... }`;
|
||||
- включите `return 301 https://$host$request_uri;` в HTTP-сервере;
|
||||
- закомментируйте временный `location /` на порту 80 (оставьте только ACME).
|
||||
5. Перезагрузите nginx:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f deploy/nginx/docker-compose.nginx.yml exec nginx nginx -s reload
|
||||
```
|
||||
|
||||
Продление: контейнер `certbot` крутит `renew` раз в 12 часов; после renew — `nginx -s reload`.
|
||||
|
||||
Файлы: `deploy/nginx/`.
|
||||
|
||||
---
|
||||
|
||||
### Вариант C — Traefik (свой или Dokploy)
|
||||
|
||||
#### C1. Свой Traefik из репозитория
|
||||
|
||||
```bash
|
||||
docker compose \
|
||||
-f docker-compose.yml \
|
||||
-f deploy/compose.behind-proxy.yml \
|
||||
-f deploy/traefik/docker-compose.traefik.yml \
|
||||
up -d --build
|
||||
```
|
||||
|
||||
В `.env`: `DOMAIN`, `ACME_EMAIL`. Сертификат выпускается HTTP-challenge на entrypoint `web`.
|
||||
|
||||
#### C2. Dokploy (встроенный Traefik)
|
||||
|
||||
Dokploy уже поднимает Traefik — **не** добавляйте `deploy/traefik/docker-compose.traefik.yml`.
|
||||
|
||||
1. В Dokploy укажите домен для сервиса `app`.
|
||||
2. Либо добавьте labels к `app` (см. `deploy/traefik/labels.example.yml`):
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.vpn-panel.rule=Host(`panel.example.com`)
|
||||
- traefik.http.routers.vpn-panel.entrypoints=websecure
|
||||
- traefik.http.routers.vpn-panel.tls=true
|
||||
- traefik.http.routers.vpn-panel.tls.certresolver=letsencrypt
|
||||
- traefik.http.services.vpn-panel.loadbalancer.server.port=8080
|
||||
```
|
||||
|
||||
Имя `certresolver` в Dokploy часто `letsencrypt` — проверьте в настройках (или `TRAEFIK_CERT_RESOLVER` в `.env`).
|
||||
|
||||
3. Не публикуйте порт `8080` наружу в UI Dokploy, если трафик идёт только через Traefik.
|
||||
|
||||
---
|
||||
|
||||
### Чеклист после включения HTTPS
|
||||
|
||||
| Проверка | Ожидание |
|
||||
|---|---|
|
||||
| `https://DOMAIN/` | Главная панель |
|
||||
| `https://DOMAIN/health` | `ok` |
|
||||
| HTTP → HTTPS | Редирект 301 (Caddy/Traefik по умолчанию; Nginx — после шага 4) |
|
||||
| Сертификат | Валидный LE, не self-signed |
|
||||
| Порт `8080` снаружи | Закрыт |
|
||||
|
||||
### Типичные ошибки
|
||||
|
||||
| Симптом | Причина |
|
||||
|---|---|
|
||||
| ACME timeout / pending | DNS ещё не указывает на сервер, или закрыт порт 80 |
|
||||
| 502 Bad Gateway | Proxy не в сети `vpn-panel-net` / сервис `app` не запущен |
|
||||
| Редирект-петля | За приложением HTTPS, а `X-Forwarded-Proto` не передаётся |
|
||||
| Certbot: no such file | Домен в путях `nginx.conf` не совпадает с `-d` |
|
||||
|
||||
---
|
||||
|
||||
## Протоколы (seed)
|
||||
|
||||
WireGuard, OpenVPN, VLESS, VMess, Trojan, Shadowsocks, Hysteria2 — можно включать/выключать в админке.
|
||||
|
||||
Reference in New Issue
Block a user