- Caddyfile: обернуть gendsgn.ru и :80 в route { } — сохраняет порядок директив,
/health и /preview/* теперь действительно short-circuit до basic_auth
- Caddyfile: добавить roll_size 50MiB / roll_keep 5 / roll_keep_for 720h в gendsgn.ru.log
- scripts/auth/add_user.sh: заменить base64 -w 0 (GNU-only) на base64 | tr -d "\n"
(busybox-compatible, caddy:2 Alpine base image)
- docs/runbooks/basic_auth_management.md: убрать несуществующий auth_audit.log,
заменить на реальную команду grep по статусу 401 в gendsgn.ru.log
caddy validate: Valid configuration (confirmed locally via caddy:2 container).
Ref: #426 (comment)
149 lines
5.1 KiB
Caddyfile
149 lines
5.1 KiB
Caddyfile
# Caddy config.
|
|
#
|
|
# - gendsgn.ru — main production site, auto-TLS via Let's Encrypt.
|
|
# - www.gendsgn.ru — 301 redirect to apex (canonical URL).
|
|
# - :80 — fallback for raw IP access. Closed by same auth gate (pilot phase).
|
|
#
|
|
# `handle /api/*` (NOT `handle_path`) — we keep the /api prefix because
|
|
# the FastAPI router is mounted at /api/v1/*.
|
|
#
|
|
# Auth gate: basic_auth for pilot phase (2026-05-23).
|
|
# Users managed via caddy/users.caddy.snippet (git history = audit trail).
|
|
# Public exclusions: /health (liveness probe), /preview/* (static mockups).
|
|
#
|
|
# IMPORTANT: route { } block is required to preserve directive order.
|
|
# Without route { }, Caddy executes directives in hard-coded default order
|
|
# (basic_auth runs before handle), making /health and /preview/* exclusions
|
|
# ineffective. With route { }, handlers are matched top-to-bottom as written.
|
|
|
|
gendsgn.ru {
|
|
encode zstd gzip
|
|
|
|
log {
|
|
output file /var/log/caddy/gendsgn.ru.log {
|
|
roll_size 50MiB
|
|
roll_keep 5
|
|
roll_keep_for 720h
|
|
}
|
|
format json
|
|
}
|
|
|
|
route {
|
|
# /health и /preview/* — public, без auth, short-circuit.
|
|
handle /health {
|
|
reverse_proxy backend:8000
|
|
}
|
|
|
|
# Static HTML mockups для review (audit alternatives).
|
|
# Public access — без auth (по запросу 2026-05-17).
|
|
handle_path /preview/* {
|
|
root * /srv/preview
|
|
file_server browse
|
|
}
|
|
|
|
# Auth gate (applies to all routes below within this route block).
|
|
import caddy/users.caddy.snippet
|
|
|
|
# Trade-In MVP subproject (tradein-mvp/) — gendesign-tradein docker stack,
|
|
# подключен через gendesign_shared network. Routes ДО универсального handle
|
|
# потому что Caddy матчит handle-блоки сверху вниз.
|
|
handle /trade-in/api/* {
|
|
# `handle_path /trade-in/api/*` стрипал бы целиком /trade-in/api;
|
|
# FastAPI router замаунтен на /api/v1/trade-in/* — нужен strip только
|
|
# префикса basePath /trade-in (Next.js basePath leak).
|
|
uri strip_prefix /trade-in
|
|
reverse_proxy tradein-backend:8000
|
|
}
|
|
|
|
# Matcher `path /trade-in /trade-in/*` ловит И /trade-in (без слеша),
|
|
# И /trade-in/ + /trade-in/anything. Без обоих случаев `handle /trade-in/*`
|
|
# пропускал /trade-in без слеша → попадал в общий frontend → пустой ответ.
|
|
@tradein path /trade-in /trade-in/*
|
|
handle @tradein {
|
|
# Next.js basePath=/trade-in — фронт сам ждёт префикса в URL
|
|
reverse_proxy tradein-frontend:3000
|
|
}
|
|
|
|
handle /api/* {
|
|
reverse_proxy backend:8000
|
|
}
|
|
|
|
handle {
|
|
reverse_proxy frontend:3000
|
|
}
|
|
}
|
|
}
|
|
|
|
www.gendsgn.ru {
|
|
redir https://gendsgn.ru{uri} permanent
|
|
}
|
|
|
|
# Obsidian Self-hosted LiveSync (CouchDB backend).
|
|
# Auto-TLS Let's Encrypt. CORS уже включён на стороне CouchDB через bootstrap
|
|
# (см. scripts/setup-couchdb.sh). Basic-auth — на стороне CouchDB (admin user).
|
|
#
|
|
# DNS: A-record obsidian.gendsgn.ru → IP VPS.
|
|
# Клиенты Obsidian + Self-hosted LiveSync plugin указывают на этот URL.
|
|
obsidian.gendsgn.ru {
|
|
encode zstd gzip
|
|
|
|
reverse_proxy couchdb:5984 {
|
|
# Большие документы (vault attachments / images) — увеличиваем timeout
|
|
transport http {
|
|
response_header_timeout 120s
|
|
}
|
|
}
|
|
}
|
|
|
|
# GlitchTip — self-hosted error tracking (Sentry-compatible).
|
|
# DNS: A-record errors.gendsgn.ru → IP VPS.
|
|
errors.gendsgn.ru {
|
|
encode zstd gzip
|
|
|
|
reverse_proxy glitchtip-web:8080
|
|
|
|
log {
|
|
output file /var/log/caddy/errors.gendsgn.ru.log
|
|
}
|
|
}
|
|
|
|
# Forgejo — self-hosted git (migration 2026-05-16).
|
|
# DNS: A-record git.gendsgn.ru → IP VPS.
|
|
# Forgejo container из forgejo-migration/docker-compose.yml на shared
|
|
# gendesign_default network. HTTP port 3000 (default Forgejo).
|
|
# Был добавлен вручную при migration, потерян при первом auto-deploy после
|
|
# изменения Caddyfile (deploy.yml делает git reset --hard). См. fix issue.
|
|
git.gendsgn.ru {
|
|
encode zstd gzip
|
|
|
|
reverse_proxy forgejo:3000
|
|
|
|
log {
|
|
output file /var/log/caddy/git.gendsgn.ru.log
|
|
}
|
|
}
|
|
|
|
# Plain HTTP by IP — closed by same auth gate (prevent bypass via direct IP / SSH tunnel).
|
|
# Caddy issues no TLS here (no hostname). /health remains public.
|
|
:80 {
|
|
encode zstd gzip
|
|
|
|
route {
|
|
# /health — public, без auth (GHA deploy smoke check, liveness probe).
|
|
handle /health {
|
|
reverse_proxy backend:8000
|
|
}
|
|
|
|
# Auth gate (same snippet as gendsgn.ru).
|
|
import caddy/users.caddy.snippet
|
|
|
|
handle /api/* {
|
|
reverse_proxy backend:8000
|
|
}
|
|
|
|
handle {
|
|
reverse_proxy frontend:3000
|
|
}
|
|
}
|
|
}
|
|
# Test deploy flow 2026-05-15T21:43:32Z
|