Self-hosted observability for teams that outgrew free tiers but will never get a Splunk budget.
Logbox ships a pre-wired Grafana + Loki + Grafana Alloy stack with content packs — drop-in dashboards, alerts, and scrape rules for common sources — plus a small-host ops profile (retention, resource caps, doctor/backup) so cost stays predictable.
After nearly a decade on Splunk, the gap this fills is simple: searchable logs, opinionated dashboards, and alerts that work — docker compose up, not a platform team and a platform tax.
flowchart LR
Sources[Apps / Docker / Nginx] --> Alloy[Alloy platform + packs]
Alloy --> Loki[Loki 14d retention]
Loki --> Grafana[Grafana UI + alerts]
| Demo | ./scripts/demo |
| Ops | operations.md · cost.md |
| Splunk map | from-splunk.md |
| Portfolio blurb | portfolio.md |
| Security | SECURITY.md |
Status: Portfolio / SMB sandbox (v0.3). Single-node, not a multi-tenant SIEM. Built on Grafana Loki/Alloy — the value is packaging, content packs, and an honest cost/ops story.
- Content packs (
app,auth,nginx) — enable/disable like lightweight Splunk apps - 14-day Loki retention by default (compactor on) so disks do not grow forever
- dev / small Compose profiles — laptop vs ~4 GB VPS resource caps
scripts/doctor, backup, restore for day-2 ops- Grafana Alloy: Docker logs, JSON app logs, syslog, nginx combined access
- Grafana 11.6 with provisioned datasources, pack dashboards, and unified alerting
- Synthetic producers so panels and alerts have immediate data
- Alloy UI at http://localhost:12345 for pipeline debugging
- Docker Engine 20.10+ and Docker Compose v2
- macOS or Linux host (paths assume a Unix-like system)
git clone https://github.com/jreis/logbox.git
cd logbox
# Guided portfolio demo (packs → stack → doctor → LogQL → UI URLs)
./scripts/demo
# Or just start the stack
./scripts/upProduction-shaped on a small VM (no generators, memory caps):
./scripts/up --small --no-demoOpen Grafana at http://localhost:3000.
Default credentials:
admin/admin— change on first login. Do not expose this stack to the public internet as-is (SECURITY.md).
Dashboards live under LogBox:
- Application Errors — error rates and recent ERROR lines (
pack:app) - Auth & Security Events — failed logins (
pack:auth) - Nginx Access — status rates, top paths, 5xx (
pack:nginx)
./scripts/pack list
./scripts/pack enable app auth nginx
./scripts/pack disable auth
./scripts/pack info nginxSee packs/README.md. Coming from Splunk? Read docs/from-splunk.md.
Point a real service at the app pack — or run the included sample:
./scripts/pack enable app
./scripts/up --no-demo
docker compose --profile sample up -d --build
curl -s http://localhost:8080/health
# Grafana → Application Errors → svc=my-dotnet-apiDetails: samples/dotnet-api/README.md.
curl -s --get http://localhost:3100/loki/api/v1/query \
--data-urlencode 'query=sum by (svc)(count_over_time({job="app", level="ERROR"}[5m]))'You should see a series for svc="my-dotnet-api" with non-zero counts.
[apps / docker / files] → Alloy (platform + pack stages) → Loki (14d retention) → Grafana (pack UI + alerts)
| Path | Role |
|---|---|
platform/ |
Always-on Loki, Alloy base scrape, Grafana datasource & notification plumbing |
packs/<id>/ |
Optional content: Alloy snippets, dashboards, alerts |
compose/small.yml |
Memory/CPU caps for small hosts |
.logbox/ |
Generated config mounted by Compose (regenerate with scripts/pack) |
scripts/pack |
Enable / disable / list packs |
scripts/up |
Ensure packs + start stack (--small, --no-demo) |
scripts/demo |
Guided portfolio walkthrough (docs/demo.md) |
scripts/doctor |
Health checks (containers, HTTP, volumes) |
scripts/backup / restore |
Config (and optional volume) backup |
Details: docs/architecture.md · docs/operations.md · docs/cost.md.
- loki —
platform/loki/loki-config.yml, volumeloki_data, port3100, retention 14d - alloy — generated
.logbox/alloy/config.alloy(platform Docker/syslog + enabled pack stages) - grafana — generated
.logbox/grafana/provisioning(datasources, pack dashboards, pack alert rules) - loggen-* — profile
demo(orpack-app/pack-auth/pack-nginx); omit with--no-demo
| Pack | Dashboard UID | Alert |
|---|---|---|
app |
pack-app-errors |
Error spike ≥50/min (pack-app-errors-1m) |
auth |
pack-auth-events |
Failed login burst ≥10/5m (pack-auth-failed-logins-5m, severity high) |
nginx |
pack-nginx-access |
5xx spike ≥20/min (pack-nginx-5xx-1m, severity high) |
Contact points live under platform/grafana/provisioning/alerting/ (placeholders only — replace before relying on delivery).
| Concern | Default / tool |
|---|---|
| Retention | 14 days (limits_config.retention_period: 336h) |
| Small host | ./scripts/up --small → compose/small.yml |
| Health | ./scripts/doctor |
| Backup config | ./scripts/backup |
| TCO framing | docs/cost.md |
Pack River files live under packs/<id>/alloy/; platform scrape is platform/alloy/base.alloy. After edits:
./scripts/pack regenerate
docker compose up -d alloy- Change log locations: edit
path_targetsin the relevant pack or platform file; mount host paths indocker-compose.yml. - Labels / parsing:
loki.processstages (json,labels,regex,multiline, …). - Debug: http://localhost:12345 or
docker compose logs -f alloy.
./scripts/demo # guided walkthrough (see docs/demo.md)
./scripts/demo --auto # no Enter prompts (good for recordings)
./scripts/up # demo, dev profile
./scripts/up --small --no-demo # small VPS, real traffic only
./scripts/doctor
./scripts/backup
./scripts/pack list
docker compose --profile demo pull
docker compose logs -f alloy
docker compose down # stop containers
docker compose down -v # also wipe Loki/Grafana volumes- Dashboard shows no data:
- Confirm packs are enabled:
./scripts/pack status - Run
./scripts/doctor - Alloy healthy: http://localhost:12345 or
docker compose logs alloy - Labels exist:
{job="app", level="ERROR"}or{job="docker"} - Generators running:
docker compose --profile demo ps
- Confirm packs are enabled:
- Missing
.logbox/: run./scripts/pack ensurebefore Compose. - OOM / host pressure: use
./scripts/up --small --no-demoand lower retention (see operations.md). - Permission errors reading host logs: adjust volume mounts and file permissions.
- Alloy can't see Docker logs: mount
/var/run/docker.sock; grant Docker Desktop file sharing if needed. - Alert delivery fails: set real addresses/webhooks in
platform/grafana/provisioning/alerting/contact-points.yml, then./scripts/pack regenerateand restart Grafana.
Ideas for later — none required to use v0.3:
- Correlated service health (metrics + logs)
- Optional NL → LogQL using pack
queries/as context - More packs as needed (e.g. postgres) — the
nginxpack is the template
Logbox configuration, packs, and scripts are MIT (LICENSE).
Runtime images are upstream open source (Grafana Loki, Grafana Alloy, Grafana OSS, Alpine, etc.) under their respective licenses. Grafana® and related marks belong to Grafana Labs.
Portfolio write-up text: docs/portfolio.md · Changes: CHANGELOG.md
Happy logging.