HomeLab. Documented.


How to install Proxy Traffic Visualizer (Nginx Proxy Manager)

Audience: homelab users running Nginx Proxy Manager (NPM)
Time: ~30–45 minutes (first time, including MaxMind signup)
Goal: run Proxy Traffic Visualizer in Docker so you get a live dashboard of NPM access logs, geolocation, and threat alerts.

What you’ll build

Prerequisites

Conventions used in this guide

Step 1 — Clone the repository

git clone https://github.com/SpoonerBoy/Proxy-Traffic-Visualizer.git
cd Proxy-Traffic-Visualizer

Verify

ls -la docker-compose.yml .env.example

Expected: both files exist in the project root.

Step 2 — Download the GeoIP database (MaxMind)

  1. Create a free account: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
  2. Download GeoLite2 City in MaxMind DB binary format (GeoLite2-City.mmdb).
  3. Place it on the Docker host, for example:
sudo mkdir -p /opt/geoip
sudo mv ~/Downloads/GeoLite2-City.mmdb /opt/geoip/GeoLite2-City.mmdb
sudo chmod 644 /opt/geoip/GeoLite2-City.mmdb

Verify

file /opt/geoip/GeoLite2-City.mmdb

Expected: output mentions MaxMind or data (not “ASCII text”).

MaxMind updates this file periodically — plan to refresh it every few months (see Keep it up to date).

Step 3 — Find your NPM access log path and active file

NPM usually stores logs under its data directory. Common layouts:

List logs by recency:

ls -lht <PATH_TO_NPM>/data/logs/

Pick the access log with recent timestamps and non-zero size. The default name is often:

Note both:

Verify

Generate a request through NPM (open any proxied site), then:

tail -n 3 "<PATH_TO_NPM>/data/logs/<YOUR_LOG_FILE>"

Expected: new lines in combined log format (IP - - [date] "METHOD path HTTP/x.x" status ...).

Step 4 — Configure environment

cp .env.example .env
nano .env

Set at minimum:

Variable What to set Example
NPM_LOG_DIR Host path to NPM logs directory /home/pi/nginx-proxy-manager/data/logs
NPM_LOG_FILE Active access log filename default-host_access.log
GEOIP_DB_PATH Host path to GeoLite2-City.mmdb /opt/geoip/GeoLite2-City.mmdb
FRONTEND_PORT Port for the dashboard UI 3002
DEMO_MODE false for real NPM logs false

Optional tuning (defaults are fine to start):

Variable Purpose
LOG_POLL_INTERVAL Seconds between polls when idle (0.25 default)
HISTORY_BUFFER_SIZE Events replayed to new WebSocket clients (200 default)

Verify

grep -E '^(NPM_LOG_DIR|NPM_LOG_FILE|GEOIP_DB_PATH|FRONTEND_PORT|DEMO_MODE)=' .env
test -r "$(grep '^GEOIP_DB_PATH=' .env | cut -d= -f2-)" && echo "GeoIP file readable"
test -d "$(grep '^NPM_LOG_DIR=' .env | cut -d= -f2-)" && echo "NPM log dir exists"

Step 5 — Build and start with Docker Compose

docker compose up -d --build

Verify containers

docker compose ps

Expected: proxy-visualizer-backend and proxy-visualizer-frontend Up.

Verify backend is tailing logs

docker logs proxy-visualizer-backend --tail 30

Expected lines similar to:

GeoIP database loaded from '/geoip/GeoLite2-City.mmdb'.
Ingest loop started (demo_mode=False).
Tailing log file '/npm-logs/<your-log-file>'.
Application startup complete.

Step 6 — Open the dashboard

In a browser on your LAN:

http://<docker-host-ip>:3002

Generate traffic through NPM (visit a proxied hostname). You should see:

The UI connects over WebSocket automatically; no separate API key is required on the default install.

Optional — Demo mode (no NPM required)

Useful to preview the UI before wiring logs:

# In .env
DEMO_MODE=true

Then rebuild:

docker compose up -d --build

Demo mode generates synthetic traffic (~15% flagged as threats). Switch back to DEMO_MODE=false for production.

What the app detects (summary)

Proxy Traffic Visualizer applies rule-based classification on each log line (not a WAF). Examples:

Level Examples
High .env probes, path traversal, SQLi/XSS patterns, Log4Shell (${jndi:), shell injection in URLs
Medium Admin panel probes, scanner user-agents, backup file probes, excessive 404s

Full rule list and API details: project README.

Official resources (verify upstream changes)

Keep it up to date

Application (after git pull in the repo):

git pull
docker compose up -d --build

GeoLite2 database (periodic):

  1. Download the newest GeoLite2-City.mmdb from MaxMind.
  2. Replace the file at GEOIP_DB_PATH.
  3. Restart the backend:
docker compose restart backend

Troubleshooting

Next steps