Real-time access monitor for internet-exposed services. Detects threats via deterministic heuristics + AI (local ONNX / optional LLM), computes a risk level per request/IP, and acts automatically: block, edge challenge (Cloudflare), rate-limit, or webhook alert.
Commercial WAFs cover the obvious. Sentry covers the rest: encoded payloads, sensitive-path scanning, malicious crawlers, anomalous access patterns — combining fast rules (zero known false positives) with AI for the unknown. All in a single Rust binary, running locally, never shipping your logs to a third party.
| Layer | Technology |
|---|---|
| Language | Rust 2021 (MSRV 1.80) |
| Async | tokio |
| CLI / TUI | clap (derive) + ratatui + crossterm |
| Storage | Postgres (sqlx) |
| Config | figment (TOML + env overlay, SENTRY_ prefix) |
| AI | ort (ONNX, local) + LlmProvider trait |
| Edge actions | ChallengeProvider trait (Cloudflare, …) |
| Geo/ASN | maxminddb (GeoLite2) |
Sources (plugins) → Pipeline → Actions (plugins)
nginx access.log rules engine local blocklist
tcp capture heuristics Cloudflare challenge
syslog AI (ONNX/LLM) webhook (Discord/Slack)
geo/ASN enrich log + persist
Every source and action is a plugin behind the Source and Action traits.
The core (sentry-core) is pure: it defines contracts, no heavy I/O. See
ARCHITECTURE.md for the full design, or browse the
live docs at https://sentry.lucas-romero.com.
Full docs live in a separate repo (IDjinn/sentry-docs), mounted as a
submodule under docs/ and deployed to Vercel at
https://sentry.lucas-romero.com.
- Languages: Portuguese (source) at
/pt, English translation at/en. - Built with: Fumadocs + Next.js 16 + Tailwind v4.
- Diagram support: Mermaid (native plugin).
git clone --recurse-submodules <this-repo>
cd docs
bun install
bun run dev # http://localhost:3000 -> redirects to /ptTo update docs without cloning the main repo:
git clone git@github.com:IDjinn/sentry-docs.git
cd sentry-docs && bun install && bun run devAfter changes are merged into sentry-docs:
git -C docs pull origin main
git add docs
git commit -m "docs: bump sentry-docs"The project logo sentry.png at the repo root is the source of truth. A
copy is committed in sentry-docs/public/sentry.png — update it there
when the root PNG changes.
crates/
├── sentry-core/ # Event, ProtocolData, traits, rules engine
├── sentry-storage/ # Postgres (sqlx) + migrations
├── sentry-ai/ # ThreatModel trait (ONNX) + LlmProvider
├── sentry-geo/ # maxminddb geo/ASN enrichment
├── sentry-source-nginx/ # Source plugin: access.log tail
├── sentry-action-cloudflare/ # ChallengeProvider: block/challenge via CF API
├── sentry-action-webhook/ # Action plugin: alerts
├── sentry-action-blocklist/ # Action plugin: in-memory blocklist
└── sentry-cli/ # binary: clap + ratatui + daemon
docker compose -f deploy/docker/docker-compose.yml up -dSecrets go in env vars, never in config:
export SENTRY_CF_TOKEN=xxx # Cloudflare API token (optional)
export SENTRY_CF_ZONE=yyy # Cloudflare zone ID (optional)
export SENTRY_LLM_KEY=zzz # OpenRouter key (optional)
export SENTRY_STORAGE__POSTGRES__URL=postgres://sentry:secret@db/sentrycargo build --release
./target/debug/sentry config validate
./target/debug/sentry runCopy config/sentry.example.toml → sentry.toml and edit. The env overlay
(SENTRY_<SECTION>__<KEY>) overrides any TOML field.
The rules engine runs before heuristics and AI (fast path). Precedence
order: Allow > Block/Challenge/RateLimit > Log/Tag > falls
through to heuristics + AI.
Default packs: vpn_proxy, tor, crawlers_bad, crawlers_good,
sensitive_paths, country_blocklist, http_anomaly, rate_scan. Each
pack runs in shadow (log only), enforce (act), or off.
For production rollout: start with everything in shadow and watch the
logs before switching to enforce.
Edge actions (block / challenge / rate-limit at a CDN/WAF) are
provider-agnostic via the ChallengeProvider trait, mirroring the
LlmProvider pattern. Config uses the canonical form:
[[action]]
type = "challenge"
provider = "cloudflare" # extensible: aws_waf, fastly, ...
[action.options]
mode = "managed_challenge" # block | js_challenge | managed_challenge | rate_limit
ttl_secs = 86400The legacy type = "cloudflare" alias is kept for backward compatibility.
Adding a new edge provider = implement ChallengeProvider in a new crate +
one match arm in daemon::build_challenge_action — no changes to
ActionKind, rules, or verdict filtering.
cargo test --all
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warningsLicensed under the PolyForm Noncommercial License 1.0.0.
You may use, copy, modify, and distribute this software for noncommercial
purposes only, with attribution. Commercial use requires a separate commercial
license from the copyright holder. See LICENSE for the full terms.