Skip to content

feat: add GeoIP session location (country/city/coordinates from IP) - #1

Merged
Athenox14 merged 3 commits into
mainfrom
claude/geoip-support-vzazg6
Jul 13, 2026
Merged

feat: add GeoIP session location (country/city/coordinates from IP)#1
Athenox14 merged 3 commits into
mainfrom
claude/geoip-support-vzazg6

Conversation

@Athenox14

@Athenox14 Athenox14 commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds GeoIP enrichment: each session's IP is resolved to country/city/coordinates via a local MaxMind GeoLite2/GeoIP2 .mmdb file (GEOIP_DB_PATH env var), mirroring the existing offline UA-detection approach — no visitor data is ever sent to a third-party geolocation service.
  • Geo is optional: without a database configured (or if it can't be read), lookups just return empty fields; nothing else in the server is affected, and startup never fails because of it.
  • Geo is resolved once per session and stored alongside the existing ip/user_agent columns on the sessions table (added via a safe pragma_table_info + ALTER TABLE migration so existing databases pick up the new columns).
  • Exposes two new GraphQL queries: sessionGeo(projectId, sessionId) and sessionsByCountry(projectId) (a visitors-by-country breakdown).

Changes

  • crates/iris-core/src/geo.rs (new): GeoLookup, a thin wrapper over the maxminddb crate with graceful fallback when no database is configured.
  • crates/iris-core/src/models.rs: new GeoInfo struct.
  • crates/iris-server/src/main.rs: loads GeoLookup from GEOIP_DB_PATH at startup, logs whether it's active.
  • crates/iris-server/src/capture.rs: resolves geo from the request IP on /capture and /batch.
  • crates/iris-server/src/storage.rs: schema migration for the new sessions columns, geo persisted on session upsert, new session_geo/sessions_by_country queries.
  • crates/iris-server/src/schema.rs: new sessionGeo / sessionsByCountry GraphQL queries.
  • README.md / DOC.md: document the new (optional) GEOIP_DB_PATH config and feature.
  • .gitignore: ignore *.mmdb database files.

Test plan

  • cargo build --workspace — builds clean on all default features.
  • cargo test --workspace — all tests pass, including new geo::tests covering the no-database and invalid-IP fallback paths.
  • Ran the server locally without GEOIP_DB_PATH set, posted to /capture with a session, and queried sessionGeo / sessionsByCountry over GraphQL — confirmed graceful empty-geo behavior with no errors.

Resolves each session's IP through a local MaxMind GeoLite2/GeoIP2 mmdb
(GEOIP_DB_PATH), mirroring the existing offline UA-detection approach so
no visitor data is sent to a third-party geolocation API. Optional: with
no database configured, geo fields just stay empty.

Geo is stored per-session (like ip/user_agent already are) and exposed
via two new GraphQL queries: sessionGeo and sessionsByCountry.
Adds a link to MaxMind's free GeoLite2 sign-up, a GraphQL usage example
for the new sessionGeo/sessionsByCountry queries, a French privacy note
in DOC.md, and fixes a stray line-wrap in the README feature list.
Sources a free GeoLite2-derived City .mmdb (IPv4 + IPv6) from
sapics/ip-location-db on first boot and weekly thereafter, cached under
./data/geoip — no signup, no license key to rotate. If the download
fails (no egress, air-gapped deploy), the server still starts and geo
fields just stay empty, same as before.

GeoLookup now opens a list of mmdb readers instead of a single one, so
it can use the split per-family files this source publishes while
still supporting a single combined MaxMind file via GEOIP_DB_PATH,
which skips auto-download entirely.
@Athenox14
Athenox14 force-pushed the claude/geoip-support-vzazg6 branch from 51652d2 to 9f8f75e Compare July 13, 2026 18:56
@Athenox14
Athenox14 merged commit 3c88f99 into main Jul 13, 2026
3 checks passed
@Athenox14
Athenox14 deleted the claude/geoip-support-vzazg6 branch July 13, 2026 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant