gendesign/Caddyfile
bot-backend bb54de6000
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
feat(tradein/sale-share): standalone «Поиск домов» — de-Mera + gendsgn.ru/sale-share
Поиск домов (доля квартир в продаже) вынесен в отдельный продукт, отвязан от
бренда «Мера» (Мера = оценка вторички). Только UI + 1 строка Caddy, бэк не тронут.

- app/sale-share/layout.tsx: своя metadata (title «Поиск домов — gendsgn»).
- components/trade-in/SaleShareHeader.tsx: своя шапка — продукт «Поиск домов»,
  без MeraMark и Mera-табов; UserMenu (auth) сохранён.
- app/sale-share/page.tsx: Topbar → SaleShareHeader; убраны «Мера» из
  breadcrumb/footer. Функционал/API (/trade-in/api/...) не тронут.
- Caddyfile: gendsgn.ru/sale-share → redir /trade-in/sale-share (короткий адрес;
  basePath=/trade-in → true vanity-URL требует отдельного app).
2026-06-29 01:09:26 +03:00

223 lines
8.9 KiB
Caddyfile
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
{
servers {
# ВКЛЮЧАЕТ raw Authorization/Cookie headers в access log
# (по default Caddy 2.x редактирует их как "REDACTED").
# Plain password будет в gendsgn.ru.log + auth_audit.log — оба root-only на VPS.
# См. forwarder.py _extract_attempted_username для использования.
log_credentials
}
}
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
}
# Отдельный лог только для auth-событий.
# Forwarder (ops/glitchtip-auth-forwarder) читает именно этот файл.
# Retention 7 дней (меньше чем main log) — содержит plain Base64 credentials.
log auth_audit {
output file /var/log/caddy/auth_audit.log {
roll_size 10MiB
roll_keep 3
roll_keep_for 168h
}
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
}
# Trade-In UI preview — public CI surface (#801). Рендерит mock-фикстуру
# «денежного экрана» без бэкенда → axe/lighthouse гоняются без креды.
# Реальных клиентских данных нет (статичная фикстура) → безопасно публично.
# ДО auth-import: route матчит сверху вниз, handle short-circuit'ит.
# Без strip — Next.js basePath=/trade-in ждёт префикс в URL (как @tradein).
# ui-preview + его статика (_next/static — CSS/JS бандлы, без секретов).
# Оба ДО auth-import, иначе ассеты страницы уходят в @tradein (под auth) → 401 → без CSS.
@uipreview path /trade-in/ui-preview/* /trade-in/_next/static/*
handle @uipreview {
reverse_proxy tradein-frontend:3000
}
# 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 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
# gendsgn.ru/sale-share — короткий адрес standalone-продукта «Поиск домов».
# Next basePath=/trade-in → редиректим на канонический /trade-in/sale-share
# (тот же tradein-frontend контейнер; query-string сохраняется). True vanity-URL
# в адресной строке требует отдельного Next-app с basePath=/sale-share.
@saleshare path /sale-share /sale-share/
handle @saleshare {
redir /trade-in/sale-share permanent
}
# 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 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
handle /api/* {
reverse_proxy backend:8000 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
handle {
reverse_proxy frontend:3000 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
}
}
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
}
}
# Uptime Kuma — self-hosted uptime monitoring + public status page (#75 B6-1).
# DNS: A-record status.gendsgn.ru → IP VPS (добавить перед деплоем стека).
# Контейнер из docker-compose.uptime.yml (project gendesign-uptime) на shared
# gendesign_shared network. Если стек не запущен — Caddy отдаёт 502 ТОЛЬКО на
# этом домене, main-сайт не страдает (как obsidian.gendsgn.ru).
#
# ВНИМАНИЕ: status-page НАМЕРЕННО публичен (trust-building для пилотов, issue #75).
# Admin-панель Kuma (/dashboard, /manage-*) защищена собственным логином Kuma —
# НЕ кладём её за caddy/users.caddy.snippet, иначе double-auth сломает setup.
status.gendsgn.ru {
encode zstd gzip
reverse_proxy uptime-kuma:3001
log {
output file /var/log/caddy/status.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 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
handle {
reverse_proxy frontend:3000 {
header_up X-Authenticated-User {http.auth.user.id}
}
}
}
}
# Test deploy flow 2026-05-15T21:43:32Z