6.8 KiB
Light Alternative: GlitchTip
This document describes GlitchTip as a much lighter alternative to the
self-hosted Sentry stack in infra/sentry/. GlitchTip is NOT the
default observability backend — it lacks Performance/Tracing, Session
Replay, and OTLP ingest. Use it only when one of the following applies:
- The Sentry host is severely RAM-constrained (< 8 GB available)
- A throw-away preview deployment needs an error sink in < 5 minutes
- You want a backend on the cheapest possible Hetzner instance for a side-project that only cares about error aggregation
For the full Sentry stack, see
sentry-selfhost.md.
At a glance
| Item | GlitchTip | Self-Hosted Sentry |
|---|---|---|
| Error events | yes | yes |
| Performance / tracing | no | yes |
| Session replay | no | yes |
| Profiling | no | yes |
| OTLP ingest | no | yes (via Relay) |
| Sentry-SDK compatibility | yes (errors only) | yes (all features) |
| Container count | 4 | ~10 |
| RAM | 1–2 GB | 12–16 GB |
| Disk (90 d) | 5–10 GB | 40–60 GB |
| Upstream image pin | glitchtip/glitchtip:v6.1.6 |
getsentry/self-hosted @ 25.12.1 |
SDK compatibility note
GlitchTip implements a subset of the Sentry HTTP ingest API — errors only.
The official Sentry SDKs (@sentry/node, @sentry/react, etc.) work
without modification for plain error reporting:
Sentry.init({
dsn: process.env.GLITCHTIP_DSN, // looks like a Sentry DSN
});
Sentry.captureException(new Error("hello"));
Do not enable tracesSampleRate, replaysSessionSampleRate, or
profilesSampleRate — those payloads are rejected. If you call
Sentry.startTransaction(...), GlitchTip silently drops the span data;
nothing breaks, but you also do not see traces.
For OpenTelemetry ingest (Phase 02 task #33) GlitchTip is not a viable backend.
Compose (light, 4-container)
The following Compose file runs on Coolify exactly like the Sentry stack
but with 4 services instead of 10. Save under
infra/glitchtip/docker-compose.yml (NOT committed today; this is the
reference document so we can stand it up quickly if needed).
version: "3.8"
networks:
default:
name: glitchtip-net
coolify:
external: true
services:
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${GLITCHTIP_DB:-glitchtip}
POSTGRES_USER: ${GLITCHTIP_DB_USER:-glitchtip}
POSTGRES_PASSWORD: ${GLITCHTIP_DB_PASSWORD:?must be set in .env}
volumes:
- /data/coolify/services/glitchtip/postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "${GLITCHTIP_DB_USER:-glitchtip}"]
interval: 10s
retries: 6
valkey:
# GlitchTip 6.x uses Valkey (Redis fork) as cache + broker. Pin to v7
# to match Coolify's existing Redis container ABI.
image: valkey/valkey:7-alpine
volumes:
- /data/coolify/services/glitchtip/valkey-data:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 10s
retries: 6
web:
image: glitchtip/glitchtip:v6.1.6
depends_on:
postgres:
condition: service_healthy
valkey:
condition: service_healthy
environment:
DATABASE_URL: postgres://${GLITCHTIP_DB_USER:-glitchtip}:${GLITCHTIP_DB_PASSWORD}@postgres:5432/${GLITCHTIP_DB:-glitchtip}
REDIS_URL: redis://valkey:6379/0
SECRET_KEY: ${GLITCHTIP_SECRET_KEY:?generate with python -c "import secrets; print(secrets.token_urlsafe(50))"}
GLITCHTIP_DOMAIN: ${GLITCHTIP_BASE_URL:-https://glitchtip.boiler.saas-ctrl.com}
DEFAULT_FROM_EMAIL: ${GLITCHTIP_FROM_EMAIL:-glitchtip@boiler.saas-ctrl.com}
ENABLE_USER_REGISTRATION: "false" # invite-only, matches Sentry hardening
ENABLE_ORGANIZATION_CREATION: "false"
CELERY_WORKER_AUTOSCALE: "1,3"
volumes:
- /data/coolify/services/glitchtip/uploads:/code/uploads
networks:
- default
- coolify
labels:
- "traefik.enable=true"
- "traefik.docker.network=coolify"
- "traefik.http.routers.glitchtip.rule=Host(`glitchtip.boiler.saas-ctrl.com`)"
- "traefik.http.routers.glitchtip.entrypoints=https"
- "traefik.http.routers.glitchtip.tls=true"
- "traefik.http.routers.glitchtip.tls.certresolver=letsencrypt"
- "traefik.http.services.glitchtip.loadbalancer.server.port=8000"
worker:
image: glitchtip/glitchtip:v6.1.6
command: ./bin/run-celery-with-beat.sh
depends_on:
postgres:
condition: service_healthy
valkey:
condition: service_healthy
environment:
DATABASE_URL: postgres://${GLITCHTIP_DB_USER:-glitchtip}:${GLITCHTIP_DB_PASSWORD}@postgres:5432/${GLITCHTIP_DB:-glitchtip}
REDIS_URL: redis://valkey:6379/0
SECRET_KEY: ${GLITCHTIP_SECRET_KEY}
GLITCHTIP_DOMAIN: ${GLITCHTIP_BASE_URL:-https://glitchtip.boiler.saas-ctrl.com}
CELERY_WORKER_AUTOSCALE: "1,3"
volumes:
- /data/coolify/services/glitchtip/uploads:/code/uploads
Note: this Compose includes an implicit migrate step. The web
service of the GlitchTip image runs Django migrations automatically on
startup; no separate migrate command is required. If you want an
explicit one-shot, override with command: ./manage.py migrate.
.env template
GLITCHTIP_BASE_URL=https://glitchtip.boiler.saas-ctrl.com
# Postgres
GLITCHTIP_DB=glitchtip
GLITCHTIP_DB_USER=glitchtip
GLITCHTIP_DB_PASSWORD=replace-me-strong
# Django secret — generate with `python -c "import secrets; print(secrets.token_urlsafe(50))"`
GLITCHTIP_SECRET_KEY=replace-me-50-chars-urlsafe
# Optional: outbound mail. GlitchTip needs this for invitation flows
# even though we disable self-signup.
GLITCHTIP_FROM_EMAIL=glitchtip@boiler.saas-ctrl.com
EMAIL_URL=smtp://smtp.mailjet.net:587/?_user=...&_password=...
Bootstrap
# 1. DNS: glitchtip.boiler.saas-ctrl.com -> 46.225.5.93
# 2. Fill .env, then:
docker compose up -d
# 3. First-superuser:
docker compose exec web ./manage.py createsuperuser
# 4. Log in, create projects, copy DSNs into apps' Coolify secrets.
When to choose which
| Scenario | Recommendation |
|---|---|
| Default production observability | Sentry self-hosted |
| OpenTelemetry traces required | Sentry (GlitchTip cannot ingest OTLP) |
| Replay / Performance / Profiling required | Sentry |
| Throw-away preview environment | GlitchTip |
| < 8 GB RAM available | GlitchTip |
| EU-only data residency on a budget VPS | GlitchTip (both work, but GlitchTip's resource footprint is dramatically smaller) |
Migration paths
- Sentry → GlitchTip: swap the DSN in app
.envs. Historical events are not migrated (different schema). Decommission the Sentry stack after a 7-day overlap window. - GlitchTip → Sentry: same swap, opposite direction. Historical GlitchTip events also do not migrate. Sentry can ingest the GlitchTip DSN format directly.