nfsen-ng

nfsen-ng

Docker app from mbolli's Repository

Overview

nfsen-ng is a modern, in-place replacement for the ageing NfSen web frontend. It sits on top of the nfdump tools and visualises NetFlow / sFlow / IPFIX traffic with real-time SSE push, a responsive light/dark UI, Sankey traffic-flow diagrams, and RRD or VictoriaMetrics storage. This is the WEB UI. It only displays flow data that a collector has already written to its data directory. Install the companion "nfsen-ng-nfcapd" collector template (or run the bundled Compose stack) and mount BOTH containers on the SAME appdata path so the UI can read what the collector writes. A device on your network (pfSense/OPNsense/MikroTik/…) must export flows to the collector. The app does not terminate TLS by design; front it with SWAG, Nginx Proxy Manager, or Traefik.

nfsen-ng

GitHub release GitHub license GitHub issues GitHub last commit GitHub stars PHP 8.4 PHPStan level 8 OpenSwoole Docker Donate a beer

nfsen-ng is an in-place replacement for the ageing NfSen web frontend. It sits on top of the existing nfdump tools and adds real-time SSE push, a responsive UI, and support for RRD or VictoriaMetrics as the storage backend.

Seven pages. Four analysis pages share one time range: Overview (the traffic graph, key figures and the top talkers of the range, precomputed while importing), Top Talkers (exact top-N by any nfdump statistic), Flows (individual records, raw output and a summary), Conversations (who talks to whom as a Sankey, a Matrix or a table). Next to them sit Alerts, Health and Settings. Anything that reads capture files shows its cost first and runs only when you press Run.

Requires Linux. The backend runs on the OpenSwoole PHP extension, which has no maintained FreeBSD/other-BSD port; see openswoole/ext-openswoole#233. Docker images are Linux-only.

nfsen-ng Overview page with the traffic graph, key figures and top talkers, light and dark

nfsen-ng Conversations page: a Sankey diagram of src IP -> dst port -> dst IP traffic, light and dark Conversations grouped by destination port: source IP, port and destination IP as a Sankey. The same result is also shown as a Matrix and a ranked table.

Quick start

No clone needed. Grab the compose file and go:

curl -O https://raw.githubusercontent.com/mbolli/nfsen-ng/master/deploy/docker-compose.yml

# Edit NFSEN_SOURCES, NFSEN_NFDUMP_PROFILES, and other env vars in docker-compose.yml, then:

# Production with bundled Caddy (auto-HTTPS, ports 80/443)
docker compose --profile proxy up -d

# Production behind your own reverse proxy (app on port 9000 only)
docker compose up -d

The app image is published on GHCR: ghcr.io/mbolli/nfsen-ng. The bundled-Caddy profile uses the stock caddy:latest image; no custom build is needed, since php-via serves and Brotli-compresses static assets itself. :latest tracks the newest release, betas included while pre-1.0; :edge always tracks the newest master build; or pin an explicit version tag from Releases for a fixed image.

Development (source mounted, auto-reload on file change):

git clone https://github.com/mbolli/nfsen-ng
cd nfsen-ng
docker compose -f deploy/docker-compose.dev.yml up -d

Set NFSEN_SOURCES, NFSEN_NFDUMP_PROFILES, and other options as environment variables in your compose file. The named volume nfsen-data keeps the RRD data, the preferences and the SQLite store (saved filters, alert history, top-N data) across upgrades. See Installation and Configuration in the book for the full guide.

MCP server (AI agent access, optional)

nfsen-ng ships an optional, off by default, read-only MCP server, so an AI agent can investigate traffic through the same data the UI shows without anyone writing nfdump filter expressions by hand.

Ten tools in two tiers, and every description says which: the cheap ones answer from the stored five-minute aggregates immediately, while the rest read capture files with nfdump and cost time proportional to the window. estimate_cost prices a window before you commit to it.

# stdio: a client launches it as a subprocess, no socket, no credentials
docker exec -i nfsen-ng php /var/www/html/nfsen-ng/backend/mcp.php

Set NFSEN_MCP_HTTP=true to serve the same tools at /_mcp on nfsen-ng's own port instead, for an agent that does not live on this host.

Nothing in it writes: no rule creation, no import triggering, no settings changes, so the worst case is disclosure of flow data rather than control of the box. Access to it is equivalent to access to the dashboard. See the MCP chapter.

Documentation

The full user guide and developer reference live in the nfsen-ng book: installation, configuration, a guide to every page, and the architecture/signals/SSE internals for contributors.

Upgrading from 1.0.0-beta.5, or migrating from the old v0.x NfSen-style release? See the upgrade guide in the book. Bare-metal installs now need php8.4-sqlite3 and a memory_limit of 512M for the server, and should run nfdump 1.7.10 (the Health page warns below it); the Docker image has all three.

Requirements

A NetFlow/sFlow/IPFIX collector must write into the same data directory this container reads. Use the companion nfsen-ng-nfcapd template and point both at the same appdata path (default /mnt/user/appdata/nfsen-ng). Your router/switch must export flows to the collector's UDP port.

Related apps

Details

Repository
ghcr.io/mbolli/nfsen-ng:latest
Last Updated2026-10-08
First Seen2026-07-08

Runtime arguments

Web UI
http://[IP]:[PORT:9000]/
Network
bridge
Shell
bash
Privileged
false
Extra Params
--restart unless-stopped

Template configuration

Web UIPorttcp

nfsen-ng web interface (OpenSwoole HTTP). Front with a reverse proxy for TLS.

Target
9000
Default
9000
Value
9000
Data (profiles)Pathrw

nfdump profiles/flow-file directory. MUST be the same path the collector writes to.

Target
/data/nfsen-ng
Default
/mnt/user/appdata/nfsen-ng
Value
/mnt/user/appdata/nfsen-ng
App dataPathrw

nfsen-ng's own data: the RRD database (rrd/), plus preferences, alert rule state and the SQLite store nfsen-ng.sqlite with saved filters, alert history and top-N data (state/). Keep this on a persistent path so it survives image updates.

Target
/var/lib/nfsen-ng
Default
/mnt/user/appdata/nfsen-ng-data
Value
/mnt/user/appdata/nfsen-ng-data
TimezoneVariable

Container timezone.

Target
TZ
Default
UTC
Value
UTC
SourcesVariable

Comma-separated source names. Each must exist as live/name under the data directory, so it has to match the collector's output sub-directory.

Target
NFSEN_SOURCES
Default
flows
Value
flows
Tracked portsVariable

Comma-separated port numbers tracked per source in RRD.

Target
NFSEN_PORTS
Default
80,443,22,53
Value
80,443,22,53
nfdump profiles pathVariable

Container-side profiles path. Must equal the 'Data (profiles)' mount target above.

Target
NFSEN_NFDUMP_PROFILES
Default
/data/nfsen-ng
Value
/data/nfsen-ng
nfdump binaryVariable

Path to the nfdump binary inside the container.

Target
NFSEN_NFDUMP_BINARY
Default
/usr/local/nfdump/bin/nfdump
Value
/usr/local/nfdump/bin/nfdump
Log levelVariable

DEBUG, INFO, NOTICE, WARNING, ERR, CRIT, ALERT or EMERG.

Target
NFSEN_LOG_LEVEL
Default
INFO
Value
INFO
Import yearsVariable

Backfill window (years) processed on first start.

Target
NFSEN_IMPORT_YEARS
Default
3
Value
3
Top-N retention (days)Variable

Days of per-interval top-N data kept in SQLite for the Overview tables. 0 turns collection off. Budget about 12 MB per source and day under App data.

Target
NFSEN_TOPN_RETENTION_DAYS
Default
31
Value
31
GeoIP databaseVariable

Optional path to a MaxMind GeoLite2/GeoIP2 City or Country .mmdb. Copy the file into the App data share and enter its container path, e.g. /var/lib/nfsen-ng/GeoLite2-City.mmdb. When set, IP lookups use it instead of the web service.

Target
NFSEN_GEOIP_DB