No description
  • Rust 95.7%
  • Dockerfile 4.3%
Find a file
Taylor Silenzio 71258885f1
build: pin Rust builder to 1.95.0 for edition 2024 support
rust:1.83 predates edition 2024 (stabilized in 1.85), so the cpufeatures
0.3.0 transitive dep fails to parse. Pin the exact local toolchain
version, bookworm variant to match the runtime stage's glibc.
2026-06-09 14:58:01 -05:00
migrations feat: enrich events with ASN org and capture UTM campaign params 2026-06-08 17:24:00 -05:00
src feat: surface ASN org and UTM data in the viewer 2026-06-08 17:24:13 -05:00
.dockerignore build: add Dockerfile, env example, and README 2026-04-27 01:37:50 -05:00
.env.example build: add Dockerfile, env example, and README 2026-04-27 01:37:50 -05:00
.gitignore chore: initial gitignore 2026-04-27 01:35:35 -05:00
Cargo.lock feat: enrich events with MaxMind geo and uap-core UA parsing 2026-04-27 02:34:57 -05:00
Cargo.toml feat: enrich events with MaxMind geo and uap-core UA parsing 2026-04-27 02:34:57 -05:00
Dockerfile build: pin Rust builder to 1.95.0 for edition 2024 support 2026-06-09 14:58:01 -05:00
README.md feat: enrich events with ASN org and capture UTM campaign params 2026-06-08 17:24:00 -05:00

trace

Personal visitor analytics for tsilenz.io. Cookie-based first-party tracking, rich event capture, single-operator HTML viewer.

Private repo. See .docs/SPEC/current/SPEC.md for the full design and .docs/AGENTS.md for the working-session conventions.

Run locally

cp .env.example .env
# edit .env: at minimum, set ADMIN_TOKEN to something real
COOKIE_SECURE=false cargo run

Then in another shell:

# fire a test event
curl -i -c cookies.txt -b cookies.txt \
  -H 'content-type: application/json' \
  -d '{"event_type":"page_view","path":"/","client_ts":1700000000000}' \
  http://localhost:3000/v1/event

# view the admin dashboard
open "http://localhost:3000/?token=replace-with-bearer-flow"
# (or use curl with Authorization: Bearer <token> header)

Endpoints

  • POST /v1/event — beacon ingest. Accepts JSON, sets tid cookie if absent, writes to SQLite.
  • GET / — admin index of visitors. Bearer auth via Authorization: Bearer <ADMIN_TOKEN>.
  • GET /v/:cookie_id — per-visitor timeline.
  • GET /healthz — health check, returns ok.

Deploy

Dockerfile is multi-stage and produces a debian-slim runtime image. Dokploy pulls from Forgejo and rebuilds on push. Caddy fronts with HTTPS via Cloudflare DNS validation. SQLite file lives on a bind-mounted ZFS dataset under /data in the container.

Required env vars at deploy time:

  • ADMIN_TOKEN — bearer token for the viewer
  • ALLOWED_ORIGIN — homepage origin (e.g. https://tsilenz.io) for CORS

Optional:

  • BIND (default 0.0.0.0:3000)
  • DATABASE_URL (default sqlite:///data/trace.db?mode=rwc)
  • COOKIE_SECURE (default true; set false only for local http)
  • MAXMIND_ASN_DB_PATH (default /usr/share/maxmind/GeoLite2-ASN.mmdb; fail-soft if absent)
  • RUST_LOG

Project layout

trace/
├── Cargo.toml
├── Dockerfile
├── migrations/
│   └── 0001_init.sql
├── src/
│   ├── main.rs       (axum bootstrap, env wiring, routes, layers)
│   ├── state.rs      (shared AppState)
│   ├── ingest.rs     (POST /v1/event, cookie set, DB write)
│   └── viewer.rs     (GET /, GET /v/:id, bearer-auth, maud HTML)
└── .docs/            (separate gitignored repo, see .docs/AGENTS.md)