Commit Graph
330 Commits
Author SHA1 Message Date
Vincent FranstyoandGitHub 827157906e feat: show CPU socket count on the system page (#2646) 2026-10-20 12:59:20 -04:00
ErnestoMunizandGitHub ac40ac027e feat(agent): add CONTAINER_NAME_LABEL to name containers from labels (#2644) 2026-10-20 11:34:57 -04:00
henrygdandSven van Ginkel ca7f75ef73 fix(agent): skip scheduled monitor probes while the hub isn't requesting stats
The hub collects monitor results only with stats requests, which stop
while
a system is paused or the agent is disconnected. Paused WebSocket agents
stay
connected, so they kept probing. Skip scheduled probes after three
default
update intervals without a stats request and resume on the next one.

Co-authored-by: Sven van Ginkel <svenvanginkel@icloud.com>
2026-10-19 19:18:02 -04:00
yi111andGitHub 574c4cf9dd fix(agent): claim sensor names before filtering so excludes don't rename (#2645)
updateTemperatures detected duplicate SensorKeys by looking at the output
map, which only holds sensors that passed every filter. A sensor dropped by
SENSORS or SKIP_GPU therefore never claimed its name, so excluding the first
of two same-named sensors renamed the second one from nvme_sensor_2_4 to
nvme_sensor_2 and dropped it too, making it impossible to exclude just one.

Track handed-out names in a separate set that is populated before any filter
runs, so a sensor's key depends only on the hardware list.
2026-10-19 13:09:05 -04:00
Sven van GinkelandGitHub b431db751f fix(agent): time out blocked fan reads so collection can't hang (#2638, #2639)
Fan sensors were read with a plain os.ReadFile and no timeout. An i915
fan1_input read that blocks in the kernel held the agent lock forever,
stalling every hub request and the WebSocket read loop, so the system
went down and the agent never reconnected.

Fan reads now go through the same timeout as temperatures
(SENSORS_TIMEOUT, default 2s). A shared readWithTimeout helper tracks a
read still blocked after timing out and skips later polls until it
returns, instead of leaking another blocked goroutine each time. The
temperature path uses the helper too, fixing the same pile-up there.
2026-10-19 13:03:13 -04:00
15859c1eb7 refactor: stop sending deprecated DiskReadPs/DiskWritePs fields (#2653)
Disk I/O has been sent in bytes since 0.13.0 (DiskIO for the system,
DiskReadBytes/DiskWriteBytes per filesystem). The agent no longer
populates the old MB-based DiskReadPs/DiskWritePs fields.

The fields are kept on Stats and FsStats only so agents < 0.13.0 still
decode. The hub migrates them on ingest: system-level to DiskIO and
per-filesystem to DiskReadBytes/DiskWriteBytes, so stored records and
the UI only use the byte fields.

Remove the MaxDiskReadPs/MaxDiskWritePs fields, their records averaging,
the UI MB fallbacks and the related TS types.

---------

Co-authored-by: hank <hank@henrygd.me>
2026-10-19 12:17:54 -04:00
Sven van GinkelandGitHub afb710a526 refactor(agent): stop sending deprecated container network fields (#2650)
NetworkSent/NetworkRecv were deprecated in 0.18.3 in favor of
Bandwidth. The hub already falls back to the old fields for older
agents, so the agent no longer needs to populate them.
2026-10-19 11:00:09 -04:00
e233d663c3 refactor(agent): simplify SMART collection with per-device smartctl attempts (#2620)
Rebuild the SMART device list on every refresh instead of keeping
per-device type and parser state across rescans. Each device gets a
short ordered list of smartctl queries, and the three parsers are merged
into one that rejects output without health data so the next query runs.

- scsi devices try auto-detect, then -d sat (#2295)
- NVMe controllers fall back to their n1 namespace
- disks in standby reuse their last reading; a disk not yet collected
  is woken once per agent run
- the last good reading survives temporary read failures
- failed or empty rescans keep the previous device list
- a missing SMART status is UNKNOWN instead of FAILED
- the reported disk type is the type that worked (e.g. sat)
- disks seen through two paths are reported once

---------

Co-authored-by: hank <hank@henrygd.me>
2026-10-19 10:57:25 -04:00
e84eb25e1c fix(agent): keep LHM helper alive after sensor failures (#2624)
Co-authored-by: hank <hank@henrygd.me>
2026-10-17 12:49:57 -04:00
4aee1668fe fix(agent): bind connection lifecycle to a cancellable context (#2464)
Agent.Start and ConnectionManager.Start now take a context.Context. The
manager runs until that context is cancelled or the process receives
SIGINT/SIGTERM. On shutdown it waits for in-flight reconnect attempts
before closing connections.

The reconnect delay, WebSocket dial and pending handshake now stop when
the context is cancelled. A context-aware dialer keeps proxy selection
from the environment. WebSocket callbacks no longer block on eventChan
after the event loop exits. A late reconnect can no longer restart the
SSH server once shutdown begins.

BREAKING CHANGE: agent.Agent.Start now requires a context.Context.

---------

Co-authored-by: hank <hank@henrygd.me>
2026-10-13 12:32:26 -04:00
henrygd 9b40b62ec8 docs(agent): explain btrfs ioctl fallback incomplete-probe semantics 2026-10-13 10:32:59 -04:00
Santhi PrakashandGitHub 01b9b03d67 fix(agent): determine btrfs pool health via ioctls when sysfs devinfo is absent (#2489)
Kernels before sysfs devinfo (pre-5.13, e.g. Synology DSM 4.4) report
every Btrfs pool health as UNKNOWN and expose no member devices, even
though the same facts are available through BTRFS_IOC_FS_INFO and
BTRFS_IOC_DEV_INFO on the mountpoint.

When the devinfo directory does not exist, enumerate devids via DEV_INFO
after confirming the filesystem through FS_INFO: members that answer are
listed with their recorded capacity, a member reporting no device path is
missing (DEGRADED), freed devids (ENODEV gaps from remove/replace) are
skipped, and the kernel device count is cross-checked against the sysfs
devices links so an unattributed missing member still reads DEGRADED.
Any ioctl failure or count mismatch leaves health UNKNOWN rather than
reporting unverified ONLINE.
2026-10-13 10:32:20 -04:00
Sven van GinkelandGitHub 1da59e3771 fix(agent): make package update checks work under the systemd sandbox (#2538)
The agent runs as the beszel user under ProtectSystem=strict, so package
managers that write temp, cache or log files failed with only
"exit status 1" in the log.

- Include the command's stderr in package update check errors.
- dnf5: point XDG_STATE_HOME and XDG_CACHE_HOME into the agent's data
  dir. They default to $HOME, which is /nonexistent for the beszel user.
  With -C, dnf5 still reads the system metadata cache.
- zypper: keep the solv cache in the data dir with --solv-cache-dir,
  since the agent user cannot rebuild it in /var/cache/zypp.
- install-agent.sh, Debian unit: add PrivateTmp=yes. dnf4 (Rocky, Alma)
  and zypper keep temporary files in /var/tmp, which ProtectSystem=strict
  makes read-only. The install script also adds it to existing units
  when re-run.
2026-10-13 08:07:44 -04:00
henrygd bb23f99b3e fix(agent): keep raw ZFS pool capacity when the root dataset has a refquota
A refquota on a pool's root dataset caps its avail by the root's own
referenced data, so used+avail can understate pool capacity when child
datasets hold most of the data and trigger false disk usage alerts.
Fetch refquota with the root datasets and fall back to the raw zpool
figures for those pools.
2026-10-12 14:17:59 -04:00
kenny-ishandGitHub 32d4692853 fix(agent): report ZFS pool capacity from the root dataset (#2540)
The pool overview used `zpool list`, whose size and alloc count raw vdev
space. On raidz that includes parity, so a TrueNAS pool with 65 TB usable
showed 98 TB capacity, while the details page (root dataset) matched TrueNAS.

Take Size, Alloc and Free from the pool's root dataset (used+avail), the same
way Btrfs reports effective capacity. If the root dataset cannot be read, keep
the raw figures and set Raw so the UI labels them as raw usage.

Fixes #2539
2026-10-12 14:14:19 -04:00
Rajeev GadgilandGitHub 02f24ed0af fix(agent): fall back to NVML power samples when power usage is unsupported (#2550) 2026-10-12 12:45:27 -04:00
Sven van GinkelandGitHub 665bcb3e53 refactor(agent): consolidate smartctl JSON types and SMART parsers (#2584) 2026-10-12 10:34:37 -04:00
spatiumstasandGitHub 3d33d5eabb fix(agent): preserve NVMe namespace fallbacks across rescans (#2597) 2026-10-12 09:28:44 -04:00
Sven van GinkelandGitHub 4da7d867f2 systemd: include user journals in service logs (#2553) 2026-10-11 13:02:38 -04:00
d324ccc097 feat(agent): support custom WebSocket headers with HUB_HEADERS (#2585)
Co-authored-by: henrygd <hank@henrygd.me>
2026-10-11 11:22:37 -04:00
henrygd 7f2eb90f24 perf(agent): reuse buffer when reading intel_gpu_top samples 2026-10-11 10:44:18 -04:00
yi111andGitHub 7f63e65f22 fix(agent): parse intel_gpu_top -J arrays that omit commas between samples (#2589) 2026-10-11 10:35:56 -04:00
Bharat KauravandGitHub 383e9c7072 fix(agent): widen NVMe unsafe_shutdowns to uint (#2583)
unsafe_shutdowns was uint16, so drives reporting more than 65535 unsafe
shutdowns made json.Unmarshal fail and the entire NVMe SMART record was
discarded with only "no valid SMART data found" in the logs. Widen it
to uint, matching power_cycles (#2484), and log the unmarshal error at
debug level so similar failures are diagnosable.

Fixes #2582
2026-10-11 09:17:17 -04:00
spatiumstasandhank 13bdd05934 fix: handle cached NVMe failures and empty SMART responses 2026-10-09 14:40:55 -04:00
Fuwuwuwuandhank d8b4191975 fix(agent): reset host CPU baseline after counter rollback 2026-10-09 14:16:35 -04:00
017ebb091a feat: surface zpool status messages in pool health (#2509)
Co-authored-by: henrygd <hank@henrygd.me>
2026-10-09 13:57:40 -04:00
b11e361799 fix(agent): prevent network counter underflow on interface removal and container restart (#2574)
Co-authored-by: hank <hank@henrygd.me>
2026-10-09 12:58:05 -04:00
Sven van GinkelandGitHub 5529d2e15e fix(agent): verify systemd on dbus before starting service monitoring (#2573) 2026-10-09 11:39:09 -04:00
bc2278e7e9 feat(agent): Handle update package check for xbps package manager (#2522)
Co-authored-by: hank <hank@henrygd.me>
2026-10-06 12:10:12 -04:00
henrygd 4fe1a0a7a4 refactor(agent): share cgroup path vars and v2 mount lookup
Drop the cpu prefix from the cgroup path vars now that memory
accounting uses them too, and extract cgroupV2Dir() for the v2 mount
lookup previously repeated in CPU, memory and the root cgroup check.
2026-10-05 14:54:29 -04:00
ef840e0e6d feat(agent): support opt-in cgroup CPU and memory accounting (#2505)
Co-authored-by: hank <hank@henrygd.me>
2026-10-05 14:52:40 -04:00
Sven van GinkelandGitHub d89f844a2a feat(monitors): add option to ignore TLS errors for HTTPS monitors (#2500) 2026-10-05 12:01:51 -04:00
Sven van GinkelandGitHub 74c952b879 fix(agent): don't detect zypper-aptitude's apt-get wrapper as apt (#2523) 2026-10-05 11:49:05 -04:00
MarrrrrrrrryandGitHub 36c14e903d fix(agent): stop sending legacy hubs a duplicate stats payload (#2529) 2026-10-05 11:38:33 -04:00
henrygd e597dd94db wifi: add SKIP_WIFI env var to disable signal monitoring 2026-10-02 12:54:22 -04:00
henrygd b115e2aa6a wifi(linux): skip nl80211 when no wireless devices are registered
Check /sys/class/ieee80211 before opening netlink sockets. Looking up
the
nl80211 family while cfg80211 is not loaded makes the kernel run
modprobe,
which loads the module on hosts without wireless hardware, or fails
again
on every poll when the module is unavailable.
2026-10-02 12:47:57 -04:00
01d91728f0 fix(agent): report LXC guest CPU usage from cgroup accounting (#2341)
Inside an LXC guest, lxcfs serves /proc/stat with the counters of the
host cores in the guest's cpuset, so an idle guest sharing a core with a
busy neighbor reported near-100% CPU.

When the agent detects it is running in an LXC guest (lxcfs mounted on
/proc/stat, container=lxc, or /run/systemd/container), derive CPU usage
from the guest's own cgroup instead: cpu.stat on cgroup v2, cpuacct on
v1, read at the cgroup mount root so it covers every process in the
guest. Usage is normalized by the usable cores (the smallest of the
affinity mask, cpuset and CPU quota).

Per-core usage is omitted in this mode, since the per-core /proc/stat
counters describe shared host cores and would contradict the total.
Iowait and steal are not available from cgroup accounting and report as
zero.

Hosts and Docker/Podman agents are unaffected and keep reading
/proc/stat, as does an LXC guest whose cgroup accounting is unreadable.

---------

Co-authored-by: hank <hank@henrygd.me>
2026-10-01 19:33:42 -04:00
Santhi PrakashandGitHub c394a6b5b1 fix(agent): resolve device symlinks so LVM volumes map to disk I/O (#2486) 2026-10-01 18:44:29 -04:00
spatiumstasandhenrygd 4ffd83677d fix(agent): improve WebSocket and SSH fallback handling (#2441)
Make WebSocket reconnect and SSH fallback transitions reliable across asynchronous disconnects, stale callbacks, and overlapping connections. Keep the SSH listener available while disconnected and allow a verified WebSocket connection to take precedence when it recovers.

Co-authored-by: henrygd <hank@henrygd.me>
2026-10-01 13:37:57 -04:00
0b101cc6be fix(agent): use nvethernet MAC counters (#2090)
Co-authored-by: hank <hank@henrygd.me>
2026-10-01 10:58:21 -04:00
Jeroen De WildeandGitHub 2502dd9626 feat: add toggle for log timestamps (#2471) 2026-09-30 21:14:13 -04:00
Santhi PrakashandGitHub 65e3e2e768 fix(agent): count ZFS snapshot reads in pool I/O stats (#2474) 2026-09-30 18:22:51 -04:00
henrygd 266f45f104 fix(agent): skip first disk I/O sample of an interval when its window is too short
Right after agent start the hub requests stats immediately, and the first
sample of the interval was measured from the baseline taken at startup, only
a second or so earlier. A burst of startup I/O was then stored as the rate
for the whole minute, causing large spikes in disk I/O charts.

The first sample of an interval now must span at least half the interval.
Otherwise it only stores the snapshot, and the next sample is measured from it.
2026-09-30 13:02:29 -04:00
henrygd e925fafd7b refactor(agent): label windows wifi interfaces by adapter name instead of GUID 2026-09-30 12:50:17 -04:00
spatiumstasandGitHub 67c5905b36 fix(agent): handle partial NVMe SMART data (#2340) 2026-09-29 12:09:32 -04:00
user01010111andGitHub 68ca6936a7 refactor(agent): avoid deprecated CPU time total helper (#2459) 2026-09-29 08:42:01 -04:00
user01010111andGitHub 130365f5d3 fix(agent): create SSH server configuration per connection (#2451) 2026-09-28 19:22:48 -04:00
user01010111andGitHub c556dc478d test: preserve fixture errors and verify complete certificate pools (#2462) 2026-09-28 18:23:15 -04:00
user01010111andGitHub 62f8a39c8a test: make agent and systemd fixtures portable (#2461) 2026-09-28 18:19:02 -04:00
7626e5e3c8 feat: show systemd service logs in service details (#2440)
Co-authored-by: hank <hank@henrygd.me>
2026-09-28 13:57:36 -04:00