Hanzo Sentry is a self-hosted Sentry 24.2.0 deployment for error tracking and performance monitoring across all Hanzo, Lux, Zoo, and Pars services.
Category: Hanzo Ecosystem Related Skills: hanzo/hanzo-o11y.md, hanzo/hanzo-kms.md, hanzo/hanzo-id.md, hanzo/hanzo-universe.md
Hanzo Sentry is a self-hosted Sentry 24.2.0 deployment for error tracking and performance monitoring across all Hanzo, Lux, Zoo, and Pars services. It is a fork of getsentry/sentry with a custom Dockerfile branded for Hanzo, configured for OIDC SSO via hanzo.id, and deployed to the hanzo-k8s cluster.
app-sentry client)hanzo-sql.hanzo.svcredis.hanzo.svcghcr.io/hanzoai/sentry:latestFork of getsentry/sentry. Local clone at ~/work/hanzo/sentry/. The GitHub repo hanzoai/sentry does not yet exist as a public fork -- currently origin points to getsentry/sentry and Hanzo customizations live in the self-hosted/ directory and K8s manifests in universe/infra/k8s/sentry/.
hanzo-sql.hanzo.svc (database sentry)redis.hanzo.svc (cache, queues, rate limits, buffers)app-sentry OIDC client for SSO| Item | Value | |------|-------| | UI | https://sentry.hanzo.ai | | Alt domains | sentry.lux.network, sentry.pars.network, sentry.zoo.network | | Port | 9000 (web), internal K8s service | | Image | ghcr.io/hanzoai/sentry:latest | | Base version | Sentry 24.2.0 | | Language | Python 3.11 + TypeScript | | K8s namespace | hanzo | | Deployments | sentry-web (2 replicas), sentry-worker (2 replicas), sentry-cron (1 replica) | | Database | hanzo-sql.hanzo.svc:5432/sentry | | Redis | redis.hanzo.svc:6379 | | Auth | OIDC SSO via hanzo.id (app-sentry) | | KMS project | hanzo-k8s-epiq, path /sentry | | Local clone | ~/work/hanzo/sentry/ | | K8s manifests | ~/work/hanzo/universe/infra/k8s/sentry/ | | Health check | GET /_health/ |
import sentry_sdk
sentry_sdk.init(
dsn="https://<key>@sentry.hanzo.ai/<project-id>",
traces_sample_rate=0.1,
environment="production",
release="[email protected]",
)
const Sentry = require("@sentry/node");
Sentry.init({
dsn: "https://<key>@sentry.hanzo.ai/<project-id>",
tracesSampleRate: 0.1,
environment: "production",
release: "[email protected]",
});
import "github.com/getsentry/sentry-go"
func main() {
sentry.Init(sentry.ClientOptions{
Dsn: "https://<key>@sentry.hanzo.ai/<project-id>",
TracesSampleRate: 0.1,
Environment: "production",
Release: "[email protected]",
})
defer sentry.Flush(2 * time.Second)
}
# compose.yml
services:
sentry-web:
image: ghcr.io/hanzoai/sentry:latest
command: ["sentry", "run", "web"]
ports:
- "9000:9000"
environment:
SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}"
SENTRY_POSTGRES_HOST: postgres
SENTRY_DB_NAME: sentry
SENTRY_DB_USER: sentry
SENTRY_DB_PASSWORD: "${SENTRY_DB_PASSWORD}"
SENTRY_REDIS_HOST: redis
sentry-worker:
image: ghcr.io/hanzoai/sentry:latest
command: ["sentry", "run", "worker"]
environment:
SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}"
SENTRY_POSTGRES_HOST: postgres
SENTRY_DB_NAME: sentry
SENTRY_DB_USER: sentry
SENTRY_DB_PASSWORD: "${SENTRY_DB_PASSWORD}"
SENTRY_REDIS_HOST: redis
sentry-cron:
image: ghcr.io/hanzoai/sentry:latest
command: ["sentry", "run", "cron"]
environment:
SENTRY_SECRET_KEY: "${SENTRY_SECRET_KEY}"
SENTRY_POSTGRES_HOST: postgres
SENTRY_DB_NAME: sentry
SENTRY_DB_USER: sentry
SENTRY_DB_PASSWORD: "${SENTRY_DB_PASSWORD}"
SENTRY_REDIS_HOST: redis
postgres:
image: postgres:16
environment:
POSTGRES_DB: sentry
POSTGRES_USER: sentry
POSTGRES_PASSWORD: "${SENTRY_DB_PASSWORD}"
redis:
image: redis:7-alpine
┌──────────────────────────────────┐
│ K8s Ingress │
│ sentry.hanzo.ai │
│ sentry.lux.network │
│ sentry.pars.network │
│ sentry.zoo.network │
└───────────────┬──────────────────┘
│
┌───────────────▼──────────────────┐
│ sentry-web (2 replicas) │
│ Django + uWSGI on port 9000 │
└──┬────────────┬─────────────┬────┘
│ │ │
┌──────▼──┐ ┌─────▼─────┐ ┌───▼────────┐
│ Postgres │ │ Redis │ │ OTEL │
│ hanzo-sql│ │ (shared) │ │ Collector │
└─────────┘ └───────────┘ └────────────┘
│ │
┌──────▼──┐ ┌─────▼──────────────┐
│ sentry- │ │ sentry-worker │
│ cron │ │ (2 replicas, Celery) │
└─────────┘ └─────────────────────┘
| Component | Command | Replicas | Purpose | |-----------|---------|----------|---------| | sentry-web | sentry run web | 2 | Django web server (uWSGI) | | sentry-worker | sentry run worker | 2 | Celery async task processing | | sentry-cron | sentry run cron | 1 | Scheduled tasks (digests, cleanup) |
A single Sentry instance serves four domains via K8s Ingress. Each domain maps to a separate Sentry organization, allowing per-org project isolation:
sentry.hanzo.ai -- Hanzo AI servicessentry.lux.network -- Lux blockchain nodessentry.pars.network -- Pars network servicessentry.zoo.network -- Zoo Labs experimentsSSO is via OIDC against hanzo.id:
sentry.hanzo.ai and clicks "SSO Login"hanzo.id for authentication (client app-sentry)The self-hosted/Dockerfile in the local clone contains Hanzo-specific changes:
[email protected] maintainer and Hanzo brandingghcr.io/hanzoai/sentry as image sourceself-hosted/sentry.conf.py and self-hosted/config.yml into /etc/sentry/tini + gosu for proper signal handlingSecrets are managed via the KMSSecret CRD that syncs from kms.hanzo.ai:
# kms-secrets.yaml
spec:
hostAPI: https://kms.hanzo.ai/api
managedSecretReference:
secretName: sentry-secrets
secretNamespace: hanzo
authentication:
universalAuth:
secretsScope:
projectSlug: hanzo-k8s-epiq
envSlug: prod
secretsPath: /sentry
Required secrets: secret-key, db-password, oidc-client-secret, commerce-api-key (optional).
# Database (PostgreSQL)
SENTRY_POSTGRES_HOST=hanzo-sql.hanzo.svc
SENTRY_DB_NAME=sentry
SENTRY_DB_USER=sentry
SENTRY_DB_PASSWORD=<from KMS>
SENTRY_DB_PORT=5432
# Redis
SENTRY_REDIS_HOST=redis.hanzo.svc
SENTRY_REDIS_PORT=6379
# Core
SENTRY_SECRET_KEY=<from KMS>
# OIDC SSO
SENTRY_OIDC_ENABLED=true
SENTRY_OIDC_ISSUER=https://hanzo.id
SENTRY_OIDC_CLIENT_ID=app-sentry
SENTRY_OIDC_CLIENT_SECRET=<from KMS>
# Observability
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.hanzo.svc:4318
OTEL_SERVICE_NAME=sentry
# Optional: Commerce billing
HANZO_COMMERCE_URL=https://commerce.hanzo.ai
HANZO_COMMERCE_API_KEY=<from KMS>
cd ~/work/hanzo/sentry
# Python setup (uses direnv + pyenv, not uv — upstream pattern)
make develop
# Run dependent services (Postgres, Redis, Kafka, etc.)
make run-dependent-services
# Apply database migrations
make apply-migrations
# Start web server
sentry run web
# In another terminal: start worker
sentry run worker
# Run Python tests
make test-python-ci
# Run JavaScript tests
make test-js
| Issue | Cause | Solution | |-------|-------|----------| | OIDC login fails | app-sentry not configured in IAM | Create OIDC client at hanzo.id with redirect URI https://sentry.hanzo.ai/auth/sso/ | | Redis connection error | Missing SENTRY_REDIS_HOST | Ensure redis.hanzo.svc is reachable in cluster | | SENTRY_SECRET_KEY is undefined | KMS sync not running | Verify sentry-secrets K8s secret exists in hanzo namespace | | Migration errors | DB not created | Run sentry upgrade to create tables and apply migrations | | Worker not processing | Celery not connected to broker | Check Redis connectivity or RabbitMQ config | | Health check failing | Sentry not fully started | Wait for initialDelaySeconds (60s); check logs for startup errors | | npm ci fails | Peer dep conflicts | Use npm install with .npmrc containing legacy-peer-deps=true |
hanzo/hanzo-o11y.md - Observability stack (OTEL, Prometheus, Grafana)hanzo/hanzo-id.md - IAM and OIDC SSO configurationhanzo/hanzo-kms.md - Secret management via KMSSecret CRDshanzo/hanzo-universe.md - Production K8s infrastructure and manifestshanzo/hanzo-database.md - Shared PostgreSQL (hanzo-sql)Last Updated: 2026-03-13 Category: Hanzo Ecosystem Related: sentry, error-tracking, monitoring, observability, self-hosted Prerequisites: Kubernetes, PostgreSQL, Redis, OIDC basics