Project

Infinite Servers

A self-hosted server fleet monitor and a multi-region service status page.

GitLab Open Source Live servers.infinitescript.com
Introduction

Infinite Servers is a self-hosted server fleet monitor built around a single design constraint: the agent must run completely unprivileged. Each monitored host installs a PHP script that runs as nobody, reads /proc, and pushes status every 15 seconds to a central dashboard. No root access, no persistent daemon with elevated privileges, no external database server.

This design was motivated by the security risks that plague popular alternatives. Tools like Nezha require agents to run as root, which creates a severe blast-radius problem: if the dashboard is compromised, an attacker can push arbitrary commands to every connected host with full system privileges. Two recent CVEs illustrate just how real this risk is:

  • CVE-2026-53519 (CVSS 9.1 Critical) — a path-traversal flaw in the Nezha dashboard allows an unauthenticated attacker to read arbitrary files, including config.yaml, by crafting a URL like /dashboard../data/config.yaml. With the config in hand — tokens included — an attacker can impersonate the dashboard toward every connected agent.
  • CVE-2026-53521 (CVSS 6.4 Medium) — incorrect authorization allows a low-privilege user to persist references to nonexistent DDNS profiles and later hijack another user’s profile configuration.

Because Nezha agents run as root, CVE-2026-53519 alone is sufficient to own an entire fleet without ever touching the agent binary. Infinite Servers’ agent has nothing to exploit — it cannot write files, cannot escalate privileges, and cannot be instructed to run commands. The worst an attacker can do is silence the telemetry feed.

Architecture

Infinite Servers has two parts:

  • Dashboard — a React + Vite frontend served by a minimal PHP backend. All historical data is written to an embedded SQLite file, so there is no database server to maintain. The dashboard is deployed either as a Docker container (the frontend is compiled from source inside the build) or natively via PHP’s built-in server behind a systemd unit, with the install script handling both paths.

  • Push Agent — a single api/status.php script installed on every monitored host. It collects CPU usage, memory, disk, load average, and network counters from /proc, then POSTs the payload to the dashboard. The agent runs as a hardened systemd service (ProtectSystem=strict, user nobody) and has no read access outside /proc and the network.

The dashboard uses Server-Sent Events for live updates, so the browser receives a push the moment a new status packet arrives rather than polling on a timer.

Agent Details

Installation is a single script invocation on each host:

git clone https://gitlab.com/hzxie/infinite-server
cd infinite-server
sudo ./scripts/install-agent.sh

The script installs php-cli with the sqlite3 and curl extensions, prompts for the server name, dashboard URL, and token, then registers the infinite-agent systemd service. The agent config lives at /opt/infinite-agent/agent.json.

For environments that can’t run the interactive installer, every prompt has an environment-variable override (AGENT_NAME, DASHBOARD_URL, AGENT_TOKEN), making fully automated provisioning straightforward.

A pull mode is also available for networks where outbound push isn’t possible: serve api/status.php behind a web server on the agent host and set the url field in the dashboard’s server config. Push mode is recommended for most deployments.

Dashboard Details

Servers are declared in configs/web-servers.json — a JSON file that maps a display name to a region code and a shared token. The region drives the flag emoji shown next to each host; optional location and tags fields add further context. The file is excluded from version control since it holds tokens.

History retention is controlled by two config keys: history-interval (how often a sample is written) and history-days (how far back the dashboard keeps). Both can be tuned to balance storage cost against graph resolution.

The IP address shown for each host is configurable via ip_mask: setting "x.x.*.*" displays the first two octets and redacts the rest, which is useful when the dashboard is publicly accessible.

Screenshots