geometrikks

geometrikks

Docker app from GilbN's Repository

Overview

GeoMetrikks tails your reverse proxy's access logs, looks up where every request came from with MaxMind GeoLite2, and shows the result on a live map and a traffic analytics dashboard. It reads nginx, Traefik JSON and Caddy JSON logs, detected per file, from a file or from Grafana Loki. The only outbound traffic is the GeoLite2 download and a public-IP lookup that places this server on the map, which you can turn off.

Features:
• Live map with heatmap and marker views, and routes that fly in as requests arrive
• Overview and analytics for requests, bandwidth, latency, status mix, top URLs and user agents, plus a Top ASNs view of the networks your traffic comes from
• Searchable access log history with filters and sorting, a live tail, and a debug view of the raw lines behind parse failures
• CrowdSec integration: active bans next to the traffic that caused them, ban or unban IPs and ranges from the UI, and abuse reports for hosting providers
• Password login, or OpenID Connect sign-in against Authelia, Authentik, Keycloak, Pocket ID or Google
• Multi-source ingestion: tail several files from one instance, or run headless agents on other hosts that write into the same database and show up on Settings > Agents
• Batch import of rotated and archived logs
• Application logs in the UI, plus a login log that fail2ban and CrowdSec can parse

Requirements:
• A TimescaleDB + PostGIS database. Install the companion "geometrikks-timescaledb" template from this repository first, or point the container at your own instance.
• A free MaxMind GeoLite2 account (https://www.maxmind.com/en/geolite2/signup) for the GeoIP databases.
• A free CARTO basemaps API key (https://carto.com/basemaps/apikey) for the map tiles.

See the repository README for full setup steps.

GeoMetrikks Unraid Templates

Unraid Community Apps templates for GeoMetrikks - a real-time geolocation analytics tool that tails your reverse proxy's access logs, does GeoIP lookups, and visualizes traffic on a live interactive map. It reads nginx, Traefik JSON and Caddy JSON logs, from a file or from Grafana Loki, and works out which is which per file.

This repository ships two Docker templates:

Template What it is
geometrikks-timescaledb TimescaleDB + PostGIS database - install this first
geometrikks The GeoMetrikks app and web UI

Setup

1. Install the database

Add geometrikks-timescaledb from Community Apps. Set a POSTGRES_PASSWORD - you'll reuse this exact value in step 2. Leave POSTGRES_USER (geouser) and POSTGRES_DB (geometrikks) at their defaults unless you have a reason to change them.

The DB Port config (default 5432) is exposed to your LAN so the app container can reach it.

The template starts Postgres with timescaledb.max_background_workers=40 (and the matching max_parallel_workers / max_worker_processes). GeoMetrikks registers around 32 TimescaleDB jobs whose refresh policies all fire on the same tick, and the image's default of 16 workers can't cover that: the database log fills with failed to launch job ... out of background workers and continuous aggregates stop refreshing. If you installed this template before September 2026, remove and re-add the container to pick the setting up, or add the three -c flags yourself under Post Arguments.

2. Install the app

Add geometrikks from Community Apps and fill in:

  • DB_HOST - your Unraid server's IP address (e.g. 192.168.1.50)
  • DB_PASSWORD - the same password you set for geometrikks-timescaledb in step 1
  • MAXMINDDB_USER_ID / MAXMINDDB_LICENSE_KEY - your free MaxMind GeoLite2 credentials (see step 3)
  • MAP_CARTO_API_KEY - a free CARTO basemaps key from https://carto.com/basemaps/apikey. CARTO's terms require one per deployment, and keyless map tiles may stop working
  • APP_ADMIN_USER / APP_ADMIN_PASSWORD - your web UI login, or APP_AUTH_DISABLED=true, or an identity provider (see below)
  • Access Logs path - point this at wherever your reverse proxy writes its access logs (defaults to a SWAG-style path; change it for Nginx Proxy Manager, Traefik, Caddy, or whatever you actually run)

Leave DB_PORT/DB_USER/DB_DATABASE at their defaults unless you changed the matching values in step 1.

Signing in with an identity provider

GeoMetrikks 0.17.0 added OpenID Connect login, so the login page can hand you off to Authelia, Authentik, Keycloak, Pocket ID or Google. Four variables switch it on:

  • OIDC_ISSUER - the provider's issuer URL, e.g. https://auth.example.com
  • OIDC_CLIENT_ID / OIDC_CLIENT_SECRET - a confidential client you register for GeoMetrikks
  • OIDC_REDIRECT_URI - https://geo.example.com/api/v1/auth/oidc/callback, registered at the provider exactly as written

Then say who gets in, with OIDC_ALLOWED_USERS (verified email addresses or subject identifiers), OIDC_ALLOWED_GROUPS, or both. One of the two is mandatory and the container refuses to start without it, which beats discovering that every Google account on earth can read your traffic.

Two things to watch for on Unraid:

  • The redirect URI is the public https address of the app, so this needs a TLS reverse proxy in front of the container, and APP_SESSION_SECURE=true with it. http://<unraid-ip>:8000 will not work as a redirect URI, and an https URI with a non-Secure cookie fails validation at startup.
  • Keep APP_ADMIN_PASSWORD set unless you want the provider to be the only way in. With both, the login page shows the provider button and the password form, which is what you want the day Authelia stops answering. Clear it and the password form disappears.

Per provider: Authelia works with the default OIDC_SCOPES (openid profile email groups) and serves groups from its userinfo endpoint, which GeoMetrikks reads. Authentik wants the issuer URL that ends in the application slug, and openid profile email unless you add a groups mapping. Google rejects the groups scope, so use openid profile email there and allow people by email. OIDC_LOGOUT_IDP only does something when the provider advertises an end_session_endpoint; Authelia 4.39 and Google do not, so leave it false for those. Settings > Status tells you whether the discovery document could be fetched.

The upstream README has the rest, including an Authelia client snippet to copy.

PUID / PGID and file ownership

The app container starts as root only long enough to remap its internal user to PUID:PGID, fix ownership of the GeoIP Data and App Logs folders, and then drop privileges - the app itself never runs as root. The template defaults to Unraid's usual 99:100 (nobody:users), which matches the rest of your appdata and the ownership SWAG/Nginx Proxy Manager give their log files, so no manual chown step is needed.

Your Access Logs mount is read-only and is not touched by that fix-up - those files just need to be readable by PUID:PGID on the host.

App logs

The App Logs path mount holds GeoMetrikks' own logs:

  • geometrikks.log - structured JSONL application log
  • login.log - plain-text login/logout/failed-login events, in a format fail2ban and CrowdSec can parse

Both rotate by size and gzip their archives (LOG_MAIN_* / LOG_LOGIN_*). You can also browse and download them in the web UI under Settings -> Logs. Mounting the path is optional but recommended: without it the logs are lost whenever the container is recreated, and host-side tools can't read login.log.

Which log format?

The mount lands at /var/log/access inside the container whatever proxy you run, and LOGPARSER_LOG_PATHS names the file there. The format is detected per file, so Traefik and Caddy JSON logs need nothing beyond the path. Pin it with LOGPARSER_LOG_FORMATS (geometrikks-json, nginx, traefik-json, caddy-json) if detection gets it wrong.

Nginx is the one that needs work on your side: GeoMetrikks reads a keyed JSON log_format you have to add to your nginx.conf. The older positional format still parses, so an existing setup keeps working. Both are in the upstream README.

Tailing several files? LOGPARSER_LOG_PATHS takes a JSON list, and giving LOGPARSER_SERVER_NAME a list of the same length names each file separately, so the UI can filter them as separate servers.

Reading from Grafana Loki

If Alloy or Promtail already ships your proxy's access logs to Loki, GeoMetrikks can read them from there. The template doesn't list the Loki variables, because a blank LOKI_URL stops the app from starting. Add them with "Add another Path, Port, Variable":

  • LOKI_URL - e.g. http://192.168.1.50:3100. Use an address this container can reach, which on the default bridge network means your Unraid server's IP, not localhost.
  • LOKI_QUERIES - one LogQL stream selector, e.g. ``, or a JSON list of them, one source each.
  • LOKI_SERVER_NAMES - optional, one name per selector. Without it every selector gets the first LOGPARSER_SERVER_NAME.

LOKI_USERNAME and LOKI_PASSWORD go together, for a Loki behind basic auth. The file in LOGPARSER_LOG_PATHS is still tailed next to Loki. Loki has to hold the raw access-log line, and Traefik's start-time timestamps need care. The upstream README covers both.

3. Get a free MaxMind GeoLite2 key

GeoMetrikks needs MaxMind's free GeoLite2 databases for GeoIP lookups:

  1. Sign up at https://www.maxmind.com/en/geolite2/signup
  2. Create a license key under your account
  3. Set MAXMINDDB_USER_ID and MAXMINDDB_LICENSE_KEY on the geometrikks template

The template requires both. Without them GeoMetrikks would run in degraded mode, with no GeoIP lookups.

Two databases are downloaded into the GeoIP Data mount: City, which drives the map and geo analytics, and ASN, which records the network behind each request and fills the Top ASNs view. Set GEOIP_ASN_ENABLED=false to skip the second one.

4. Open the web UI

http://<your-unraid-ip>:8000/ - log in with the admin credentials you set in step 2.

Notes

  • Full environment variable reference: https://github.com/GilbN/geometrikks/blob/main/docs/configuration.md. Most of it is exposed as "advanced" settings on the geometrikks template - expand "Show more settings" when adding the container to see log parser tuning, log rotation, analytics retention, and map settings. Settings the template leaves out use the app's defaults, and you can add them with "Add another Path, Port, Variable".
  • LOGPARSER_IGNORE_IPS is worth setting: give it your own public IP (or any CIDR) to drop that traffic entirely - no geo event, access log or debug row. LAN traffic is never ingested in the first place, so this is for your own WAN-side hits.
  • Reaching the UI through a TLS reverse proxy? Set APP_SESSION_SECURE=true, and put your proxy's IP/CIDR in APP_TRUSTED_PROXIES (e.g. 172.17.0.0/16) so client IPs are read from X-Forwarded-For. Leave APP_SESSION_SECURE at false if you browse to http://<unraid-ip>:8000 directly, or logins won't stick.
  • API_LOG_LEVEL is deprecated - use LOG_LEVEL. If an existing container still has it, delete the variable. Leaving it blank stops the app from starting.
  • APP_PROXY_ADVISORY puts a warning on Settings > Status when the traffic in a tailed file comes from CDN or private addresses, which means your proxy is logging the hop in front of it instead of the visitor. Set it to false if that's deliberate (Tailscale-only access, a CDN you front on purpose).
  • APP_MODE is full here and should stay that way. agent turns the container headless: no UI, no API, just tail, geolocate and write into a shared database. It's for a second GeoMetrikks next to another proxy, feeding this one. Give each agent its own APP_INSTANCE_NAME so it gets its own row on Settings > Agents. Two unnamed agents both go by agent and overwrite each other's status.
  • GeoMetrikks 0.21.0 renamed six variables. LOGPARSER_HOST_NAME is now LOGPARSER_SERVER_NAME, and the MAP_HOME_* variables are MAP_SERVER_*: MAP_SERVER_LOCATIONS, MAP_SERVER_LATITUDE, MAP_SERVER_LONGITUDE, MAP_AUTO_DETECT_SERVER_LOCATION and MAP_SERVER_LOCATION_REFRESH_HOURS. The old names work until 1.0, and Settings > Status tells you which ones a container still reads. If a container has an old and a new name set to different values, the app refuses to start. Copy the value you set into the new variable, then delete the old one.
  • The template sets --stop-timeout=20 so the app can finish flushing its ingestion batch on shutdown. Unraid's default of 10 seconds kills it mid-write.
  • GeoMetrikks itself: https://github.com/GilbN/geometrikks

Media gallery

1 / 9

Requirements

Requires a reachable TimescaleDB+PostGIS database (see the companion geometrikks-timescaledb template), a free MaxMind GeoLite2 account for GeoIP downloads, and a free CARTO basemaps API key for the map.
Nginx access logs need a specific log_format. Traefik and Caddy JSON access logs are read as they come. See the repository README for the nginx log_format to use.

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/gilbn/geometrikks:latest
Last Updated2026-10-20
First Seen2026-07-20

Runtime arguments

Web UI
http://[IP]:[PORT:8000]/
Network
bridge
Shell
bash
Privileged
false
Extra Params
--restart=unless-stopped --stop-timeout=20

Template configuration

WebUIPorttcp

HTTP port for the GeoMetrikks web UI.

Target
8000
Default
8000
Access LogsPathro

Host directory holding your reverse proxy's access logs, mounted read-only. The default assumes SWAG. Point it at wherever nginx, Nginx Proxy Manager, Traefik or Caddy writes instead. The files must be readable by PUID:PGID. Whichever proxy you run, the container-side path stays /var/log/access, so that is what LOGPARSER_LOG_PATHS refers to.

Target
/var/log/access
Default
/mnt/cache/appdata/swag/log/nginx
LOGPARSER_LOG_PATHSVariable

Access log file(s) to tail, named as the container sees them under /var/log/access. Single path, or a JSON list [&quot;/var/log/access/access.log&quot;, &quot;/var/log/access/site2/access.log&quot;] for several files.

Default
/var/log/access/access.log
GeoIP DataPathrw

Persistent storage for the downloaded MaxMind GeoLite2 City and ASN databases. The container fixes ownership of this folder to PUID:PGID on every start, so no manual chown is needed.

Target
/app/data/geoip
Default
/mnt/cache/appdata/geometrikks/geoip
DB_HOSTVariable

IP address of your TimescaleDB container, typically your Unraid server's IP if you installed the companion geometrikks-timescaledb template. Do not use localhost or 127.0.0.1, which is this container itself. The database container must be running and its port reachable from here.

DB_PASSWORDVariable

Database password. Must match POSTGRES_PASSWORD in the geometrikks-timescaledb template.

MAXMINDDB_USER_IDVariable

MaxMind account ID, used to download the GeoLite2 databases. Free account: https://www.maxmind.com/en/geolite2/signup

MAXMINDDB_LICENSE_KEYVariable

MaxMind license key, used to download the GeoLite2 databases. Create it under your MaxMind account.

MAP_CARTO_API_KEYVariable

CARTO basemaps API key, sent with every basemap request the browser makes. CARTO's terms require one per deployment and keyless tiles may stop working. Free at https://carto.com/basemaps/apikey. Not a secret: anyone who can open the map can see it.

APP_ADMIN_USERVariable

Web UI login username.

Default
admin
APP_ADMIN_PASSWORDVariable

Web UI login password. Leave it blank only if you set APP_AUTH_DISABLED=true or configured OIDC_* below; otherwise the container refuses to start. With OIDC configured, a password set here keeps the password form next to the provider button, so you can still log in when the provider is down.

LOGPARSER_IGNORE_IPSVariable

IPs/CIDRs the parser drops entirely - no geo event, access log or debug row. Use it to keep your own WAN traffic through the reverse proxy out of the data(LAN traffic is never ingested), e.g. 88.99.77.66. Single value, comma-separated, or a JSON list. Empty (default): nothing is ignored.

DB_PORTVariable

Database port.

Default
5432
DB_USERVariable

Database user. Must match POSTGRES_USER in the geometrikks-timescaledb template.

Default
geouser
DB_DATABASEVariable

Database name. Must match POSTGRES_DB in the geometrikks-timescaledb template.

Default
geometrikks
PUIDVariable

User ID the app runs as. The container starts as root only long enough to remap its internal user and fix ownership of the GeoIP and App Logs folders, then drops privileges. 99 is Unraid's 'nobody' - keep it so the appdata folders match the rest of your shares, and so nginx logs written by SWAG/NPM (which also default to 99:100) stay readable.

Default
99
PGIDVariable

Group ID the app runs as. 100 is Unraid's 'users' group.

Default
100
App LogsPathrw

Where GeoMetrikks writes its own logs: geometrikks.log (structured JSONL) and login.log (plain text, fail2ban/CrowdSec-friendly), plus their gzipped archives. Mounting this keeps logs across container recreation and lets host-side tools read login.log. Ownership is fixed to PUID:PGID on start.

Target
/app/logs
Default
/mnt/cache/appdata/geometrikks/logs
LOG_LEVELVariable

Application log verbosity (DEBUG, INFO, WARNING, ERROR).

Default
INFO
LOGPARSER_SERVER_NAMEVariable

A name you choose for this server, recorded on every request it ingests. It is not your nginx server_name. A JSON list matched to LOGPARSER_LOG_PATHS by position names each file separately, e.g. [&quot;edge-01&quot;, &quot;edge-02&quot;], and the UI then filters them as separate servers. Replaces LOGPARSER_HOST_NAME: copy your value here and delete the old variable, because the app refuses to start when the two differ.

Default
Unraid
LOGPARSER_LOG_FORMATSVariable

Format of the file(s) above: auto (detected per file), geometrikks-json, nginx, traefik-json or caddy-json. One value covers every path, or give a JSON list matched to LOGPARSER_LOG_PATHS by position. Leave at auto unless detection gets it wrong.

Default
auto
APP_INSTANCE_NAMEVariable

Name this container goes by on Settings &gt; Agents, which lists every GeoMetrikks instance writing to the database. Blank: it shows as head, or as agent with APP_MODE=agent. Give every agent its own name, because two unnamed agents share one and overwrite each other's status. Up to 255 characters, no slashes.

APP_SESSION_SECUREVariable

Mark the session cookie Secure so browsers only send it over HTTPS. Set true when you reach the UI through a TLS reverse proxy; leave false if you browse to http://server-ip:8000 directly, or you will not be able to log in. An https OIDC_REDIRECT_URI requires true, and the app will not start otherwise.

Default
false
APP_TRUSTED_PROXIESVariable

Reverse-proxy IPs/CIDRs allowed to supply X-Forwarded-For, e.g. 172.17.0.0/16 for Unraid's docker bridge. Single value, comma-separated, or a JSON list. Empty (default): forwarded headers are never trusted.

APP_AUTH_DISABLEDVariable

Set true ONLY if this container sits behind an authenticating reverse proxy (Authelia, Tailscale, etc). There is then no login and no session: anyone who can reach the container has full access. It cannot be combined with the OIDC_* settings below, and the app will not start if you set both.

Default
false
ANALYTICS_RAW_RETENTION_DAYSVariable

Days to keep raw geo_events and access_logs data.

Default
180
CROWDSEC_LAPI_URLVariable

CrowdSec Local API base URL, including http:// or https://, e.g. http://crowdsec:8080. Without the scheme the connection fails. Leave blank to disable CrowdSec integration.

CROWDSEC_BOUNCER_API_KEYVariable

Bouncer API key (cscli bouncers add geometrikks) - grants read access to CrowdSec decisions.

CROWDSEC_MACHINE_IDVariable

Machine ID (cscli machines add) - optional, enables ban/unban from the GeoMetrikks UI. Set it together with the machine password, or the app will not start.

CROWDSEC_MACHINE_PASSWORDVariable

Machine password - optional, enables ban/unban from the GeoMetrikks UI. Set it together with the machine ID, or the app will not start.

OIDC_ISSUERVariable

Issuer URL of your identity provider, e.g. https://auth.example.com. Leave blank to keep OIDC off. GeoMetrikks reads {issuer}/.well-known/openid-configuration and the token's iss claim must match this value exactly. Must be https unless the host is localhost. Filling in this plus the client id, secret and redirect URI puts a 'Sign in with ...' button on the login page.

OIDC_CLIENT_IDVariable

Client id of the confidential client you registered for GeoMetrikks at the provider. The authorization code flow with PKCE is used, so a public client will not work.

OIDC_CLIENT_SECRETVariable

Client secret for that client.

OIDC_REDIRECT_URIVariable

The exact callback URL registered at the provider: this container's public address plus /api/v1/auth/oidc/callback, e.g. https://geo.example.com/api/v1/auth/oidc/callback. It has to end in that path, and plain http is only accepted on localhost. With an https URL you also need APP_SESSION_SECURE=true.

OIDC_ALLOWED_USERSVariable

Who may sign in, as verified email addresses or subject identifiers. Single value, comma-separated, or a JSON list. An email only matches when the provider marks it verified. At least one of OIDC_ALLOWED_USERS and OIDC_ALLOWED_GROUPS is required: without an allow list, everyone the provider authenticates would get in, which for Google means everyone.

OIDC_ALLOWED_GROUPSVariable

Groups allowed to sign in; being in any one of them is enough. Same formats as OIDC_ALLOWED_USERS. The provider has to send the group claim, so keep the groups scope in OIDC_SCOPES.

OIDC_SCOPESVariable

Space-separated scopes requested at login; openid is mandatory. Authelia works with the default. Google rejects the groups scope, and Authentik only sends groups if you add the mapping yourself, so use 'openid profile email' for those and allow people by email in OIDC_ALLOWED_USERS.

Default
openid profile email groups
CROWDSEC_DEFAULT_BAN_DURATIONVariable

Default duration for manual bans (Go duration string).

Default
4h
CROWDSEC_REQUEST_TIMEOUTVariable

LAPI request timeout in seconds.

Default
10.0
CROWDSEC_VERIFY_TLSVariable

Verify TLS when LAPI uses https.

Default
true
CROWDSEC_STREAM_POLL_INTERVALVariable

Seconds between decision-stream polls feeding live ban/unban updates.

Default
15.0
OIDC_GROUPS_CLAIMVariable

Claim that carries group membership. It is read from the ID token and from the userinfo endpoint, so providers that only serve groups from userinfo (Authelia) need nothing extra.

Default
groups
OIDC_PROVIDER_NAMEVariable

Label on the login button: 'Sign in with {name}'.

Default
SSO
OIDC_LOGOUT_IDPVariable

On logout, also end the session at the provider. This only works when the provider's discovery document advertises an end_session_endpoint; Authelia 4.39 and Google do not, so leave it false there. Before enabling it, register {your app URL}/signed-out as the post-logout redirect URI at the provider. Logout always clears the GeoMetrikks session either way.

Default
false
OIDC_CA_BUNDLEVariable

PEM file holding the CA that signed your provider's certificate, for a provider behind an internal CA. Give the path as the container sees it and add a path mapping for the file yourself, e.g. host /mnt/user/appdata/geometrikks/certs/ca.pem to container /app/certs/ca.pem, readable by PUID:PGID. The app refuses to start when the file is missing. There is no switch to turn certificate verification off.

LOGPARSER_ENABLEDVariable

Tail and ingest the access logs. Set false for an instance that only serves the UI over data another instance writes.

Default
true
LOGPARSER_POLL_INTERVALVariable

Interval in seconds to poll the log file for new entries. Lower it (1.0 is the app default) for a snappier live map, at the cost of more wakeups.

Default
10
LOGPARSER_BATCH_SIZEVariable

Max records before a forced commit.

Default
100
LOGPARSER_COMMIT_INTERVALVariable

Max time interval in seconds between database commits.

Default
5.0
LOGPARSER_STORE_DEBUG_LINESVariable

Store all raw log lines in the debug table, not just malformed ones.

Default
false
GEOIP_ASN_ENABLEDVariable

Download the GeoLite2 ASN database alongside the City one and record the network and organization behind each request. This is what fills the Top ASNs view. Uses the same MaxMind credentials; without them the app ingests without ASN data.

Default
true
GEOIP_REFRESH_DAYSVariable

Re-download the GeoLite2 databases when older than this many days.

Default
7
GEOIP_LOCALESVariable

JSON list of GeoIP locales to use.

Default
[&quot;en&quot;]
MAP_DEFAULT_VIEWVariable

Where the map opens, as latitude,longitude or latitude,longitude,zoom (zoom 0-22, default 3), e.g. 71.129982,27.653369,15. Unset: the map opens on your server locations, or the whole world when there are none.

MAP_AUTO_DETECT_SERVER_LOCATIONVariable

Look up this server's public IP at startup and geolocate it, so the map knows where live request routes end. Set false to skip the lookup. Replaces MAP_AUTO_DETECT_HOME: copy your value here and delete the old variable, because the app refuses to start when the two differ.

Default
true
MAP_PUBLIC_IP_URLVariable

JSON endpoint used for public-IP discovery; response must contain an 'ip' field.

Default
https://api64.ipify.org?format=json
MAP_SERVER_LOCATION_REFRESH_HOURSVariable

Hours between re-detecting this server's public IP and updating its map location. Replaces MAP_HOME_REFRESH_HOURS: copy your value here and delete the old variable, because the app refuses to start when the two differ.

Default
24
MAP_SERVER_LOCATIONSVariable

Fixed map locations per server name, as a JSON object of latitude/longitude pairs, e.g. {&quot;edge-01&quot;: [59.91, 10.75]}. Use it for a server whose public IP geolocates wrong (CGNAT, VPN), or whose logs are shipped from another machine. An entry here beats the location the server detects for itself. Delete the entry and its row goes at the next start. Replaces MAP_HOME_LOCATIONS: copy your value here and delete the old variable, because the app refuses to start when the two differ.

Default
{}
ANALYTICS_DEBUG_RETENTION_DAYSVariable

Days to keep access_log_debug data.

Default
30
ANALYTICS_HOURLY_RETENTION_DAYSVariable

Days to keep hourly continuous aggregate data.

Default
60
ANALYTICS_CAGG_REFRESH_INTERVAL_MINUTESVariable

Minutes between continuous aggregate refreshes.

Default
5
ANALYTICS_COMPRESSION_AFTER_DAYSVariable

Days after which to compress hypertable chunks.

Default
7
SCHEDULER_ENABLEDVariable

Enable scheduled background tasks.

Default
true
LOG_MAIN_MAX_BYTESVariable

Rotate the main JSONL log (geometrikks.log) when it exceeds this size in bytes. Default 10 MiB.

Default
10485760
LOG_MAIN_BACKUP_COUNTVariable

Number of gzipped main-log archives to keep.

Default
5
LOG_LOGIN_MAX_BYTESVariable

Rotate the login log (login.log) when it exceeds this size in bytes. Default 10 MiB.

Default
10485760
LOG_LOGIN_BACKUP_COUNTVariable

Number of gzipped login-log archives to keep.

Default
5
DB_STARTUP_WAIT_SECONDSVariable

How long startup waits for the database before serving in degraded mode. 0 probes once. The app keeps retrying in the background and recovers on its own when the database answers.

Default
30
APP_MODEVariable

full runs everything: web UI, API, migrations, scheduler, CrowdSec and ingestion. agent is headless. It tails, geolocates and writes into a shared database and serves only /health and /health/ready, so the WebUI port and the admin login do nothing. Set agent only on an extra copy of this container that feeds a full instance elsewhere, and give it the same image tag as that instance.

Default
full
APP_PROXY_ADVISORYVariable

Warn on Settings &gt; Status when recent traffic for a tailed file comes from CDN or private addresses, which means the proxy is logging the hop in front of it rather than the visitor. Set false when that traffic mix is deliberate, such as Tailscale-only access or a CDN you front on purpose.

Default
true