All apps · 0 apps
NetProbe
Docker app from bmartino1's Repository
Overview
Netprobe 2.0 – Internet Quality Dashboard
Netprobe 2.0 is a lightweight, container-friendly network probe and web UI for home/lab internet monitoring.
It periodically:
Pings your gateway, router, and a list of “anchor” sites.
Measures packet loss, latency, and jitter.
Measures DNS lookup latency per DNS server.
Runs scheduled and manual Speedtest.net tests.
Stores everything in SQLite and renders a dark-mode dashboard with Chart.js.
The goal is a simple “drop in and forget it” quality monitor that you can run on Unraid, Proxmox, Docker, etc.
Additional variables can be found here: https://github.com/bmartino1/NetProbe_Python
Optional data:
ALL are OPTIONAL! Defaults/fallbacks to SQLite.
--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=SYS_ADMIN
Use standalone Postgres for backend storage docker variables...(May be hidden in template)
USE_POSTGRES: ${USE_POSTGRES:-true}
DB_ENGINE: ${DB_ENGINE:-postgres}
POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
POSTGRES_DB: ${POSTGRES_DB:-netprobe}
POSTGRES_USER: ${POSTGRES_USER:-netprobe}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-netprobe}
Readme
View on GitHubNetprobe 2.0 – Internet Quality Dashboard
Netprobe 2.0 is a lightweight, container-friendly network probe and web UI for home / lab internet monitoring.
It periodically:
- Pings your gateway, router and a list of “anchor” sites.
- Measures packet loss, latency and jitter.
- Measures DNS lookup latency per DNS server.
- Runs scheduled and manual Speedtest.net tests.
- Stores everything in SQLite and renders a dark-mode dashboard with Chart.js.
The goal is a simple “drop in and forget it” quality monitor that you can run on Unraid, Proxmox, Docker, etc.
Features
Internet Quality Score (0–100)
Weighted composite of loss, latency, jitter and DNS response time.Per-metric panels
- Packet Loss
- Latency to anchors
- Jitter
- DNS Response Time (with lines + checkboxes for each configured DNS server)
- Bandwidth (download / upload history from speedtest)
History controls
Time selector on each chart (seconds → months).Panel toggles
Checkboxes to show/hide sections (Internet Quality, Loss, Latency, Jitter, DNS, Bandwidth). Preference is saved inlocalStorageper browser.Speedtest integration
- Automatic periodic runs (
SPEEDTEST_INTERVAL). - “Run Speedtest Now” button in UI.
- Last result summary in the top status bar.
- Download / upload charts.
- Automatic periodic runs (
SQLite storage
measurements– aggregate probe results.dns_measurements– per-DNS-server latency per probe.speedtests– speedtest history.
Single-container deployment
- Flask + Gunicorn backend
- Chart.js frontend
- Works nicely with Docker Compose and Unraid templates.
How it works
Every PROBE_INTERVAL seconds the probe loop:
- Detects the container’s default gateway.
- Pings:
- Default gateway (inside Docker network)
- Optional
ROUTER_IP(your LAN router) - Each hostname in
SITES
- Computes average latency, jitter (max–min) and packet loss across all ping targets.
- For each configured DNS server (
DNS_NAMESERVER_X_IP), it measures the time to resolveDNS_TEST_SITEseveral times and averages the result. - Computes an Internet Quality Score using weighted, threshold-normalized metrics.
- Stores:
- Aggregate metrics in
measurements - Per-server DNS results in
dns_measurements
- Aggregate metrics in
Separately, a periodic task runs speedtest when at least
SPEEDTEST_INTERVAL seconds have passed since the last run and stores the
result in speedtests.
The frontend polls the APIs (JSON) and renders gauges + history charts.
Quick start (Docker Run)
docker run -d \
--name netprobe \
--restart unless-stopped \
-p 8080:8080 \
-v /mnt/user/appdata/netprobe/database:/data \
-e DB_ENGINE=sqlite \
-e USE_POSTGRES=false \
-e ROUTER_IP=192.168.1.1 \
-e DNS_NAMESERVER_4="LAN_DNS" \
-e DNS_NAMESERVER_4_IP=192.168.1.1 \
bmmbmm01/netprobe
Quick start (Docker Compose)
# docker-compose.yml
services:
netprobe:
image: bmmbmm01/netprobe:latest
#build: ./probe #github clone and build run your own...
container_name: netprobe
restart: unless-stopped
# Optional: use a separate env file instead of inline vars
# env_file:
# - ./probe/config.env
environment:
WEB_PORT: 8080
DB_PATH: /data/netprobe.sqlite
PROBE_INTERVAL: 60
PING_COUNT: 4
SITES: fast.com,google.com,youtube.com
ROUTER_IP: 192.168.1.1
DNS_TEST_SITE: google.com
DNS_NAMESERVER_1: Google_DNS
DNS_NAMESERVER_1_IP: 8.8.8.8
DNS_NAMESERVER_2: Quad9_DNS
DNS_NAMESERVER_2_IP: 9.9.9.9
DNS_NAMESERVER_3: CloudFlare_DNS
DNS_NAMESERVER_3_IP: 1.1.1.1
DNS_NAMESERVER_4: My_DNS_Server
DNS_NAMESERVER_4_IP: 192.168.1.1
WEIGHT_LOSS: 0.6
WEIGHT_LATENCY: 0.15
WEIGHT_JITTER: 0.2
WEIGHT_DNS_LATENCY: 0.05
THRESHOLD_LOSS: 5
THRESHOLD_LATENCY: 100
THRESHOLD_JITTER: 30
THRESHOLD_DNS_LATENCY: 100
SPEEDTEST_ENABLED: "True"
SPEEDTEST_INTERVAL: 14400 # 4 hours
APP_TIMEZONE: UTC
ports:
- "8080:8080"
volumes:
- netprobe_data:/data
cap_add:
- NET_RAW
- NET_ADMIN
- SYS_ADMIN
volumes:
netprobe_data:
** Both Quick Starts use the sqlfile option for longterm persitent data... Postgres backend changeover is available via additional docker options later
Environment variables
| Variable | Default | Description |
|---|---|---|
WEB_PORT |
8080 |
Port inside container for the web UI / API. |
DB_PATH |
/data/netprobe.sqlite |
SQLite DB path (used when DB_ENGINE=sqlite). |
DB_ENGINE |
sqlite |
Database backend: sqlite or postgres. |
USE_POSTGRES |
(empty) | Legacy flag; if true, forces Postgres unless DB_ENGINE is set. |
POSTGRES_HOST |
postgres |
Postgres host when DB_ENGINE=postgres or USE_POSTGRES=true. |
POSTGRES_PORT |
5432 |
Postgres TCP port. |
POSTGRES_DB |
netprobe |
Postgres database name. |
POSTGRES_USER |
netprobe |
Postgres username. |
POSTGRES_PASSWORD |
netprobe |
Postgres password. |
PROBE_INTERVAL |
30 |
Seconds between probe runs. |
PING_COUNT |
20 |
ICMP packets per target per probe. |
APP_TIMEZONE |
UTC |
Label shown in UI (no TZ conversion yet). |
SITES |
fast.com,google.com,youtube.com,amazon.com |
Comma-separated ping targets. |
ROUTER_IP |
(empty) | Optional LAN router IP. |
DNS_TEST_SITE |
google.com |
Domain for DNS latency tests. |
DNS_NAMESERVER_1..4 |
(labels) | Human-readable DNS names for UI. |
DNS_NAMESERVER_1..4_IP |
(IPs) | DNS IPs to probe. |
WEIGHT_LOSS |
0.6 |
Weight of packet loss in score (0–1, sum = 1). |
WEIGHT_LATENCY |
0.15 |
Weight of latency. |
WEIGHT_JITTER |
0.2 |
Weight of jitter. |
WEIGHT_DNS_LATENCY |
0.05 |
Weight of DNS latency. |
THRESHOLD_LOSS |
5 |
Loss % considered “max bad” for scoring. |
THRESHOLD_LATENCY |
100 |
Latency ms considered “max bad”. |
THRESHOLD_JITTER |
30 |
Jitter ms considered “max bad”. |
THRESHOLD_DNS_LATENCY |
100 |
DNS ms considered “max bad”. |
SPEEDTEST_ENABLED |
True |
Enable periodic speedtests. |
SPEEDTEST_INTERVAL |
14400 |
Seconds between automatic speedtests. |
SPEEDTEST_SERVER |
"" |
Optional Speedtest server ID. Leave blank to use automatic server selection. |
LIVE_LOG_POLL_SECONDS |
2 |
Seconds between live log viewer refreshes in the web UI. |
You can also put these in config.env and uncomment env_file in the
Compose file.
API code overview...
The frontend uses these JSON endpoints (you can also query them yourself by calling the python venv...):
GET /– main UI.GET /api/score/recent?limit=N
Recent aggregate data. Each row includes:ts,isoavg_latency_ms,avg_jitter_ms,avg_loss_pctavg_dns_latency_msscore(0–100)dns_per_server– optional{ "<dns_ip>": latency_ms }map.
GET /api/score/latest
Most recent probe (same fields as above).GET /api/config
Effective configuration (after env overrides), including:- probe interval, ping count, timezone label
- resolved gateway IP
- router IP
- sites
- DNS test site
dns_servers_detail– list of{ name, ip }- weights / thresholds
- speedtest settings.
GET /api/speedtest/history?limit=N
Speedtest history, newest → oldest, each with:ts,isoping_msdownload_mbps,upload_mbpsserver_name,server_host,server_country.
GET /api/speedtest/latest
Most recent speedtest result.POST /api/speedtest/run
Trigger an immediate speedtest. Returns:{ "success": true, "result": { "timestamp": 1234567890, "ping_ms": 6.1, "download_mbps": 100.0, "upload_mbps": 20.0, "server": { "name": "Example ISP", "host": "speed.example.com", "country": "US" } } }
Find a Speedtest Server ID
If you want to manually target a specific Speedtest server, you can list available server IDs from inside the running Netprobe container.
Command
docker exec -it netprobe speedtest-cli --list
This returns a list of nearby Speedtest servers with their numeric IDs.
Example output
12345) Example ISP - Chicago, IL (12.34 km)
23456) Another ISP - Rockford, IL (88.12 km)
34567) Test Provider - Milwaukee, WI (140.55 km)
In this example, the server IDs are:
123452345634567
You can then use one of those IDs with Netprobe.
Troubleshooting
Charts all show 100% loss / very high latency
Let it run for 5 min... internet average takes time to build per defualt weights...
Ensure the container has the needed capabilities:
NET_RAW,NET_ADMIN,SYS_ADMIN
From the host, verify basic connectivity from inside the container:
docker exec -it netprobe ping -c 3 8.8.8.8If this fails, fix host networking / firewall before debugging Netprobe.
DNS panel is flat or empty
Confirm
DNS_TEST_SITEresolves inside the container:docker exec -it netprobe nslookup google.com 8.8.8.8Verify that
DNS_NAMESERVER_X_IPvalues are correct and reachable.Click Show Config / Env in the UI to confirm DNS servers are parsed as expected.
Speedtest never runs
- Check that:
echo $SPEEDTEST_ENABLED
# should be: True
- Look at logs:
docker logs netprobe
You should see lines like:
Speedtest: ping=… down=… up=…Remember automatic runs only happen every SPEEDTEST_INTERVAL seconds. (by default every 4 hours) you can manuly run or set this interval in the docker env...)
Use the Run Speedtest Now button in the UI to verify it works on demand
Install NetProbe on Unraid in a few clicks.
Find NetProbe in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Requirements
# Optional: if ping needs extra caps in your environment
--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=SYS_ADMIN
# Use standalone Postgres for backend storage docker variables...
USE_POSTGRES: ${USE_POSTGRES:-true}
DB_ENGINE: ${DB_ENGINE:-postgres}
# Postgres connection details (match the Postgres service above via env file...)
POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
POSTGRES_DB: ${POSTGRES_DB:-netprobe}
POSTGRES_USER: ${POSTGRES_USER:-netprobe}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-netprobe}
Download Statistics
Related apps
Explore more like this
Explore allLinks
Details
bmmbmm01/netprobe:latestRuntime arguments
- Web UI
http://[IP]:[PORT:8080]- Network
bridge- Shell
bash- Privileged
- false
Template configuration
- Target
- 8080
- Default
- 8080
- Value
- 8080
Container /data location for SQLite file that holds long-term data. Container path can be changed if DB_PATH variable is assigned. DB_PATH defaults to /data/netprobe.sqlite
- Target
- /data/
- Default
- /mnt/user/appdata/netprobe_database
- Value
- /mnt/user/appdata/netprobe_database
Seconds between script probe runs. (Countdown in web page.) This runs the pings, DNS lookups, and others to collect data...
- Default
- 30
- Value
- 30
ICMP packets per target per probe.
- Default
- 20
- Value
- 4
Time zone, e.g. America/Chicago
- Default
- UTC
- Value
- UTC
Comma-separated ping targets.
- Default
- fast.com,google.com,youtube.com
- Value
- fast.com,google.com,youtube.com
Optional LAN router IP. Your router/gateway IP address to help with pings. Can leave blank (to leave blank, delete this variable).
- Default
- 192.168.1.1
- Value
- 192.168.1.1
Domain for DNS latency tests.
- Default
- google.com
- Value
- google.com
Web UI display name
- Default
- My_DNS_Server
- Value
- My_DNS_Server
DNS IPs to probe. Do you run a custom DNS server? Set this to that IP.
- Default
- 192.168.1.1
- Value
- 192.168.1.1
Enable periodic speed tests at SPEEDTEST_INTERVAL in seconds.
- Default
- True
- Value
- True
14400 seconds = 4 hours. Seconds between automatic speed tests.
- Default
- 14400
- Value
- 14400
Google_DNS
- Default
- Google_DNS
- Value
- Google_DNS
Google_DNS 8.8.8.8
- Default
- 8.8.8.8
- Value
- 8.8.8.8
Quad9_DNS
- Default
- Quad9_DNS
- Value
- Quad9_DNS
Quad9_DNS 9.9.9.9
- Default
- 9.9.9.9
- Value
- 9.9.9.9
CloudFlare_DNS
- Default
- CloudFlare_DNS
- Value
- CloudFlare_DNS
CloudFlare_DNS 1.1.1.1
- Default
- 1.1.1.1
- Value
- 1.1.1.1
Requires DB_ENGINE set to postgres Use a standalone Postgres and set the required Postgres Docker variables manually.
- Default
- true
- Value
- false
Choose database backend. If using Postgres, set USE_POSTGRES to true as well.
- Default
- postgres
- Value
- sqlite
Weight of packet loss in score (0–1, sum = 1).
- Default
- -0.6
- Value
- -0.6
Weight of latency.
- Default
- 0.15
- Value
- 0.15
Weight of jitter.
- Default
- 0.2
- Value
- 0.2
Weight of DNS latency.
- Default
- 0.05
- Value
- 0.05
Loss % considered “max bad” for scoring.
- Default
- 5
- Value
- 5
Latency ms considered “max bad”.
- Default
- 100
- Value
- 100
Jitter ms considered “max bad”.
- Default
- 30
- Value
- 30
DNS ms considered “max bad”.
- Default
- 100
- Value
- 100
This sets the Python web server port. If edited, update Docker NAT ports and WebUI URL.
- Default
- 8080
- Value
- 8080
Fallback container directory for Tailscale state information - Added by Community Applications
- Target
- CA_TS_FALLBACK_DIR
- Default
- /data/
- Value
- /data/