rafalmasiarek / dashboard-kit-addon-geoip
GeoIP middleware and log processor addon for dashboard-kit
Package info
github.com/rafalmasiarek/php-dashboard-kit-addon-geoip
pkg:composer/rafalmasiarek/dashboard-kit-addon-geoip
Requires
- php: >=8.2
- monolog/monolog: ^3
- psr/http-server-middleware: ^1
- rafalmasiarek/dashboard-kit: *
- slim/psr7: ^1
- slim/slim: ^4
Requires (Dev)
None
Suggests
- geoip2/geoip2: Required for the built-in MaxMindDriver (^4.0)
- rafalmasiarek/real-ip-resolver: Resolves the real client IP behind proxies; injected automatically when dashboard-kit is used (^2.0)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-13 02:13:57 UTC
README
GeoIP middleware and log enrichment addon for dashboard-kit.
Resolves the client IP to country, city, and region on every request. Stores results in $_SERVER (compatible with nginx ngx_http_geoip_module) and enriches all Monolog log channels with geo context fields.
Installation
composer require rafalmasiarek/dashboard-kit-addon-geoip
For the built-in MaxMind driver, also install:
composer require geoip2/geoip2
Download a free GeoLite2-City.mmdb database from MaxMind.
Usage
use rafalmasiarek\DashboardKit\Dashboard; use rafalmasiarek\DashboardKitGeoIp\GeoIpAddon; $dashboard = Dashboard::create(__DIR__ . '/../', [ 'geoip' => [ 'db_path' => __DIR__ . '/../storage/GeoLite2-City.mmdb', 'log_days' => 30, ], ]); GeoIpAddon::register($dashboard->getApp(), $dashboard->getContainer()); $dashboard->run();
Custom driver
Bind a custom driver before calling register(). The built-in MaxMind driver is skipped automatically.
use rafalmasiarek\DashboardKitGeoIp\GeoIpAddon; use rafalmasiarek\DashboardKitGeoIp\GeoIpDriverInterface; use rafalmasiarek\DashboardKitGeoIp\GeoIpResult; final class MyDriver implements GeoIpDriverInterface { public function resolve(string $ip): GeoIpResult { // never throw — return empty GeoIpResult on any failure return new GeoIpResult( country: 'Poland', countryCode: 'PL', city: 'Warsaw', region: 'Masovian Voivodeship', ); } } $container->set(GeoIpDriverInterface::class, fn() => new MyDriver()); GeoIpAddon::register($dashboard->getApp(), $container);
HTTP driver tips
For HTTP-based drivers (ip-api.com, ipinfo.io, custom API):
- Use cURL — supports HTTPS and configurable timeout
- Accept a configurable URL template with
%sfor the IP - Point the URL at a Cloudflare Worker to get automatic retries, HTTPS, and rate-limit handling
final class IpApiDriver implements GeoIpDriverInterface { public function __construct( private readonly string $url = 'http://ip-api.com/json/%s?fields=country,countryCode,city,regionName', private readonly int $timeoutMs = 3000, ) {} public function resolve(string $ip): GeoIpResult { ... } } // point at CF Worker for retries and HTTPS: $container->set(GeoIpDriverInterface::class, fn() => new IpApiDriver( url: 'https://geoip.example.workers.dev/%s', ));
$_SERVER keys
After the middleware runs, the following keys are available globally:
| Key | Example value |
|---|---|
GEOIP_COUNTRY |
Poland |
GEOIP_COUNTRY_CODE |
PL |
GEOIP_CITY |
Warsaw |
GEOIP_REGION |
Masovian Voivodeship |
Keys already set by nginx or Cloudflare are never overwritten.
Log enrichment
All Monolog channels (app, audit, error) automatically receive geo context on every log record:
req.country — full country name
req.country_code — ISO 3166-1 alpha-2 code
req.city — city name
geoip.log
Each driver call produces one audit line in {logs_dir}/geoip.log:
[2026-07-17 12:34:56] [level=info] [channel=geoip] resolved req.id=550e8400-... req.ip=1.2.3.4 duration_ms=42.3 country=Poland country_code=PL city=Warsaw region=Masovian\ Voivodeship
req.id appears automatically when dashboard-kit-request-id is registered before this addon.
Custom log formatter
Default format is KvLineFormatter (key=value lines). Override before register():
use Monolog\Formatter\JsonFormatter; $container->set('geoip.log.formatter', fn() => new JsonFormatter()); GeoIpAddon::register($dashboard->getApp(), $container);
Configuration reference
'geoip' => [ 'db_path' => '/path/to/GeoLite2-City.mmdb', // required for MaxMindDriver; omit to disable plugin 'log_days' => 30, // geoip.log retention in days ],
When db_path is not set and no custom driver is bound in the container, GeoIpAddon::register() does nothing — no middleware is added and no log processor is registered. This allows the addon call to remain in index.php without crashing when the database file is not yet available.
Requirements
- PHP 8.2+
- dashboard-kit
- monolog/monolog ^3
- geoip2/geoip2 ^4.0 (only for MaxMindDriver)
License
Business Source License 1.1 — see LICENSE. For alternative licensing, contact us.