Keen-Kestrel
Docker app from Ferdinand99's Repository
Overview
Readme
View on GitHub
Self-hosted error tracking and privacy-friendly analytics in one small binary.
Status: v0.2 "analytics", an early release (Docker image only). Error tracking works end to end in 26 languages: the official Sentry SDKs send events, which are scrubbed of personal data, grouped into issues and stored; issue and event pages with search, live updates, stack traces and triage; iOS and macOS crashes symbolicated from dSYMs uploaded with
sentry-cli; alerts for new issues, regressions, spikes and a release's first crash to ~40 notification channels (Slack, Discord, Teams, Telegram, ntfy, email, webhooks …); release health with crash-free sessions and users; and a REST API, OpenAPI document and MCP tools for all of it. Web analytics: a script under 2 KB, no cookies and no stored IP addresses, a Web tab with visitors, pageviews, pages, referrers, UTM, browsers and devices, filters and live current visitors, and it respects Global Privacy Control. App analytics with the KestrelKit Swift package: an App tab with daily, weekly and monthly active users, sessions, signal types, version adoption, OS versions, devices and locales, a signal explorer for payloads, and each release's adoption next to its crash-free rate. Installers and Unraid/Proxmox templates come by v1.0. The translations are unreviewed drafts. Sending errors to Kestrel shows how to point each SDK at it, upload dSYMs and set up alerts; Web analytics shows how to add the snippet and what is kept; App analytics does the same for KestrelKit. The design is indocs/design.md; to build and run it, seedocs/development.md.
Keen Kestrel answers two questions about the apps and sites you run:
- What broke? Errors and crashes from the official Sentry SDKs (iOS/Swift, JavaScript, Rust, Python,
Go and more) work unchanged. Issues are grouped, alerts go to the same ~40 channels as
Vigilant Vole, and iOS crashes are symbolicated from the
dSYMs that
sentry-cliuploads. - How is it used? App signals and website pageviews without cookies or stored IP addresses, with dashboards for users, versions, devices, pages and referrers.
One Rust binary and SQLite: no Kafka, ClickHouse, Redis or Postgres. It shares its design language and foundations with Vigilant Vole and runs on Docker, Unraid, Proxmox or plain Linux.
Install
Kestrel runs as one container with its data in a single folder:
mkdir keen-kestrel && cd keen-kestrel
curl -fsSLO https://raw.githubusercontent.com/Ferdinand99/Keen-Kestrel/main/docker-compose.yml
docker compose up -d
Then open http://<host>:3002/setup to create the first admin, create a project and copy its DSN.
Set the address your apps use under Settings → General (public URL), or as KK_PUBLIC_URL in
docker-compose.yml, which is stored there at every start: it goes into the DSNs and alert links. Put Kestrel
behind HTTPS with KK_TRUST_PROXY=1 when it's reachable from the internet. Images
are on GHCR for amd64 and arm64: ghcr.io/ferdinand99/keen-kestrel:<version> or :latest.
Planned for v1
| Errors | Analytics |
|---|---|
| Sentry-compatible ingest (envelopes, sessions, feedback, attachments) | App signals via the KestrelKit Swift package |
| Issue grouping, search, resolve/ignore/merge, regressions | Web pageviews via a script under 2 KB |
iOS/macOS symbolication from dSYMs (sentry-cli compatible) |
Daily, weekly and monthly users, versions, devices, locales |
| Release health: crash-free sessions and users | Pages, referrers, UTM, browsers |
| Alerts: new issue, regression, spike, first crash in a release | No cookies, no stored IPs, daily-rotating salts |
| REST API, OpenAPI, MCP tools for coding agents | Same projects, keys and releases as errors |
Not in v1: performance tracing, session replay, JavaScript source maps (planned for v1.1), funnels and
cohorts. See docs/design.md for the full scope and the phases.
License
Requirements
Categories
Related apps
Explore more like this
Explore allDetails
ghcr.io/ferdinand99/keen-kestrel:latestRuntime arguments
- Web UI
http://[IP]:[PORT:3002]/- Network
bridge- Shell
sh- Privileged
- false
Template configuration
Web interface, API, ingest (Sentry SDKs, KestrelKit, k.js) and sentry-cli uploads.
- Target
- 3002
- Default
- 3002
- Value
- 3002
kestrel.sqlite, store.sqlite, uploaded debug files, session key and pre-migration backups. Ownership is set to PUID:PGID on every start.
- Target
- /data
- Default
- /mnt/user/appdata/keen-kestrel
- Value
- /mnt/user/appdata/keen-kestrel
The public address apps and sites use, e.g. https://kestrel.example.com. Used in DSNs, the k.js snippet and alert links. Without it, each request's own address is used.
Set to 1 when Kestrel is reached through a reverse proxy or tunnel (SWAG, Nginx Proxy Manager, Traefik, Pangolin) that sets X-Forwarded-* headers.
- Default
- 0
- Value
- 0
Optional. When set, the first-run /setup page only opens with ?token=VALUE, so nobody else can create the admin account on an exposed instance.
Optional second port inside the container that serves only ingest and /healthz, so the admin UI can stay on the LAN. Also map that port below if you use it.
- Target
- KK_INGEST_PORT
User id the app runs as (Unraid: 99 = nobody).
- Default
- 99
- Value
- 99
Group id the app runs as (Unraid: 100 = users).
- Default
- 100
- Value
- 100
Time zone for log timestamps.
- Default
- Europe/Oslo
- Value
- Europe/Oslo
Log level filter.
- Default
- info
- Value
- info