greggd
Lightweight Linux, macOS, and Windows metrics daemon for the gregg monitoring ecosystem.
Installation
Prebuilt binaries are published on GitHub Releases; the bootstrap installer is the default path and Cargo is the fallback for source-only hosts.
# Default installation (Linux/macOS)
|
# Source install / fallback (requires Rust 1.89+)
Prebuilt assets (glibc 2.17 on Linux, unsigned on macOS):
greggd-x86_64-unknown-linux-gnu·greggd-aarch64-unknown-linux-gnu(covers 64-bit Raspberry Pi/Le Potato)greggd-x86_64-apple-darwin·greggd-aarch64-apple-darwingreggd-x86_64-pc-windows-msvc.exe
Linux ARMv7 (armv7l) is source-build only and uses cargo install when available.
See packaging/README.md for the full bootstrap contract, checksum verification,
and install.sh/install.ps1 details.
Usage
Run the daemon directly in the foreground. On Unix, systemd and launchd are optional
operator-managed deployment mechanisms; greggd does not invoke them.
On Windows, native SCM lifecycle commands remain available:
Automatic startup and restart (cross-platform restart, Unix startup):
greggd uninstall removes only the exact invoked executable plus startup
integration whose command target matches that executable (systemd
ExecStart, launchd ProgramArguments, the managed cron command, or the
registered SCM image path). Foreign and ambiguous artifacts are reported and
preserved; SCM query uncertainty blocks mutation. Discovery is independent per
artifact, so multiple owned artifacts can be removed together. Configuration
is preserved by default; --purge removes the resolved daemon config (and the
macOS daemon log). Permissions are preflighted before teardown; an uncertain
direct stop blocks deletion. On Unix, Cargo-owned removal completes owned
startup/direct-stop work before delegating the executable to Cargo and applies
--purge only after Cargo succeeds.
startup install defaults to auto: Windows→SCM, macOS→launchd, Linux with running systemd→systemd, else cron. Systemd uses /usr/local/bin/greggd, /etc/gregg/greggd.toml, greggd user/group, /etc/systemd/system/greggd.service (atomic, daemon-reload + enable + start/restart); launchd uses /Library/LaunchDaemons/com.eggstack.greggd.plist; cron uses an idempotent # greggd managed watchdog block with @reboot + * * * * * croncheck (shell-quoted, preserves unrelated crontab, never edits /var/spool/cron). An identified systemd/launchd host never silently falls back to cron on permission failure; the exact sudo <exe> startup install --method <...> is printed and exit 4 is returned. No internal sudo. startup instructions never mutates state. restart is manager-aware and exact-executable-aware: systemd and launchd are restarted only when their registration targets the invoked binary; foreign same-config or unknown registrations fail closed, while a foreign registration with a different known config may use the config-specific direct path. Windows queries the SCM image path and preserves foreign, unknown, and not-installed states without direct fallback. Otherwise Unix uses stop + detached run.
greggd update queries the latest stable greggd crate on crates.io, downloads the exact vX.Y.Z GitHub asset plus .sha256, verifies checksum and candidate version before any replacement, observes exact-executable UpdateLifecycle only after full preparation (Unix ownership + selected health; Windows SCM ownership revalidated immediately before quiescence, owned-to-foreign fails pre-replacement), then atomically replaces the current executable (same-filesystem rename on Unix, self-replace on Windows) and restarts only ManagedRunning/DirectRunning via ownership-aware restart_daemon() (owned Windows running/start-pending may stop, owned stop-pending waits stopped without restart, foreign/unknown/not-installed do zero SCM mutation; Unix foreign same-config preserved, foreign inactive cannot mask direct running); intentionally stopped/foreign services remain stopped/preserved and a successful replacement with failed restart reports Installed X.Y.Z but not activated with the exact greggd restart/systemctl/launchctl command and returns nonzero. No background checks or sudo. The shared download/verify/stage/replace mechanism lives in the internal gregg-update crate; greggd owns only activation/restart coordination.
Ensure the daemon is running. croncheck is a watchdog for cron, Task
Scheduler, and other supervisors without built-in readiness monitoring. It
probes /v2/healthz with bounded raw HTTP on the configured local endpoint,
normalizing wildcard binds to loopback. Valid Gregg Ready, Warming, and Failed
responses all mean the daemon is running. Only a refused connection proves the
endpoint absent and permits spawning greggd run as a detached child; unrelated,
malformed, silent, or ambiguous peers return nonzero without spawning. No service
manager is invoked.
When a non-root bootstrap rerun replaces a same-scope user-local greggd, it
records the default-config daemon's valid health before replacement. A healthy
daemon is reactivated through the new binary's config-specific stop followed
by croncheck; a stopped daemon and a first install remain stopped. Prebuilt
and staged-Cargo candidates use this same finalization path. If activation
fails after the binary is replaced, the installer returns nonzero and prints
an exact retry command.
On Windows, the service entry point is greggd service (internal, used by the SCM). Install via the provided PowerShell scripts in packaging/; uninstall via greggd uninstall (the legacy packaging/uninstall-windows.ps1 is a thin wrapper around it and no longer deletes directories recursively). For startup, the PowerShell installer remains the canonical SCM registration; startup install on Windows reports service state and startup instructions prints SCM commands.
Configuration
Default config path:
- Linux:
/etc/gregg/greggd.toml - macOS:
/Library/Application Support/gregg/greggd.toml - Windows:
%ProgramData%\gregg\greggd.toml
Override the default with --config PATH.
configprint is read-only and prints the configured bind address as a
canonical socket address, with bind wildcards resolved to the host's primary
local IP so the output is a usable address a remote client can dial. A
specific configured host is preserved unchanged, and a wildcard is preserved
verbatim if the local IP cannot be resolved. The output looks like
192.168.182.143:11310 or [fd00::10]:11310. The command does not probe
the network, bind a listener, start, stop, or modify the daemon; wildcard
resolution uses a transient UDP connect() that performs a local route
lookup only and transmits no packets.
status is read-only local diagnostics: it prints the binary version,
resolved config path, canonical bind address, the bounded /v2/healthz
classification (ready, warming, failed, unreachable, or not-gregg
for a peer that answered but is not a valid Gregg endpoint), and the
detected startup-manager state. Exit 0 only when a valid Gregg endpoint
answered; the report is still printed otherwise. It never starts, stops,
restarts, installs, mutates config, or invokes sudo.
Network
This daemon is designed for private networks only. It exposes a read-only HTTP/1 JSON API on the configured port (default 11310) and is not hardened for public internet exposure. No firewall rules are created automatically. LAN exposure is operator-controlled and the daemon has no TLS or authentication.
/v2/status is the universal status endpoint and may include bounded drives
capacity records plus additive live telemetry: current CPU frequency in raw
Hz, daemon-selected disk read/write bytes per second, and directional network
receive/transmit bytes per second with optional link capacities in bits per
second. CPU frequency is current OS-reported frequency, not a base or maximum
clock; macOS omits it because Gregg uses no privileged or undocumented source.
Missing or null optional data means unavailable/legacy; an empty list means
successful enumeration with no eligible records. Disk capacity (used / total)
and disk I/O are separate accounting domains, and R/s/W/s are byte rates.
Disk/network aggregates are separate from detail records and are not inferred
from display rows. Network utilization is directional and full-duplex-safe:
the maximum valid Rx or Tx percentage is used rather than summing both.
Collection is best-effort and does not model physical disks or storage
topology; loopback may appear in network detail but cannot contribute to
aggregate capacity. Older clients and daemons remain compatible by ignoring or
omitting these additive fields; daemon-version transport is not part of the
wire contract. Linux and macOS retain /v1/status; Windows is v2-only for
status semantics.
Live rates use cumulative native counters and the actual monotonic elapsed time
between observations. Counter reset, daemon restart, device hotplug, and link
disappearance re-establish a baseline before a rate is published. Linux uses
CPUFreq policy files, /sys/block/*/stat, /proc/net/dev, and sysfs link
metadata; macOS uses public AF_LINK records and IOKit storage statistics; and
Windows uses CallNtPowerInformation, IOCTL_DISK_PERFORMANCE, and IP Helper.
Optional source failures never make an otherwise valid core sample unready.
The configured daemon display name must be non-empty, at most 128 bytes, and contain no control characters. If identity collection fails, the daemon does not publish a blank identity; it remains warming or failed and preserves any previous valid snapshot.
When writing configuration, the temp file is created 0600 and the final
file is relaxed to 0644: the daemon config carries no secrets and
read-only croncheck/status/configprint must work for unprivileged
operators and cron. A newly created parent directory is restricted to mode
0700; an existing operator-managed directory keeps its current
permissions. Systemd/launchd installs normalize an older 0600 system
config to 0644 with a traversable (0755) parent. Metadata errors while
loading a default config are reported instead of silently falling back to
defaults. If an existing install still shows
Permission denied (os error 13), rerun
sudo greggd startup install --method systemd (or launchd on macOS).
On Unix, greggd stop uses the config-specific local control socket. The
socket path is reserved by the kernel before its restrictive permissions are
verified, so a concurrent path occupant is never replaced; the temp-directory
fallback remains best effort when the config-adjacent directory is unavailable.
If the system clock moves backward, a future-dated cached snapshot is not treated as stale solely because its timestamp is ahead of the current clock.
Links
- Repository: https://github.com/eggstack/gregg
- Project: https://github.com/eggstack/gregg
License
MIT