feat(infra): GlitchTip self-hosted error tracking (#204 devops) #205
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#205
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/204-glitchtip-infra"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
docker-compose.prod.yml: addglitchtip-web+glitchtip-workerservices; both share existingpostgres(new DBglitchtip) andredis(DB index 2); mem_limit 256m eachCaddyfile: adderrors.gendsgn.rublock — auto-TLS, reverse_proxy toglitchtip-web:8080, gzip/zstd, access log.env.example: documentGLITCHTIP_DB_PASS,GLITCHTIP_SECRET,GLITCHTIP_DSN,NEXT_PUBLIC_GLITCHTIP_DSNscripts/bootstrap_glitchtip.sh: idempotent one-shot script — creates DB/role, pulls images, starts containers, waits for healthcheck, prints next steps (superuser, projects, DSNs)No changes to
deploy.yml—docker compose up -dpicks up new services automatically.Env variable contract (cross-PR)
GLITCHTIP_DB_PASS.envGLITCHTIP_SECRET.envGLITCHTIP_DSNbackend/.env(after UI setup)NEXT_PUBLIC_GLITCHTIP_DSNbackend/.envor.env(after UI setup)Test plan
docker compose -f docker-compose.prod.yml configvalidates without errorsbash -n scripts/bootstrap_glitchtip.sh— syntax OK (checked)bash scripts/bootstrap_glitchtip.shon VPS, verify https://errors.gendsgn.ru is reachableCloses #204
Deep Code Review — verdict
Summary
docker-compose.prod.yml,Caddyfile,scripts/bootstrap_glitchtip.sh,.env.example)a79ee83· base256909ddocker-compose*.yml+Caddyfile)🔴 Critical
None.
🟠 High (fix before merge)
[
scripts/bootstrap_glitchtip.sh:55] SQL injection / breakage via password interpolationPassword substituted into heredoc:
Any
'inGLITCHTIP_DB_PASS→ SQL syntax error (best case) или injection (worst). Прод-пароль из random generator скорее всего безопасен, но контракт хрупкий.Fix: pass via psql variable +
format():[
docker-compose.prod.yml:124-160+.forgejo/workflows/deploy.yml:194] Crash-loop on first deploy after mergeDeploy workflow runs
docker compose up -dбез service-фильтра → новыеglitchtip-web/glitchtip-workerстартуют немедленно, но:GLITCHTIP_DB_PASS/GLITCHTIP_SECRETещё не в VPS/opt/gendesign/.envglitchtip+ role не созданы→ containers будут падать в restart-loop с
restart: alwaysпока человек не сделает: (1) добавить env в.env, (2) запустить bootstrap script.PR body утверждает "compose auto-picks up new services" — это правда, но в этом контексте это бага, не фича.
Fix (выбрать один):
profiles: ["glitchtip"]к новым services → не стартуют автоматом. Bootstrap script затем делаетdocker compose --profile glitchtip up -d..envи запустить bootstrap до merge feature ветки в main".up -d, но это требует уже залитого compose.yml → catch-22 без profiles.Рекомендую (a) — самый чистый.
[
docker-compose.prod.yml:139-140,158]mem_limit: 256mслишком мал для GlitchTip Django+Gunicorn+CeleryUpstream рекомендует min 512m для web и 256-512m для worker. С
CELERY_WORKER_AUTOSCALE: "1,3"(3 worker процесса) под нагрузкой → OOM-kill, потеря событий именно тогда, когда tracker нужен (incident). Все остальные services в compose без limit — это новый паттерн только для glitchtip.Fix:
mem_limit: 512mдля web,mem_limit: 384mдля worker, ИЛИ убрать limit вовсе (consistent с остальными).🟡 Medium
[
docker-compose.prod.yml:124,141]image: glitchtip/glitchtip:latest— pin к major (:v4) или конкретной версии. GlitchTip может выкатить breaking schema migration;:latest+ auto-pull в deploy = surprise downtime.[
docker-compose.prod.yml:124-141] нет healthcheckБез него Caddy в той же
defaultсети начнёт проксировать сразу → 502 для ~30-60s после рестарта.[
docker-compose.prod.yml:138]CELERY_WORKER_AUTOSCALE: "1,3"наglitchtip-web— это var для Celery worker, на web (gunicorn) бессмыслен. Cosmetic, но указывает на copy-paste config. Удалить изglitchtip-webenv, оставить только наglitchtip-worker.Нет persistent volume для GlitchTip media/uploads. Если используется
MEDIA_ROOT(event attachments, profile avatars), теряются при--force-recreate. Если default GlitchTip storage = postgres only — OK, но это нужно подтвердить и закомментировать в compose.[
scripts/bootstrap_glitchtip.sh:46]pg_isreadyждёт только 30 секунд (30 × 2s). Если postgres стартует медленно при первом запуске PostGIS init scripts — таймаут. Increase to 60 итераций или 5s интервал.🟢 Low / nits
[
Caddyfile:47-57] Нет explicit security headers (X-Frame-Options,Strict-Transport-Security,Content-Security-Policy). GlitchTip upstream шлёт свои headers, но Caddy auto-TLS не добавляет HSTS по дефолту. Можноheader Strict-Transport-Security "max-age=31536000;"в block. Не блокирующее.[
scripts/bootstrap_glitchtip.sh:32]source .env— fragile если.envсодержит values с пробелами /#/"без quoting. На текущей.envработает, но docker-compose-style.envparser строже чем bashsource. Edge case.[
bootstrap_glitchtip.sh:101-103]up -d --force-recreate --no-deps backend / worker / beatбезpullсначала — recreate возьмёт existing image, ok, но если image обновился pre-existing — нужен явныйpull. Cosmetic.Cross-file impact analysis
backend/app/main.pyинициализируетsentry_sdk.init(dsn=GLITCHTIP_DSN)при non-empty DSN. Без infra (этот PR) backend просто no-op'нет → safe.@sentry/nextjsno-op при отсутствииNEXT_PUBLIC_GLITCHTIP_DSN. Safe.decisions/decision-glitchtip-frontend-sentry.md+fixes/fixes-MOC.mdуже содержат запись о backend SDK migration. После merge этого PR нужна новая запись вdecisions/decision-glitchtip-infra.mdс финальным VPS bootstrap runbook →runbooks/glitchtip-bootstrap.md(per CLAUDE.md rule #6)..forgejo/workflows/deploy.ymltrigger paths включаютdocker-compose.prod.yml+Caddyfile→ этот PR триггерит full deploy цикл (build всех images + SSH deploy + caddy reload). См. 🟠 #2 — race condition.Vault cross-check
decisions/decision-glitchtip-frontend-sentry.md— frontend контракт consistent (NEXT_PUBLIC_GLITCHTIP_DSN)fixes/fixes-MOC.mdGlitchTip backend section (PR #207) — env var naming consistent (GLITCHTIP_DSN,GLITCHTIP_TRACES_SAMPLE_RATE)decisions/decision-glitchtip-infra.md/runbooks/glitchtip-bootstrap.md— создать в той же сессии что merge PRConventions check
.env.example— пустые placeholders, no secret leakageset -euo pipefail,:?validation для required vars, idempotent SQL via\gexec+DO $$ IF NOT EXISTSredis_urldefault/0, нигде нет/2)obsidian.gendsgn.rublockPOSTGRES_USER):latesttags inconsistent с остальным проектом (${IMAGE_TAG}для GHCR images) — но для внешнего vendor image приемлемо если pin не критичен; рекомендую:v4минимумPerformance / blast radius
docker compose -p gendesign rm -f glitchtip-web glitchtip-worker+DROP DATABASE glitchtip; DROP ROLE glitchtip;Positive observations
IF NOT EXISTS,\gexec), validation (:?),set -euo pipefail, чёткие next-stepsENABLE_USER_REGISTRATION: "false"+ENABLE_ORGANIZATION_CREATION: "false"— закрыто от random signup, правильный production defaultEMAIL_URL: dummy://— explicit, не падёт при first start без SMTPPOSTGRES_USERGLITCHTIP_DOMAIN: https://errors.gendsgn.ruкорректно (нужен GlitchTip для генерации absolute URLs в emails / DSNs)Recommended next steps
profiles: ["glitchtip"]чтобы не стартовали авто в deploy), 🟠 #3 (mem_limit 256m → 512m web / убрать):latest→:v4; add healthcheck; removeCELERY_WORKER_AUTOSCALEс web containerdecisions/decision-glitchtip-infra.md+runbooks/glitchtip-bootstrap.mdв vaultprofilesapproach: merge → deploy безопасен → потом VPS bootstrapGLITCHTIP_DB_PASS+GLITCHTIP_SECRETв.env→ run bootstrap → потом mergeFinal action: НЕ мержу (scope blocked:
docker-compose.prod.yml+Caddyfile). Требуется human merge после fix-ов выше + manual bootstrap план.Review fixes in
ffaa363— all HIGH and medium items addressed:Closed:
-v gt_pass=...+format(%L, :'gt_pass')— shell never interpolates into SQL stringprofiles: ["glitchtip"]to both services; bootstrap uses--profile glitchtipfor pull/up; addedCOMPOSE_PROFILES=glitchtipnote for persistent activation in.envglitchtip/glitchtip:latest→glitchtip/glitchtip:6.1.6(current latest minor on Docker Hub)wget -q --spider http://localhost:8080/api/0/, 30s/5s/5r/60s start_periodCELERY_WORKER_AUTOSCALEmoved from glitchtip-web to glitchtip-worker onlyDeferred (low priority):
source .envfragility — out of scope for this infra PRpullbefore--force-recreate— deploy.yml concern, separate improvementNote on healthcheck tool: glitchtip image (Django/Alpine-based) includes
wget, so using that consistently in both compose healthcheck and bootstrap wait loop.Deep Code Review — verdict (re-review after fixup)
Summary
ffaa363(basee0055d2)docker-compose.prod.yml,Caddyfile,scripts/bootstrap_glitchtip.sh,.env.example) · +193 / -0a79ee83) — all blocking items fixedVerification of previous HIGH issues
psql -v gt_pass=...+ server-sideformat('CREATE ROLE glitchtip LOGIN PASSWORD %L', :'gt_pass')(scripts/bootstrap_glitchtip.sh:53-59). Shell no longer interpolates password into SQL string.profiles: ["glitchtip"]on bothglitchtip-web(line 130) andglitchtip-worker(line 154). Plaincompose up -dskips them. Bootstrap activates explicitly via--profile glitchtip up -dand instructs addingCOMPOSE_PROFILES=glitchtipto/opt/gendesign/.envfor persistent activation across future deploys.mem_limit: 256mtoo small1,3reasonable within 384m.:latesttagglitchtip/glitchtip:6.1.6.wget -q --spider http://localhost:8080/api/0/, 30s/5s/5r/60s start_period (matches bootstrap wait loop probe).CELERY_WORKER_AUTOSCALEon web containerConventions check
.env.example: pure placeholders, no leakset -euo pipefail,:?validation, idempotent SQL (IF NOT EXISTS+\gexec), wait loops bounded# Bootstrap script activates the profile after DB + secrets are ready.)wget --spiderso behavior is consistentDeferred (acceptable)
source .envstrictness vs docker-compose parser — edge casepullbefore--force-recreatefor backend/worker/beat — deploy.yml concernRisk
docker compose rm -f glitchtip-*+ drop DB/role)Post-merge follow-up
decisions/decision-glitchtip-infra.md+runbooks/glitchtip-bootstrap.mdin vault (per CLAUDE.md rule #6)bash scripts/bootstrap_glitchtip.shon VPS after merge withGLITCHTIP_DB_PASS/GLITCHTIP_SECRETset in/opt/gendesign/.envMerging via deep-code-reviewer — verdict APPROVE.