Real-time Linux monitoring for one server or a whole fleet.
No Node.js. No database. No Cloudflare account or domain required.
SysMon has two binaries:
sysmon: the dashboard/hub.agent-monitor: runs on every remote Linux server and sends metrics to the hub.
The normal setup is deliberately two steps.
Run this on the Linux server that will host the dashboard:
curl -fsSL https://raw.githubusercontent.com/HitamLegit6777/Sysmon/main/install.sh | sudo bashThe installer:
- installs
sysmonandagent-monitor(release assets, or built from source when the release download fails); - installs
cloudflaredif needed; - generates and stores a private agent token;
- starts the hub as a system service;
- creates a free
trycloudflare.comQuick Tunnel; - prints the exact agent command to copy.
No Cloudflare login, domain, DNS record, or tunnel configuration is needed.
Open http://<hub-ip>:8088 on the LAN, or use the public Quick Tunnel URL printed by the installer. Initial login: admin / admin123. Change the password immediately from Profile.
Copy the single command printed by the hub installer and run it on the Linux server you want to monitor. It has this shape:
curl -fsSL https://raw.githubusercontent.com/HitamLegit6777/Sysmon/main/install.sh | \
sudo env SYSMON_MODE=agent \
SYSMON_HUB_URL=https://random-name.trycloudflare.com \
SYSMON_TOKEN=<generated-token> bashThat is all. The agent installs as a service, connects outbound, and appears in Fleet. Repeat the same command on other servers. Each server uses its hostname as the default ID.
The installer accepts the public HTTPS URL directly; you do not need to append /agent/ws or convert https:// to wss://.
| Component | Supported systems |
|---|---|
| Hub and agent | Linux x86_64 and ARM64 |
| Linux distributions | Distribution-independent release binaries; tested installer path does not require apt, dnf, yum, pacman, or apk |
| Init systems | systemd is configured automatically; on Alpine/OpenRC, containers, WSL without systemd, and other init systems the installer prints the manual start command |
| Dashboard browser | Any current browser on Linux, Windows, macOS, Android, or iOS |
| Windows/macOS monitoring agent | Not supported: collectors require Linux /proc and /sys |
Supported Linux environments include Debian, Ubuntu, Fedora, RHEL-compatible distributions, Arch, Alpine, openSUSE, Raspberry Pi OS, Linux containers, and Linux VMs, provided the machine is x86_64 or ARM64 and exposes /proc and /sys.
Quick Tunnel is the default because it requires no Cloudflare account or domain. The hub owns the cloudflared child process and prints a new URL plus a ready-to-paste agent command whenever the tunnel starts.
Important limitations:
- Cloudflare describes Quick Tunnels as testing/development infrastructure with no uptime SLA.
- The random
trycloudflare.comURL can change after a hub or tunnel restart. - Connected agents receive the new URL from the hub and persist it before reconnecting.
- An agent that was offline during the URL change must be run once with the newly printed command.
- Cloudflare currently limits Quick Tunnels to 200 in-flight requests and does not support SSE. SysMon uses WebSockets, not SSE.
For a long-lived production deployment with a stable hostname, use a named Cloudflare Tunnel later; SysMon itself does not require one.
# Hub
systemctl status sysmon
journalctl -u sysmon -f
systemctl restart sysmon
# Agent
systemctl status agent-monitor
journalctl -u agent-monitor -f
systemctl restart agent-monitor
# Print the current Quick Tunnel URL
cat /run/sysmon/tunnel-urlOn systems without systemd:
# Hub
SYSMON_AGENT_TOKEN=<token> /usr/local/bin/sysmon --port 8088
# Agent; HTTPS base URLs are accepted
/usr/local/bin/agent-monitor \
--hub https://random-name.trycloudflare.com \
--token <token>| Variable | Meaning |
|---|---|
SYSMON_MODE=hub |
Install the hub; this is the default |
SYSMON_MODE=agent |
Install an agent |
SYSMON_HUB_URL |
Hub HTTPS/HTTP/WS/WSS base URL; agent mode only |
SYSMON_TOKEN |
Shared agent token; generated automatically for the hub |
SYSMON_AGENT_ID |
Agent ID; defaults to hostname |
SYSMON_PORT |
Hub port; defaults to 8088 |
SKIP_SYSTEMD=1 |
Install binaries without service units |
SYSMON_WEBHOOK_URL |
Generic HTTP(S) alert webhook |
SYSMON_AGENT_ACTIONS |
Comma-separated agent action allowlist |
Requirements: Linux and Rust 1.80+.
cargo build --release
# Hub: Quick Tunnel starts automatically when cloudflared is installed
SYSMON_AGENT_TOKEN="$(openssl rand -hex 24)" \
./target/release/sysmon --port 8088
# Agent: the base HTTPS URL is normalized automatically
./target/release/agent-monitor \
--hub https://random-name.trycloudflare.com \
--token <same-token>Use --no-quicktunnel for LAN-only deployments.
- Fleet dashboard with rename/remove, maintenance windows, status, metrics, alerts, and latency, plus a one-click Add server dialog that builds the ready-to-paste agent install command (admin only).
- Forced password rotation on first login: the dashboard refuses to settle for the default
admin/admin123credentials. - Generic webhook delivery and first-class agent-offline alerts.
- Durable JSONL history with daily rotation/retention; no database required.
- Prometheus text exporter, process top-grower history, and disk-full ETA.
- GPU telemetry (NVIDIA via
nvidia-smi, AMD and Intel via sysfs) with per-metric capability bits, so an unreadable metric renders as "not reported" instead of a misleading0. - Container metrics from the Docker or Podman socket (CPU, memory, network rates, uptime, restarts) with no runtime dependency beyond the socket itself.
- Disk health: SMART verdicts via
smartctlplus mdraid array state, where an unreadable disk reportsunknownand is never presented as healthy. - Global rules plus per-agent alert overrides, recovery debounce (hysteresis) against flapping, and structured remote actions (
restart-service,terminate-process,reboot); arbitrary shell commands are never accepted. - Admin/viewer roles enforced server-side: every fleet, alert-rule, and remote-action mutation requires an admin session — the viewer role is read-only.
- Low-footprint agent: cadence-tiered collectors (per-tick syscalls only where 1s accuracy matters; process I/O, socket counts, and core frequencies sampled less often), no subprocess spawning, and a self-measured overhead of well under 1% of a single core.
- Embedded frontend, authenticated WebSockets, bounded queues, serialize-once broadcast fan-out, and hostile-input sanitization.
Browser ──HTTPS/WebSocket──> Quick Tunnel ──> sysmon hub
▲
│ outbound authenticated WebSocket
agent-monitor ──────┤
agent-monitor ──────┘
Agents only make outbound connections, so remote servers need no inbound firewall rule. Collectors read Linux /proc and /sys; the hub stores current state and rolling history in memory and persists authentication and alert configuration locally.
Hub CLI:
sysmon [OPTIONS]
-p, --port <PORT> Listen port (default 8088)
--host <HOST> Bind address (default 0.0.0.0)
-c, --config <FILE> JSON config file
--enable-shell Enable the authenticated web terminal
--no-quicktunnel Disable automatic Quick Tunnel
-v, --version
-h, --help
Agent CLI:
agent-monitor --hub <URL> --token <SECRET> [OPTIONS]
--hub <URL> HTTPS/HTTP/WS/WSS hub URL
--token <SECRET> Shared token
--id <NAME> Agent ID (default hostname)
--interval-ms <N> Sampling interval (default 1000 ms)
--process-io Report per-process I/O and fd counts (off by default)
-h, --help
Config file example; sections are optional and keys are camelCase:
{
"server": { "host": "0.0.0.0", "port": 8088, "enableCompression": true },
"sampling": {
"fastIntervalMs": 1000,
"processIntervalMs": 3000,
"diskIntervalMs": 5000,
"thermalIntervalMs": 4000,
"processLimit": 200,
"processIo": true
},
"history": { "capacityFast": 3600, "retentionDays": 7, "directory": "/var/lib/sysmon/history" },
"alerts": { "enabled": true, "rules": [] },
"notifications": { "enabled": true, "webhooks": ["https://ntfy.sh/example"] },
"ui": { "title": "SysMon", "defaultTheme": "dark", "accentColor": "#5b8cff" },
"agents": {
"enabled": true,
"token": "REPLACE_WITH_A_LONG_RANDOM_SECRET",
"maxAgents": 64,
"offlineAfterMs": 45000,
"idleIntervalMs": 5000,
"activeIntervalMs": 1000,
"actionAllowlist": []
}
}- The default
admin/admin123account must be rotated: the dashboard redirects the first login to the password form and keeps showing a warning banner until the primary password changes. The optional web terminal stays disabled while default credentials are active. - Fleet, alert-rule, and remote-action mutations are admin-only and enforced in the router, not just hidden in the UI; viewers are read-only.
- The agent token is never exposed over the API except through the admin-only
GET /api/agents/install-commandendpoint that builds the install command. - The generated agent token is stored with mode
0600under/etc/sysmon; it is not embedded directly in systemd unit arguments. - Quick Tunnel exposes the dashboard publicly. Dashboard authentication remains mandatory.
- Agent Bearer tokens are compared over fixed-length SHA-256 digests; invalid agents never enter the registry.
- Remote strings and metric values are bounded and sanitized before alerting or browser broadcast.
| Symptom | Fix |
|---|---|
| No Quick Tunnel URL | Run journalctl -u sysmon -f; confirm cloudflared --version works and outbound HTTPS is allowed |
| Agent cannot connect | Use the newly printed command; verify hub service and token, then inspect journalctl -u agent-monitor -f |
| Agent offline after tunnel restart | Run the latest command printed by the hub if the agent was offline during URL rotation |
| Agent not visible | Agent IDs must contain only letters, numbers, ., -, or _ |
| No thermal/disk data | The subsystem may not be exposed by the VM/container; SysMon degrades gracefully |
| No systemd | Use the manual commands printed by the installer or configure your init system |
All dashboard APIs require the authenticated session cookie.
- Metrics/data:
GET /api/snapshot,/api/summary,/api/host,/api/history?from=&to=,/api/processes,/api/process-history,/api/alerts,/api/config,/api/health,/api/metrics. - Rules/fleet: alert-rule CRUD,
PATCH/DELETE /api/agents/:id, per-agent rules, structured actions and action-result polling. - Onboarding (admin only):
GET /api/agents/install-commandreturns the ready-to-paste agent install command for the current hub URL. - Accounts: login/logout/me/password/username/preferences plus admin-only user CRUD.
- Browser WebSocket:
/ws; agent WebSocket:/agent/wswith Bearer token.
cargo test --all-targets
cargo clippy --all-targets --all-features -- -D warnings
node docs/cdp_validate.mjs # running hub on :8099 + Chrome required
node tools/security-test.mjs # running token-enabled hub requiredThe Rust suite currently contains 138 tests covering sessions, persisted alerts,
collectors/utilities, agent registry isolation and eviction, input sanitization,
agent authentication, login-lockout semantics, role enforcement on every
mutating route, alert hysteresis and webhook retry/backoff, GPU/container/SMART
collectors, history rotation/pruning and round-trips, and the chunked HTTP
client used against the container runtime socket. One further test
(collects_real_containers_end_to_end) is ignored unless a live Docker or
Podman socket is present.
MIT.
