- Docker
- 系统要求
- 安装
- 免 root 放行 ICMP
- 首次启动
- 常用命令
- 管理监控目标
- 作为 systemd 服务运行
- 反向代理
- 数据、保留期与备份
- 怎么看图
- 升级
- 故障排查
- 从源码构建
- 设计说明
Images for linux/amd64, arm64 and arm/v7 (Raspberry Pi, NAS, RouterOS). Data lives in /data.
# first run: --edit so you can add targets in the web UI
docker run -d --name fogping --restart unless-stopped -p 8518:8518 -v fogping_data:/data githubflyideas/fogping:latest --edit user=admin passwd=change-me
# done editing: recreate without --edit (data in ~/fogping is kept)
docker rm -f fogping
docker run -d --name fogping --restart unless-stopped -p 8518:8518 -v fogping_data:/data githubflyideas/fogping:latest user=admin passwd=change-meEverything after the image name is passed to fogping as-is (--edit, --days=30,
user= / passwd=). Where you can set environment variables but not a command
(Docker Desktop, NAS container managers, RouterOS), use these instead:
| Variable | Same as |
|---|---|
FOGPING_EDIT=1 |
--edit |
FOGPING_USER=admin / FOGPING_PASSWD=change-me |
user=admin passwd=change-me (comma-separated for several) |
FOGPING_DAYS=30 |
--days=30 (default and maximum 93) |
--edit without a login is refused, as on bare metal. PING targets work without
extra capabilities on Docker 20.10+; --user keeps the mounted directory writable by you.
- Linux on x86-64. The release binary is statically linked, so the distribution and its glibc version do not matter.
- For PING targets: permission to send ICMP (see below). TCP targets need no special permission.
- TCP port 8518 reachable from your browser — or
--localhostplus a reverse proxy. The port is fixed at 8518. - Nothing else: no database server, no runtime, no web server.
sudo mkdir -p /opt/fogping && sudo chown "$USER": /opt/fogping && cd /opt/fogping
wget https://github.com/githubflyideas/fogping/releases/download/v1.3.3/fogping-v1.3.3-linux-amd64.tar.gz
wget https://github.com/githubflyideas/fogping/releases/download/v1.3.3/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS # expect: fogping-v1.3.3-linux-amd64.tar.gz: OK
tar --no-same-owner -xzf fogping-v1.3.3-linux-amd64.tar.gz
./fogping --versionThe tarball contains only fogping and LICENSE. Everything fogping writes goes
into one directory it creates where you start it: data/ — so the start
directory must be writable by the user fogping runs as.
(The systemd section below hands it to a dedicated user.)
fogping first tries an unprivileged ICMP socket and falls back to a raw socket. Either one needs a permission. Pick one:
A. Unprivileged ICMP (recommended). Many distributions already enable it; check:
sysctl net.ipv4.ping_group_range
# "0 2147483647" -> already allowed for everyone, nothing to do
# "1 0" -> disabled; enable it permanently:
echo 'net.ipv4.ping_group_range = 0 2147483647' | sudo tee /etc/sysctl.d/99-fogping.conf
sudo sysctl --systemB. Give the binary cap_net_raw. Repeat after every upgrade, because a new
binary does not inherit the capability:
sudo setcap cap_net_raw+ep /opt/fogping/fogpingC. Run as root. Works, but not needed.
Without any of these, PING targets show 100% loss and every round logs
cannot open an ICMP socket (needs net.ipv4.ping_group_range or cap_net_raw, see README).
Always start fogping from its install directory: data/ is relative to the
current working directory.
cd /opt/fogping
./fogping --edit user=admin passwd=change-meOn a brand-new install it creates data/fogping.db, adds the demo target and
starts probing. The log looks like this:
new database — seeded a demo target (www.google.com)
[Demo] probing www.google.com
fogping X.Y.Z up · 1 targets · targets editable in the web UI · listening on 0.0.0.0:8518 · data in ./data · 93-day retention
➜ open http://localhost:8518 for the smoke graph
web login enabled for 1 user(s)
Open http://<server>:8518 and log in. The first round is sent immediately;
after that every target is probed on its own schedule
(see pace). Stop with Ctrl-C — pending data is flushed
before exit.
Everything below is also printed by ./fogping --help, ready to copy.
Try it out — the web UI is open to anyone who can reach port 8518 on any of the host's addresses:
./fogpingRequire a login (recommended). Logins last 7 days; sessions live in memory, so a
restart logs everyone out, and signing out ends the session on the server too.
After 5 wrong passwords from one address that address is locked out for 30 s,
doubling with every further miss up to 15 min (even the right password is
refused while the lock holds); a successful login clears the count. With a login
configured, /api/version tells anonymous callers the version and nothing else:
./fogping user=admin passwd=change-meSeveral users — names and passwords are comma-separated and paired by position
(alice logs in with alice-pw, bob with bob-pw):
./fogping user=alice,bob passwd=alice-pw,bob-pwAdd, edit or delete targets — start with --edit, change them in the web UI,
then press Ctrl-C and start again without --edit so the UI is read-only:
./fogping --edit user=admin passwd=change-me--edit refuses to start without a login (or --localhost): an open, writable UI
would let anyone make this host ping or connect to arbitrary addresses.
History is kept for 93 days by default, which is also the maximum. Keep less with
--days (raw samples are always kept for 2 days; the UI hides range buttons longer
than the history). A value above 93 is refused at startup with --days max is 93:
./fogping --days=30 user=admin passwd=change-meRun in the background with a log file, and stop it again (for a proper service, see systemd):
nohup ./fogping user=admin passwd=change-me >> fogping.log 2>&1 &
pkill -x fogpingListen on 127.0.0.1:8518 only, when a reverse proxy in front handles access
(see reverse proxy):
./fogping --localhost
./fogping --localhost --editPrint the version:
./fogping --versionArguments can come in any order, and the port is always 8518. Quote passwords
that contain shell characters: passwd='p@ss;word'.
Anything on the command line — including the password — is visible to other
local users (ps, systemctl show). If that matters on your host, use
--localhost and let the reverse proxy handle authentication.
Targets are stored in the SQLite database and changed in one place only: the web
UI, when fogping runs with --edit. There is no config file and no list file.
Without --edit nothing — not the UI, not the API — can change a target.
-
Start with
--edit(and a login):./fogping --edit user=admin passwd=change-me -
Click ✎ targets in the top right.
-
Fill in the form and press + add. For example:
- PING, host
1.1.1.1, nameCloudflare, pacefast— pinged every 15 s, 30 packets per round. - TCP, host
api.example.com, port443— measures how long a TCP connect takes; shown asapi.example.com:443since no name was given. - PING, host
10.0.0.1, nameGateway, interval10— every 10 s, overriding the pace.
PING targets are IPv4; hostnames are resolved every round. The name is what the chart buttons show: optional, up to 64 characters, unique.
- PING, host
-
edit changes a target in place; delete stops probing it.
Changes take effect immediately, without a restart. When you are done, restart
without --edit to make the UI read-only again.
- Deleting keeps history. The data stays until retention ages it out. Adding a target with the same name again brings its history back.
- Renaming keeps history. Renaming onto the name of a deleted target is refused, so two histories are never merged by accident.
| Pace | Probed every | Packets per round |
|---|---|---|
fast |
15 s | 30 |
normal |
60 s | 20 |
slow |
300 s | 20 |
Packets in a round are sent 50 ms apart; replies later than 1 s count as lost. A custom interval changes how often a round runs, not how many packets it sends.
The target editor (--edit) has ⇩ export and ⇧ import… buttons. On a
read-only instance an ⇩ targets button in the header still exports.
- Export downloads the active targets as
fogping-targets-YYYYMMDD.json(GET /api/targets/export): name, type, host, port, pace and interval only — no ids, history, logins or settings. It needs the same access as viewing the targets: a login whenuser=is set, otherwise none. - Import reads such a file (pick it, or drop it on the panel) and first shows
a preview: rows to add, rows skipped because the name already exists (or repeats
in the file), and invalid rows with the reason. Import N targets applies the
valid rows in one transaction — all of them or none. It only ever adds: existing
targets are not changed or removed. A row named like a deleted target brings
that target back with its history, exactly as re-adding it by hand does, and the
preview says so. Import needs
--edit(and a login when users are configured) and is refused from another site. - The file format is shared with pingping, so lists move between the two in both directions.
{
"format": "netping-targets",
"version": 1,
"name": "Japan top 3",
"targets": [
{"name": "Google JP", "type": "tcp", "host": "www.google.co.jp", "port": 443, "pace": "normal"},
{"name": "Gateway", "type": "ping", "host": "10.0.0.1", "pace": "fast", "interval": 10}
]
}type is ping or tcp (icmp is accepted), port is for tcp only, pace is
fast / normal / slow (default normal), interval (seconds, 1-86400) is
optional. Files are limited to 1 MB and 500 targets. Full spec:
targets-format.md · JSON Schema:
targets.schema.json.
Importing makes this host probe every address in the file. Read the preview, and only import lists you trust.
Create a dedicated user and hand it the install directory:
sudo useradd --system --home-dir /opt/fogping --shell /usr/sbin/nologin fogping
sudo chown -R fogping: /opt/fogping/etc/systemd/system/fogping.service:
[Unit]
Description=fogping link-quality probe
After=network-online.target
Wants=network-online.target
[Service]
User=fogping
WorkingDirectory=/opt/fogping
ExecStart=/opt/fogping/fogping user=admin passwd=change-me
# Only if you chose option B for ICMP and not ping_group_range:
# AmbientCapabilities=CAP_NET_RAW
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.targetsudo chmod 600 /etc/systemd/system/fogping.service # it contains the password
sudo systemctl daemon-reload
sudo systemctl enable --now fogping
journalctl -u fogping -f # watch the logTo edit targets on a running service, stop it, run once in the foreground with
--edit as the same user, then start it again:
sudo systemctl stop fogping
cd /opt/fogping && sudo -u fogping ./fogping --edit user=admin passwd=change-me
# ... edit in the browser, then Ctrl-C
sudo systemctl start fogpingIf you are not using a reverse proxy, open the port:
sudo ufw allow 8518/tcp or sudo firewall-cmd --add-port=8518/tcp --permanent && sudo firewall-cmd --reload.
Run fogping with --localhost and let the proxy provide TLS (and, if you like,
authentication instead of fogping's own login).
Caddy:
fogping.example.com {
reverse_proxy 127.0.0.1:8518
}
nginx:
location / {
proxy_pass http://127.0.0.1:8518;
proxy_set_header Host $host; # required for --edit, see below
}The target editor refuses requests whose Origin does not match the Host they
arrive with (cross-site request protection). Caddy passes the original Host
through by default; nginx does not unless you set proxy_set_header Host $host.
Without it, saving a target fails with cross-origin request refused.
Everything lives in data/fogping.db (plus -wal and -shm files while it runs):
targets, raw rounds and hourly buckets.
| Tier | What | Kept | Used for views |
|---|---|---|---|
| Raw | every sample of every round | 2 days | up to 1 day |
| Hourly | per hour: min / p50 / p90 / p99 / max, loss, bursts | --days (93, max 93) |
3 days and longer |
Hourly buckets are computed in-process: on start for everything raw still holds, then every 5 minutes. Old data is removed every night at 00:05 local time, and the file is compacted when there is free space to hand back. There is nothing to cron.
Size, roughly: ~0.35 MB per normal target and ~2 MB per fast target for the
two days of raw samples, plus ~1.8 KB per target per day of hourly history
(~170 KB per target for the full 93 days). The raw tier dominates: 200 normal
targets come to about 105 MB, 200 fast targets to about 430 MB.
Upgrading from a version that kept more than 93 days: hourly rows older than the
new retention are deleted by the next nightly clean-up (00:05). Back up data/
first if you want to keep them.
Backup — while running, with the sqlite3 tool:
sqlite3 /opt/fogping/data/fogping.db ".backup /backup/fogping-$(date +%F).db"or stop the service and copy the whole data/ directory. Do not copy
fogping.db alone while fogping is running.
To start over from scratch: stop fogping and delete data/.
- Line — the median RTT. Smoke — the spread around it: on views up to 1 day every individual sample, beyond that each hour's min/p50/p90/p99/max. Tight smoke is a steady link; tall smoke is jitter.
- Red bars — packet loss (right axis, %).
- ◆ — a loss burst: loss far above the target's own recent baseline (robust z-score ≥ 3.5). There are no thresholds to configure.
- P50 / P90 / P99 under the chart are computed from all samples in the window.
On views of 3 days and longer they are marked
≈: exact window percentiles cannot be rebuilt from hourly ones, so these are the typical hour's values. - Compare — the COMPARE menu overlays an earlier period's median as a dashed
line: Previous period (the window just before this one), Yesterday, same
time or Last week, same time. Hover shows the compare value and the Δ%.
A choice is greyed out ("Beyond retention") when that period is older than the
93-day history, so 60d and longer windows cannot compare with the previous period.
When the period has no data yet the legend says so; a compare line far above
the main chart is clipped at the top with its peak shown (
↑ N ms). - For an exact range, fill in the two date fields and press Go; ✕ selection returns to the preset windows.
cd /opt/fogping
sudo systemctl stop fogping
sudo cp -a data data.bak # optional, lets you roll back
sudo wget https://github.com/githubflyideas/fogping/releases/download/vX.Y.Z/fogping-vX.Y.Z-linux-amd64.tar.gz
sudo tar --no-same-owner -xzf fogping-vX.Y.Z-linux-amd64.tar.gz # replaces the binary only
sudo setcap cap_net_raw+ep fogping # only if you used ICMP option B
sudo systemctl start fogpingSchema changes are applied automatically on start.
From 1.1.0: the targets/ directory and its *.imported files are no longer
used; delete them.
From 1.0.x: ping.list and tcp.list are no longer read. Either upgrade to
v1.1.0 first and start it once (it imports the lists into the database), then
upgrade to the latest release; or start the new version with --edit and add the
targets again in the web UI using the same names — history is keyed by name,
so it comes back. The old daily table is dropped (hourly data covers the same span).
| Symptom | Cause / fix |
|---|---|
PING targets at 100% loss, log shows cannot open an ICMP socket |
ICMP permission missing — see Allow ICMP. |
--edit needs a login or --localhost |
By design: add a login, or bind to localhost behind a proxy. |
Saving a target says read-only: restart fogping with --edit |
fogping was started without --edit. |
Saving a target says cross-origin request refused |
Your proxy does not forward Host — see reverse proxy. |
bind: address already in use |
Another fogping is already running (e.g. the service, while you start --edit by hand). |
| Everyone was logged out | fogping restarted; sessions are kept in memory. |
data/ appeared in an unexpected place |
fogping was started from another directory; cd into the install directory or set WorkingDirectory=. |
| After upgrading from 1.0.x there are no targets | List files are no longer read — see Upgrading. |
store init failed: ... permission denied |
The start directory is not writable by the user running fogping — chown it. |
Requires Go 1.22+ and a C compiler (SQLite is linked through cgo):
git clone https://github.com/githubflyideas/fogping.git && cd fogping
CGO_ENABLED=1 go build -trimpath -ldflags "-s -w" -o fogping .
go test ./...Only linux/amd64 is released: cgo rules out cross-compiling the other platforms from the release runner. A local build links glibc dynamically; the release tarball is linked statically.
fogping is a minimalist smokeping-like network oscilloscope with SQLite storage:
raw rounds are held hot for 2 days, then rolled up hourly and kept for 93 days
(--days to shorten; 93 is the maximum). Burst detection (z-score) writes its verdict alongside each
round, so the ◆ marks on the chart come straight from the store. Built-in Web UI
with native auth — read-only unless started with --edit — no Nginx, no Caddy, no
external database. Targets are rows in the same SQLite file; there is no config file.
Sibling project: pingping — the same oscilloscope without cgo.