Logging (GoAccess → Grafana → Loki)¶
TL;DR / when to use this: My log stack evolved in three stages: GoAccess (lightweight, real-time analytics per proxy host), Grafana + GeoIP (dashboards with country data), and Loki + Promtail (the current setup — log aggregation with LogQL). The classic ELK stack still works but is heavier than Loki for a home server. Pick Loki unless you already have ELK running.
Stage 1 — GoAccess (Nginx Proxy Manager)¶
Lightweight, real-time analytics. The justsky/goaccess-for-nginxproxymanager image tails NPM's logs:
goaccess:
image: justsky/goaccess-for-nginxproxymanager:latest
restart: unless-stopped
environment:
- TZ=America/Denver
ports:
- '7880:7880'
volumes:
- ./data/npm_data/logs:/opt/log
# per-host analytics: mount just one proxy host's log
# - ./data/npm_data/logs/proxy-host-1_access.log:/opt/log/proxy-host-1_access.log
GoAccess can digest all logs, but it can't filter per hostname — for per-host analytics, mount a single proxy-host-N_access.log (NPM writes one per proxy host).
Real IP behind Cloudflare
In the NPM advanced tab, add real_ip_header CF-Connecting-IP; so GoAccess sees the real client IP through a Cloudflare tunnel.
Stage 2 — Grafana + GeoIP¶
The preconfigured npmGrafStats dashboard adds country-level analytics on top of NPM + GoAccess, fed by a JSON access log with GeoIP fields (the JSON log format is in SWAG). Full setup in the post.
Stage 3 — Loki + Promtail (current)¶
Follow the official Loki docker-compose (pin the compose file to a version — floating examples go stale). Practical adjustments:
- Promtail mounts the Nginx logs read-only (
:/var/log/nginx:ro) and tails them into Loki. - Grafana auto-provisions Loki as the default datasource; anonymous admin is fine for a private LAN instance.
- Query with LogQL — filter by label, e.g.
{job="nginx"}.
This replaced GoAccess for me: structured JSON logs + GeoIP fields make Grafana panels far more useful than GoAccess's fixed analytics view.
Which to pick¶
| Stack | Strength | Cost |
|---|---|---|
| GoAccess | Zero-config real-time analytics | Fixed views, no per-host filter |
| Grafana + GeoIP | Country dashboards, custom panels | Needs JSON logging |
| Loki + Promtail | Full aggregation, LogQL, retention | More moving parts |
| ELK | Mature, powerful | Heaviest footprint |
See also¶
- SWAG — JSON + GeoIP logging source
- ELK Stack — the classic option
- Blog posts: GoAccess + NPM · Grafana + GeoIP · Loki + Promtail