Skip to content
Go back

ntopng vs darkstat

By SumGuy 10 min read
ntopng vs darkstat

Something Is Eating Your Upload

You spent $40 on a smart switch. You added a VLAN. You installed Pi-hole. You are, objectively, a person who has their home network together.

And yet — your upload is pegged at 95% and you have no idea which device is responsible. The smart switch dashboard shows you blinking LEDs. Very helpful.

Two open-source tools can actually answer that question, and they answer it in completely different ways. ntopng goes deep — DPI, per-flow charts, GeoIP, NetFlow ingestion, alerts, the whole observatory. darkstat is a single C binary that captures packets and renders a plain HTML page showing you the top talkers. That’s it.

Neither is wrong. They just solve different problems, and knowing which one to reach for saves you from standing up a Redis instance on a Pi 4 at midnight when all you needed was “which host is hammering my NAS.”


Install Footprint

darkstat: Embarrassingly Small

darkstat ships as a single binary with no external dependencies. On Debian/Ubuntu:

Terminal window
sudo apt install darkstat

That’s roughly 120 KB of binary. It links against libpcap. It reads packets, tallies counters in RAM, and serves the HTML page on port 667 by default. The entire config is a handful of flags.

Systemd unit to run it on an interface:

/etc/systemd/system/darkstat.service
[Unit]
Description=darkstat network stats
After=network.target
[Service]
ExecStart=/usr/sbin/darkstat -i eth0 -p 667 --no-dns --daylog /var/lib/darkstat/daylog
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now darkstat

Browse to http://your-host:667 and you’ll see host traffic counters within seconds. RAM usage on a Pi 4 at moderate home-lab traffic: roughly 8–12 MB. CPU: negligible.

ntopng: A Whole Stack

ntopng is not a single binary. The community edition pulls in Redis (for persistence), nDPI (the deep packet inspection library), and optionally GeoIP databases. The Docker Compose route is the sanest install path:

docker-compose.yml
services:
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
ntopng:
image: ntop/ntopng:stable
restart: unless-stopped
network_mode: host # needs raw access to the interface
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ntopng_data:/var/lib/ntopng
- ./ntopng.conf:/etc/ntopng/ntopng.conf:ro
depends_on:
- redis
ports:
- "3000:3000"
volumes:
redis_data:
ntopng_data:
ntopng.conf
-i=eth0
-r=redis://redis:6379
--community
--http-port=3000
--disable-login=1 # remove in prod; handy for lab testing
Terminal window
docker compose up -d

On a Pi 4 with moderate traffic, ntopng will idle around 120–200 MB RAM with Redis adding another 30–50 MB. Under active DPI load that climbs. On a mini PC (N100 / N5105) it barely registers. On a Pi 4 with a busy LAN and NetFlow ingestion, you’ll feel it.


What Each Tool Actually Sees

darkstat: Host and Port Counters

darkstat operates at layer 3. It sees source IP, destination IP, protocol, and byte counts. That’s the entire data model. The UI gives you:

What it does not give you: application identification, DNS names resolved against flows, per-flow timelines, GeoIP, alerts, or any form of historical drill-down beyond the in-RAM ring buffer (which resets when the daemon restarts).

This is not a limitation so much as a design goal. darkstat answers “which host sent the most bytes in the last hour?” It does not answer “what application on that host was doing it.”

One underrated use: pipe the darkstat HTTP output into a cron job or healthcheck. Because it’s plain HTML with predictable structure, you can scrape the top-talkers table with a five-line Python script and fire an alert when a single host crosses a threshold. You won’t find that workflow in any docs because it’s technically an abuse of a stats page — but it works, and sometimes duct tape is the right material.

ntopng: Full Flow Visibility

ntopng runs nDPI on every packet. nDPI is a layer-7 classification library that identifies application protocols — not just port 443 but specifically “this is Netflix,” “this is BitTorrent,” “this is WireGuard.” It currently recognizes over 300 protocols.

What you get on top of that:

The community edition is genuinely useful. The Pro tier ($49/year as of writing) unlocks historical flow export, SNMP polling, and more alert types. For a home lab the community tier covers most use cases.


Getting Whole-Network Visibility

Both tools need to see traffic. That’s the hard part, especially if you want more than just the traffic hitting the host running the tool.

Option 1 — Port Mirror / SPAN Port

Most managed switches support port mirroring. You mirror all traffic to one port, plug a Pi or mini PC into that port, and run darkstat or ntopng on the mirror interface. This gives you full visibility into everything crossing the switch.

Terminal window
# Confirm the mirror interface is receiving traffic
tcpdump -i eth0 -c 20 -n

Option 2 — In-line / Bridge Mode

Some setups insert the monitoring host inline between the router and the switch. Traffic passes through the monitoring host. Adds latency; works when a span port isn’t available.

The cleanest bridge setup on Linux uses two NICs and a software bridge:

Terminal window
# Create a bridge between eth0 (WAN side) and eth1 (LAN side)
ip link add name br0 type bridge
ip link set eth0 master br0
ip link set eth1 master br0
ip link set br0 up
ip link set eth0 up
ip link set eth1 up
# Now run darkstat or ntopng on br0

Traffic flows through unmodified; the monitoring daemon sees everything on br0. Latency added is microseconds unless your monitoring host is already CPU-bound.

Option 3 — NetFlow from the Router (ntopng only)

If your router runs OPNsense or pfSense, this is the cleanest option for ntopng. Enable the NetFlow exporter plugin on the router, point it at ntopng’s collector port.

On OPNsense: Services → NetFlow → Settings

Listening Interfaces: WAN, LAN (or all)
Destination Host: <ntopng-host-ip>
Destination Port: 2055

In ntopng.conf, add the NetFlow collector interface:

ntopng.conf
-i=eth0
-i=nf:0 # NetFlow collector on UDP 2055
-r=redis://redis:6379
--community
--http-port=3000

Restart ntopng and you’ll start seeing aggregated flow data from the entire network without needing a span port. darkstat cannot consume NetFlow — it needs raw packets on a local interface.

Pi-hole Integration

ntopng has a Pi-hole DNS-over-HTTPS bridge that lets it resolve hostnames from Pi-hole’s query log. In ntopng.conf:

--dns-mode=1

With that enabled, ntopng uses passive DNS to label hosts by name rather than IP. darkstat has a --dns mode that does real-time reverse DNS lookups, but it’s blocking and can slow down packet capture — leave --no-dns on by default.


UI Quality

Let’s be honest. darkstat’s UI looks like it was designed during the Bush administration. It probably was. That’s not an insult — it’s a plain HTML table with host IPs, byte counts, and sparklines. Loads in 200ms. Works without JavaScript. You can curl it and grep the output if you want. The aesthetic is “sysadmin tool from 2003 that still works in 2026.”

ntopng’s UI is a full dashboard — charts, traffic flows, a world map showing geolocated connections, per-host timelines, alert tables. The community edition is polished. It auto-refreshes. There’s a search bar. You can drill from a country code down to a specific flow in three clicks.

If you need to hand a network report to someone who is not you, ntopng. If you just need to squint at top talkers at 2 AM, darkstat loads faster than ntopng’s React app initializes.


History and Retention

darkstat keeps counters in memory. If the process restarts, the counters reset. The --daylog option writes a daily traffic summary to a file for rough trending, but there’s no queryable history beyond “bytes since daemon start.”

ntopng stores flows in Redis (community edition) and SQLite/MySQL (Pro). You can query flows from the last 24 hours, 7 days, or whatever your retention window is. Historical drill-down is one of its most useful features — you can pull up yesterday’s 10pm traffic spike and see exactly which host connected to which destination.


Resource Usage Summary

Metricdarkstatntopng (community)
RAM (idle, Pi 4)~10 MB~150–200 MB + Redis
CPU (moderate traffic)< 1%5–15%
DiskNegligibleRedis + SQLite (grows with retention)
DependencieslibpcapRedis, nDPI, GeoIP
Install time30 seconds5–10 minutes

Layering Into a Wider Stack

darkstat and ntopng sit in the middle of a monitoring hierarchy:

A practical home-lab stack: darkstat running 24/7 on a Pi as a lightweight always-on watch, ntopng spun up via Docker Compose when something weird shows up in darkstat and you need to identify the actual application. You don’t need both running permanently unless you’re building a proper home NOC — and if you are, you probably already know this.


The Verdict

Pick darkstat if:

Pick ntopng if:

The real answer: run both. darkstat costs you nothing. Keep it on the same Pi you’re already running Pi-hole. When darkstat’s host table shows something unexpected, pull up ntopng to identify the actual application and correlation.

Your upload is still pegged. But now you’ll know it’s your NAS backup job, not a compromised IoT device — and that distinction matters at 2 AM when you’re deciding whether to fix it or go to bed.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
HACS: When Custom Integrations Bite You
Next Post
Gemma 4 vs Qwen3.6

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts