- Caddyfile: global servers { log_credentials } — Caddy перестаёт
редактировать Authorization header в "REDACTED"
- Caddyfile: отдельный log auth_audit { } → /var/log/caddy/auth_audit.log
(retention 7d, roll 10MiB×3) для изоляции auth-событий
- docker-compose.prod.yml: CADDY_LOG_FILE → auth_audit.log (forwarder
читает меньший файл, снижает false reads от non-auth requests)
- forwarder.py: обновлены docstrings — требования к log_credentials явные
- docs/runbooks: секция «Аудит логи» + security note про log_credentials
Результат: _extract_attempted_username получает raw Basic auth header
(не "REDACTED") → attempted_username tag в GlitchTip event заполнен.
Caddy validate: Valid configuration (caddy:2 v2.11.3).
5.9 KiB
Basic Auth Management Runbook
Установлено: 2026-05-23 (PR #426, commit cc2d148)
Realm: "GenDesign Pilot"
URL: https://gendsgn.ru/
Добавить пользователя
./scripts/auth/add_user.sh <username>
# Вводи пароль интерактивно; скрипт добавляет в caddy/users.caddy.snippet
После: commit snippet → PR → merge → GHA deploy → Caddy reload (автоматически в deploy.yml).
Удалить пользователя
./scripts/auth/remove_user.sh <username>ASAP- Commit + push + PR (merge приоритетным)
docker compose exec caddy caddy reloadпосле deploy- Сгенерировать новый credential через
add_user.sh - Уведомить остальных стейкхолдеров о замене
Просмотр текущих пользователей
./scripts/auth/list_users.sh
Credencial rotation
При компрометации пароля: remove_user + add_user с новым паролем + PR-merge + разослать новый credential.
Аудит логи
-
Auth audit:
/var/log/caddy/auth_audit.log— все события basic_auth (включая raw Authorization). Содержит plain credentials в Base64 — accessible только root на VPS. Используется forwarder'ом (см.ops/glitchtip-auth-forwarder/forwarder.py). Retention: 7 дней (roll_size 10MiB, keep 3, 168h). -
Access log:
/var/log/caddy/gendsgn.ru.log— все requests, format JSON. Тоже содержит raw Authorization из-за globallog_credentials(Caddy 2.x — опция только global, нельзя per-block). Retention: 30 дней (roll_size 50MiB, keep 5, 720h).
Failed auth последние 100:
docker compose -f docker-compose.prod.yml exec caddy \
grep -P '"status":401' /var/log/caddy/auth_audit.log | tail -100 | jq
Security note
log_credentials — опция под servers { } global block, нельзя per-virtual-host. Plain Base64 credentials попадают в оба log файла. Mitigation:
- VPS root-only (только SSH key authorized owner)
- Retention: gendsgn.ru.log = 30 дней, auth_audit.log = 7 дней
- Не выгружать логи на внешние системы без redaction
Диагностика
# Посмотреть 401-ошибки в auth audit log
ssh gendesign 'docker compose -p gendesign exec caddy tail -f /var/log/caddy/auth_audit.log' | grep '"status":401'
# Reload конфига Caddy без перезапуска
ssh gendesign 'docker compose -p gendesign exec -T caddy caddy reload --config /etc/caddy/Caddyfile'
GlitchTip auth event forwarding
Sidecar gendesign-auth-forwarder шлёт 401 события в GlitchTip как Sentry warning events.
- Состояние:
docker compose -p gendesign ps | grep auth-forwarder - Logs:
docker compose -p gendesign logs -f glitchtip-auth-forwarder - GlitchTip dashboard: https://errors.gendsgn.ru/ — фильтр
event_type:basic_auth_failed - Storm digest: при >10 failed auth за 60s → отдельный
event_type:basic_auth_stormevent - Мониторы (GlitchTip uptime, SentryUptimeBot) — получают 401 стабильно из-за отсутствия credentials; они фильтруются как individual events, учитываются только в storm digest
Если sidecar упал — failed auth события не теряются (offset persistent в auth_forwarder_state volume), но в GlitchTip не доезжают пока container down.
Перезапуск forwarder
ssh gendesign 'docker compose -p gendesign restart glitchtip-auth-forwarder'
Переменные окружения forwarder
Задаются в /opt/gendesign/.env на VPS:
| Переменная | Описание | Обязательна |
|---|---|---|
GLITCHTIP_DSN |
Sentry DSN GlitchTip (project backend) | Да |
Deploy
Sidecar собирается локально на VPS на каждом запуске deploy.yml (после merge в main).
Не требует pre-push image build, не использует GHCR.
Forwarder контейнер пересоздаётся --force-recreate чтобы подхватить новый image при изменении кода.
В случае sidecar не запустился:
ssh gendesign 'docker compose -p gendesign -f docker-compose.prod.yml logs --tail=100 glitchtip-auth-forwarder'
Если build fail на VPS — проверь ops/glitchtip-auth-forwarder/Dockerfile локально:
docker build ops/glitchtip-auth-forwarder/
Phase 2 — реализовано (PR #430)
GlitchTip forwarder sidecar добавлен в ops/glitchtip-auth-forwarder/.
Архитектура: Python 3.12 slim, sentry-sdk 2.18, tail live Caddy log, offset в named volume.
Deploy автоматизирован через deploy.yml — ручной SSH на VPS не нужен.
Phase 3 — реализовано (PR #436)
log_credentials + auth_audit.log → forwarder получает реальный username из 401.
- Global
log_credentialsв Caddyfile — Caddy перестаёт редактировать Authorization header. - Отдельный
auth_audit.log(retention 7d) — forwarder читает именно его. _extract_attempted_usernameдекодирует Basic auth →attempted_usernametag в GlitchTip event.- Результат: GlitchTip event получает
attempted_username:testbruteforceвместо(none).
Phase 4 (TODO)
- При >30 users — миграция на OAuth/NextAuth
- Разделение admin/user по доступу через Caddy path matcher или app-level RBAC