Files
auth-portal/docs/deploy-traefik.md
T
Denozordec b5a50ac3b3
Build and Push Auth Portal Docker Image / build-and-push (push) Successful in 46s
Build and Push Auth Portal Docker Image / create-release (push) Skipped
docs: update deployment instructions for Auth Portal with Traefik in a single Docker Compose stack
2026-07-18 19:33:22 +07:00

7.1 KiB
Raw Blame History

Развёртывание Auth Portal + Traefik (один Docker Compose)

Один стек: Traefik (HTTPS, Let's Encrypt DNS-01 через Cloudflare) + auth-portal (API + SPA, SQLite).

Образ приложения: git.shts.su/denozord/auth-portal
Публичный URL: https://auth.shnt.top
Compose: deploy/docker-compose.traefik.yml
Env-шаблон: deploy/env.traefik.example

Документация Traefik: Expose Docker, ACME DNS challenge.

Internet → :80/:443 (Traefik) → auth-portal:8080
                ↑
         Cloudflare DNS TXT (ACME)

Предпосылки

  1. Зона домена в Cloudflare (например shnt.top).
  2. Docker Engine + Compose plugin на VPS.
  3. Свободные порты 80 и 443 на хосте (этот стек сам поднимает Traefik).
  4. docker login git.shts.su.

Если на сервере уже крутится другой Traefik на 80/443 — либо остановите его, либо смените TRAEFIK_HTTP_PORT / TRAEFIK_HTTPS_PORT (и проброс снаружи). Два Traefik на одних портах не запустятся.


1. Cloudflare: токен и DNS

API-токен

API Tokens → Create Token — шаблон Edit zone DNS или Custom:

Permission Access
Zone → DNS Edit
Zone → Zone Read (желательно)

Zone Resources: Include → Specific zone → ваша зона.

Токен → CF_DNS_API_TOKEN в .env стека. Не Global API Key, не в Git.

DNS-запись

Type Name Content Proxy
A / AAAA auth IP VPS DNS only (серое облако)
dig +short auth.shnt.top A

Traefik для сертификата создаёт TXT _acme-challenge.auth… через Cloudflare API (HTTP-01 на :80 не обязателен).


2. Файлы на сервере

mkdir -p /opt/auth-portal/data
cd /opt/auth-portal

# из репозитория или curl:
#   deploy/docker-compose.traefik.yml → docker-compose.yml
#   deploy/env.traefik.example → .env

curl -fsSL -o docker-compose.yml \
  https://git.shts.su/denozord/auth-portal/raw/branch/main/deploy/docker-compose.traefik.yml
curl -fsSL -o .env \
  https://git.shts.su/denozord/auth-portal/raw/branch/main/deploy/env.traefik.example

nano .env   # заполнить секреты

Обязательные переменные в .env

Переменная Назначение
CF_DNS_API_TOKEN Cloudflare token для ACME DNS-01 (env контейнера Traefik)
LETSENCRYPT_EMAIL Email для Let's Encrypt
JWT_SECRET HS256; тот же секрет в VPS Tracker / CFDM (AUTH_JWT_SECRET)
ADMIN_PASSWORD Пароль bootstrap-админа (только при пустой БД)
AUTH_DOMAIN Хост в Traefik rule, по умолчанию auth.shnt.top
ISSUER https://auth.shnt.top — совпадает с AUTH_ISSUER приложений
RETURN_TO_ALLOWLIST Origins SSO (например .shnt.top)

Опционально: AUTH_IMAGE_TAG, TRAEFIK_IMAGE_TAG, TRAEFIK_HTTP_PORT, TRAEFIK_HTTPS_PORT.

В production cookie refresh с флагом Secure — нужен HTTPS.


3. Запуск (один compose)

cd /opt/auth-portal
docker login git.shts.su
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f --tail=100

Сервисы:

Service Контейнер Роль
traefik auth-portal-traefik :80 → HTTPS, ACME, роутинг
app auth-portal приложение на внутренней сети auth-portal, порт 8080

Первая выдача сертификата обычно 30–90 с.

Проверка

curl -fsS https://auth.shnt.top/health
echo | openssl s_client -connect auth.shnt.top:443 -servername auth.shnt.top 2>/dev/null \
  | openssl x509 -noout -issuer -dates -subject

docker compose logs traefik 2>&1 | grep -iE 'acme|certificate|cloudflare|error'

Обновление / остановка

cd /opt/auth-portal
docker compose pull
docker compose up -d

# остановка (тома и ./data сохраняются)
docker compose down
# НЕ делайте down -v без бэкапа — сотрёт ACME (auth_portal_traefik_letsencrypt)

Что внутри compose

  • Сеть Docker auth-portal (внутренняя, создаётся стеком).
  • Том auth_portal_traefik_letsencrypt/letsencrypt/acme.json.
  • Том хоста ./data → SQLite портала.
  • Labels на app: Host(AUTH_DOMAIN), entrypoints=websecure, certresolver=letsencrypt, backend port 8080.
  • CF_DNS_API_TOKEN только у сервиса traefik.

Полный файл: deploy/docker-compose.traefik.yml.


Связка с приложениями

AUTH_REQUIRED=true
AUTH_JWT_SECRET=<тот же JWT_SECRET>
AUTH_ISSUER=https://auth.shnt.top
AUTH_PORTAL_URL=https://auth.shnt.top

UI:

VITE_AUTH_ENABLED=true
VITE_AUTH_PORTAL_URL=https://auth.shnt.top

См. integrate-vps-tracker.md, integrate-cfdm.md.
Logout SSO: https://auth.shnt.top/logout.


Бэкап

# SQLite
cp /opt/auth-portal/data/app.db /opt/auth-portal/data/app.db.bak-$(date +%F)

# ACME
docker run --rm -v auth_portal_traefik_letsencrypt:/data -v "$PWD:/backup" alpine \
  tar czf /backup/traefik-acme-$(date +%F).tgz -C /data .

Откат образа: в .env AUTH_IMAGE_TAG=vX.Y.Zdocker compose pull && docker compose up -d.


Troubleshooting

Симптом Что проверить
Bind for 0.0.0.0:80/443 failed Другой Traefik/nginx занимает порты
ACME / нет HTTPS CF_DNS_API_TOKEN, права Zone:DNS:Edit, логи docker compose logs traefik
invalid credentials Не Global Key; зона в scope токена; пробелы в .env
Gateway Timeout / 404 docker compose ps; labels; сеть auth-portal
Login OK, SSO в app падает JWT_SECRET / ISSUER
return_to rejected RETURN_TO_ALLOWLIST
Cookie не держится HTTPS; NODE_ENV=production
docker compose logs traefik 2>&1 | grep -iE 'acme|certificate|cloudflare|error'
docker compose logs app --tail=50

Альтернатива: Docker CLI (без compose)

Если нужен ручной запуск — создайте сеть и два контейнера с теми же env/labels, что в compose. Предпочтительный путь — один docker compose up -d выше.