All apps · 0 apps
nexpulse
Docker app from DerKezorm's Repository
Overview
Readme
View on GitHubnexpulse
A speed test tracker for your homelab. Measures on a schedule, shows every test live on a gauge, keeps the history and tells you when your line is slower than what you pay for.
Status: early. A small side project, part of the nex apps (Nexview and friends).

The screenshots show a throwaway instance with made-up data.
What it does
- Live view with a gauge: ping, download and upload as they happen, whether you started the test or a schedule did.
- Three sources: Cloudflare (works right away), LibreSpeed (public servers or your own) and, if you activate it yourself, Ookla. See below.
- Everything measurable: download, upload, ping, jitter, lowest and highest ping, latency under load (bufferbloat), and packet loss where the source measures it.
- Schedules: every n minutes, once a day, a cron expression, or n times a day at random times: the day is split into n equal parts with one test at a random minute in each, drawn anew every day, so over a few weeks every hour is covered and busy times show up. All of them can be limited to weekdays and a time window. Tests never overlap.
- History with charts, averages and a CSV export.
- Your plan: enter what your provider promises, and nexpulse marks tests below a threshold of it.
- Alerts via ntfy, Gotify or a webhook: slow test, high ping, failed test.
- API for dashboards like nexdeck or Home Assistant, with keys that can only read or also start tests.
- No accounts. Optionally one password for the interface. The API always needs a key.
- German and English, dark and light.

Sources
| Source | Server choice | Packet loss | Notes |
|---|---|---|---|
| Cloudflare | automatic (nearest data center) | no | The same endpoints as speed.cloudflare.com. Cloudflare refuses tests that come too often; one an hour is plenty. |
| LibreSpeed | automatic, a public server or your own | no | Automatic pings all servers, tries the nearest ones briefly and takes the fastest. |
| Ookla | automatic or any nearby server | yes | Not included. See below. |
About Ookla
nexpulse does not ship any Ookla software. If you activate Ookla in the settings, nexpulse downloads the official Speedtest CLI from Ookla into your data folder.
Ookla's license does not cover this use. It allows the CLI only for personal, non-commercial use on a single personal computer, and forbids running it on a device that other devices can reach over the network, or on routers, modems or other devices that are not personal computers. A container in a homelab falls under that. nexpulse says so before you activate it; if you do, it is your decision and your risk.

Install
services:
nexpulse:
image: ghcr.io/derkezorm/nexpulse:latest
container_name: nexpulse
restart: unless-stopped
ports:
- "8440:8000"
volumes:
- ./data:/data
environment:
PUID: 1000
PGID: 1000
TZ: Europe/Berlin
Then open http://<your-host>:8440. The full example with every option is in
docker-compose.yml.
Forgot the password? This turns it off:
docker exec nexpulse python -m app.cli remove-password
API
Create a key under Settings > Access and API, then send it as X-Api-Key
or as Authorization: Bearer.
| Method | Path | Access |
|---|---|---|
| GET | /api/v1/me |
read (any key: name, access, whether it may start tests) |
| GET | /api/v1/status |
read |
| GET | /api/v1/latest |
read |
| GET | /api/v1/results?from=…&to=…&source=… |
read |
| GET | /api/v1/stats?range=24h|7d|30d|90d|all |
read |
| POST | /api/v1/tests with {"source": "cloudflare"} (or librespeed, ookla) |
run |
| GET | /api/v1/tests/{id} |
read |
The full reference is at /api/docs on your instance.
Development
| Part | Command |
|---|---|
| Backend | cd backend && python -m venv .venv && .venv/Scripts/pip install -r requirements-dev.txt, then python -m uvicorn app.main:app --port 8440 |
| Frontend | npm --prefix frontend install, then npm --prefix frontend run dev (port 5440, proxies /api to 8440) |
| Checks | python -m ruff check app tests, python -m pytest -q in backend; npm run lint, npm test, npm run build in frontend |
License
GNU AGPL v3.0. Cloudflare, LibreSpeed, Ookla and Speedtest are names of their owners; nexpulse is not affiliated with them.
Install Nexpulse on Unraid in a few clicks.
Find Nexpulse 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.
Categories
Related apps
Explore more like this
Explore allDetails
ghcr.io/derkezorm/nexpulseRuntime arguments
- Web UI
http://[IP]:[PORT:8000]/- Network
bridge- Shell
sh- Privileged
- false
Template configuration
Port you reach nexpulse at. Container port: 8000
- Target
- 8000
- Default
- 8440
- Value
- 8440
Holds the SQLite database with all results and the key that signs sessions. Keep it on a local disk, not on a network share.
- Target
- /data
- Default
- /mnt/user/appdata/nexpulse
- Value
- /mnt/user/appdata/nexpulse
User id that should own the files in /data. 99 is the Unraid default.
- Default
- 99
- Value
- 99
Group id that should own the files in /data. 100 is the Unraid default.
- Default
- 100
- Value
- 100
Schedules run at the wall clock time of this zone, for example Europe/Berlin. Leave blank to pick the zone later in the settings; until then nexpulse uses UTC.
- Target
- TZ
Leave this empty unless you switched Network Type to Host. In bridge mode the WebUI Port above already does the job and setting this will break it, because the mapping still points at 8000. On host networking the port inside the container is the port on your server, so use this to move nexpulse off 8000 if something else is already there.
- Target
- NEXPULSE_PORT
Signs sessions and encrypts stored notification tokens. Leave blank: nexpulse creates one on first start and keeps it in /data/secret.key.
- Target
- NEXPULSE_SECRET_KEY
Only matters with a password. auto marks the session cookie Secure when the request arrived over https. Use on only if a proxy terminates TLS and forwards plain http, and never if nexpulse should also be reachable over http, or nobody can sign in. off never marks it.
- Target
- NEXPULSE_COOKIE_SECURE
- Default
- auto
- Value
- auto