Environment configuration

The file bridge can't write .env files, so copy these by hand.

Append to your dev .env

# โ”€โ”€โ”€ Telemetry store โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# postgres (default, dev) | clickhouse (production / SaaS)
TELEMETRY_STORE=postgres
CLICKHOUSE_URL=http://localhost:8123
CLICKHOUSE_DB=sentinel
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=

# Optional read replica for dashboard queries (managed PG providers hand these out)
# DATABASE_REPLICA_URL=

# โ”€โ”€โ”€ Retention โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
RETENTION_LOGS_DAYS=30
RETENTION_METRICS_DAYS=400

Create .env.production from this template

POSTGRES_DB=sentinel
POSTGRES_USER=sentinel
POSTGRES_PASSWORD=change-me
CLICKHOUSE_DB=sentinel
CLICKHOUSE_USER=sentinel
CLICKHOUSE_PASSWORD=change-me
# Public URL the browser uses to reach the API
PUBLIC_API_URL=https://api.sentrinel.example.com
# Optional managed-Postgres read replica
DATABASE_REPLICA_URL=
RETENTION_LOGS_DAYS=30
RETENTION_METRICS_DAYS=400

Trying the ClickHouse path locally

docker compose --profile ch up -d          # Postgres + ClickHouse
bun run --cwd packages/db ch:migrate       # apply ClickHouse schema
# set TELEMETRY_STORE=clickhouse in .env, then:
bun run dev
curl localhost:3001/health                 # โ†’ telemetryStore: "clickhouse"

New in the completed roadmap

# โ”€โ”€โ”€ Authentication & multi-tenancy โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Leave unset for a single-user self-hosted install. Set to true for a SaaS
# deployment: the dashboard API then requires a session AND scopes every query
# to the caller's organization. Ingest, cron check-ins, and public status pages
# are always exempt (they carry their own credentials).
SENTRINEL_REQUIRE_AUTH=true

# Self-serve signup is on by default and gives each new account its own
# organization. Set this to lock a private deployment to invite-only โ€” the very
# first account can always be created, or there'd be no way in.
# SENTRINEL_DISABLE_SIGNUP=true

What SENTRINEL_REQUIRE_AUTH=true changes

off (default) on
Dashboard API open 401 without a session
?appId= from another org served 403
Unscoped lists (apps, issues, alerts, keysโ€ฆ) everything only your org's
Live tail (SSE) all traffic only your org's
SQL console unrestricted rows filtered to your apps (project app_id)

Tenant isolation is enforced in packages/api/src/lib/guard.ts and lib/tenancy.ts, and covered by packages/api/tests/tenancy.test.ts.

Sending OpenTelemetry traces

Any OTel SDK or Collector can export to Sentrinel:

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:3001
OTEL_EXPORTER_OTLP_PROTOCOL=http/json
OTEL_EXPORTER_OTLP_HEADERS=x-api-key=<your app key>

GenAI spans (gen_ai.request.model + gen_ai.usage.*_tokens) are additionally priced and shown on the LLM cost page.

Cron monitoring

Create a monitor in the dashboard, then add its check-in URL to the job:

# at the end of the job
curl -fsS https://sentrinel.example.com/api/checkin/<token>

# or, for long jobs, report start / duration / explicit failure
curl -fsS "https://sentrinel.example.com/api/checkin/<token>?state=start"
curl -fsS "https://sentrinel.example.com/api/checkin/<token>?duration=1430"
curl -fsS "https://sentrinel.example.com/api/checkin/<token>?state=fail"

Deploy markers

Pass a version to the plugin and every release is recorded automatically:

sentrinelPlugin({ appName: "my-api", version: process.env.GIT_SHA })