Skip to content

Host agent

Probes check your services from the outside. The agent checks the machine itself, which is the only way to see a full disk, a dead process, or a host that is up but no longer doing its job. It is deliberately narrow: it measures and reports, and it executes nothing on your behalf.

Every 15 seconds, on the host:

Signal Detail
CPU Total utilisation, 0 to 100
Load average 1, 5 and 15 minutes (Unix only)
Memory and swap Used, total, percentage
Disk Every mounted filesystem, used and total and percentage
Uptime Seconds since boot
Services For each watched process: running, process count, CPU, resident memory

No network counters, no per-core breakdown, no temperatures. Nothing about the host that is not in that table.

Create an enrolment token in the app under Host agents, New agent. It hands you a ready-made command:

PERSTAT_TOKEN=psag_… sh -c "$(curl -fsSL https://agent.perstat.io/install.sh)"

The environment assignment keeps the token out of ordinary process arguments and ps output. A literal command pasted into an interactive shell can still be stored in shell history; use your secret manager or a shell-specific hidden-input/history policy, then unset the variable.

Supported today: Linux on x86_64 and aarch64 (static musl builds, no runtime dependencies) and macOS as a universal binary. Windows is not shipped yet.

The installer detects OS and architecture, downloads the matching binary, and checks SHA-256. With an Ed25519-capable OpenSSL 3 it also verifies the release signature against the key in the script. Without that capability, including common macOS LibreSSL and older distributions, it warns and falls back to TLS transport plus SHA-256. Because installer and key come from the same origin, the first install still depends on that origin being trusted. The agent’s later self-update uses a compiled key and is fail-closed, as described below.

On macOS it installs a LaunchDaemon instead. Set PERSTAT_NO_SERVICE=1 if you want the binary without a service.

Re-running is safe. If the host is already enrolled, the installer switches to upgrade mode: it refreshes the binary and the service, keeps the existing identity, and needs no token. Running the same line from your configuration management on every host, repeatedly, is the intended use. For more than a handful of machines, see agents on a fleet.

Property Default Range
Lifetime 24 hours 1 to 720 hours
Single use yes can be made reusable

The token is shown once and stored only as a hash. Single use is right for one machine; a reusable token is right for a fleet roll-out. Tokens cannot be withdrawn before they expire, so prefer a short lifetime over a long one.

The token itself is opaque. Which organization and project it belongs to is resolved on the server, never parsed by the agent.

An agent reports; a monitor decides what is worth an incident. Create monitors of type agent and bind them to the agent. One monitor watches one signal:

metric Fields Fires when
availability grace_seconds (default 180, range 60 to 3600) The host stopped reporting for longer than the grace
cpu threshold (default 90) CPU above the threshold
mem threshold (default 90) Memory above the threshold
disk threshold (default 90) The fullest filesystem above the threshold
service service_name, grace_seconds (default 120, range 60 to 3600) The process has been absent for longer than the grace

Two settings apply to all of them. breach_severity is down (opens an incident, pages on-call, shows on status pages) or degraded (an in-app notice only). notify_push toggles the push notification.

One disk monitor covers every mount point, because the threshold is evaluated against the fullest filesystem. Note what that does and does not catch: it sees a filesystem filling up, not a single file growing. A log file that adds 700 MB to a 25 GB disk moves the figure by three points and will not trip a 90 percent threshold.

Agent monitors are evaluated on our side roughly every 30 seconds. They take no check regions and no quorum, so a single breaching evaluation opens the incident once the grace has passed.

service_name is a process name, not a systemd unit. The agent scans the process table and matches three ways: the exact process name, the exact basename of the executable (which is what makes postgres and postmaster both work), and the Linux 15-character name truncation. Matching is case sensitive on Linux.

That has a consequence worth knowing before you configure it. A service that starts as a script shows up in the process table as python3, sh or node, so two such services cannot be told apart by name. Compiled daemons and anything that sets its own process name are fine.

To see the real names, either run ps -eo comm= | sort -u on the host, or switch on the process inventory for that agent. It is opt-in, off by default, and transmits process and executable names only, deduplicated and capped, never command lines, paths, users or PIDs. With it on, the monitor form suggests names instead of asking you to type them.

The agent only scans the process table when at least one service monitor exists for it.

Outbound only. The agent never opens a listening socket. There is no inbound rule to write and no port to expose, and the systemd unit restricts address families and system calls to match.

Two destinations over HTTPS on port 443:

Host Purpose
api.perstat.io Enrolment, measurements, configuration polling
agent.perstat.io Installer, binaries, self-update downloads

Both need to resolve. On a machine that runs an authoritative nameserver rather than a resolver, make sure a usable resolver is configured.

Measurements every 15 seconds, sent in a batch every 60 seconds, configuration polled about every 5 minutes. The first measurement is sent immediately after enrolment, so a new host appears within seconds.

When a push fails, measurements queue in memory (about six hours’ worth) and are sent when the connection returns, so a short outage does not leave a hole in your history. The queue does not survive a restart of the agent.

One consequence of the 5 minute configuration poll: after you add a service monitor, it can take a few minutes before the agent is watching that process. Until real data arrives the monitor stays pending rather than firing, so a newly created monitor never raises a false alarm.

The agent keeps itself current. Releases are ed25519-signed, the signing key stays offline, and the agent verifies the signature against a key compiled into its own binary before swapping anything. It is fail-closed: an unverifiable release is not installed, and a lower version never qualifies. The swap happens inside the agent’s own directory and needs no root helper.

Set DATARGO_AGENT_NO_SELFUPDATE=1 in the service environment if you would rather drive versions yourself.

Remove the identity with the trash icon on the agent. This revokes its token, archives the monitors attached to that agent, and resolves their open incidents. Archived monitors free their plan slots while their historical records remain subject to the applicable retention rules.

Remove the software on the host:

curl -fsSL https://agent.perstat.io/uninstall.sh | sudo sh

It stops and removes the service, deletes the binary, state and service user, and deregisters the host. If the machine is already gone, removing the identity in the cockpit is sufficient.

Worth understanding precisely, because it decides what you see.

The availability monitor fires: silence past its grace period opens an incident. This is the monitor that tells you a host is gone, and it is the reason to give every agent one.

The other monitors are not evaluated at all once the last report is older than 180 seconds. They write no checks, so they neither open nor resolve anything, which is why a dead host produces one incident rather than one per metric. The flip side: those tiles keep displaying their last reading, which is usually green. Read the availability monitor, not the tiles, when a host is silent.

One distinction we do not yet draw: a dead host and a healthy host that cannot reach us produce the same signal, because the timestamp we work from is when the report arrived. If that difference matters to you, pair the availability monitor with an external check against the same machine.

The agent never collects command lines, environment variables or usernames. Process inventory is opt-in and limited to names. It measures the host and reports; it is not an inventory or forensics tool, and its narrow scope is the point.

It also executes nothing. There is no remote command channel, no script hook and no way for us to run something on your machine. That is a deliberate design limit rather than a feature we have not built yet.

  • Windows is not shipped. It lands on the changelog when it is real.
  • systemd unit state is not read. The check answers “is a process of this name alive”, so a failed unit with a lingering process, a wedged process, and restart flapping inside the grace window all read as healthy.
  • Your own measurements cannot be reported through the agent. If you need to alert on a number only the host knows, a heartbeat monitor covers it: each one has a healthy endpoint (/ping/<token>) and a failure endpoint (/ping/<token>/fail), and a timer on the host decides which to call. Calling the failure endpoint breaches at the next evaluation rather than waiting out the period. That covers what a percentage threshold cannot, such as a count that dropped or a directory that grew.
  • One monitor per signal. Watching four processes on a host means four monitors.