Commit Graph
112 Commits
Author SHA1 Message Date
henrygd 1997984325 refactor(hub): make SSHTransport the single owner of each system's SSH connection
The updater and on-demand requests kept separate copies of the SSH client
(sys.client and the transport's client) and synced them after each request.
That allowed a closed client to be reinstalled over a newer one and leaked
connections that were replaced without being closed.

The updater now dials, opens sessions and tears down timed-out connections
through the transport. The dial keeps the TCP keepalive and handshake
deadline, and an OnConnect callback handles the per-connection resets.
The transport is created under a lock and agentVersion is now atomic.
2026-09-29 11:59:15 -04:00
97db8bd199 fix(hub): honor SSH request cancellation (#2450)
Co-authored-by: hank <hank@henrygd.me>
2026-09-29 11:22:17 -04:00
24881fbfdf fix(hub): prevent proxy caching of systemd details (#2456)
Co-authored-by: hank <hank@henrygd.me>
2026-09-29 10:54:17 -04:00
0484c54919 fix(hub): require system access for alert subscriptions and delivery (#2455)
Co-authored-by: hank <hank@henrygd.me>
2026-09-29 10:27:11 -04:00
a77ed345d7 refactor(hub): scope monitor result writes to the reporting system (#2449)
Co-authored-by: hank <hank@henrygd.me>
2026-09-29 09:41:48 -04:00
user01010111andGitHub 5df0a256c6 fix(hub): pad short monitor IDs to the schema minimum (#2454) 2026-09-28 19:48:57 -04:00
user01010111andGitHub 8b38db1ba0 test: initialise and stop hub fixture workers before cleanup (#2463) 2026-09-28 19:42:36 -04:00
921ded1af0 fix(hub): synchronise WebSocket connection access (#2453)
Co-authored-by: user01010111 <lapses.50.booster@icloud.com>
2026-09-28 19:12:00 -04:00
user01010111andGitHub 09a277f074 fix(hub): synchronise system status access (#2452) 2026-09-28 18:58:46 -04:00
user01010111andGitHub 083b28a1fc fix(hub): preserve custom DNS resolvers when syncing monitors (#2448) 2026-09-28 18:49:43 -04:00
user01010111andGitHub c556dc478d test: preserve fixture errors and verify complete certificate pools (#2462) 2026-09-28 18:23:15 -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
henrygd b684ac9910 fix(hub): bound SSH handshake so a silent peer can't hang the updater
ssh.ClientConfig.Timeout only covers the TCP connect. A peer that accepts
the connection but never sends an SSH banner blocked ssh.NewClientConn
forever, wedging the system's updater goroutine and leaking the socket.
Set a deadline on the conn for the handshake and clear it afterward.
2026-09-28 10:18:59 -04:00
Anand HegdeandGitHub 8613cfe548 feat: list pending package updates on the system page (#2427) 2026-09-27 11:27:13 -04:00
henrygd 15994474f6 hub: return 404 status for unknown frontend routes (#2414) 2026-09-26 10:17:25 -04:00
henrygd 24ec18a937 refactor(hub): decode each agent response into a new struct
The WebSocket path reused sys.data, and CBOR leaves omitted fields
untouched, so stale values carried over (e.g. Details re-saved every
poll, SystemdServicesUpdated stuck true, old map entries kept).

sys.data is now set only by the regular update for alerts. Removes the
Wi-Fi-only workaround in UnmarshalResponse.
2026-09-26 09:43:33 -04:00
henrygd 16e3fbadce store compact RSSI stats and skip real-time collection
Stats.WiFi is now map[string]int8 (json "wf") holding only available
RSSI
readings; SSID and unavailable signals stay in Info.WiFi. Averages are
rounded to whole dBm.

Wi-Fi is collected only on the default 60s interval; real-time requests
reuse the last snapshot to avoid spawning osascript / dumping the BSS
cache every second.
2026-09-25 18:02:34 -04:00
Vito CappelloandGitHub 86ab0fae8b feat: monitor connected Wi-Fi signal per interface (#2367) 2026-09-25 17:43:57 -04:00
Sven van GinkelandGitHub f7528a0208 feat: Add option to define which DNS server a DNS monitor queries (#2389) 2026-09-24 19:01:10 -04:00
Sven van GinkelandGitHub 4d10ea2e03 feat: add SYNC_SYSTEM_NAMES env var to sync system names with hostname (#1917) 2026-09-24 17:45:59 -04:00
Mario MoharandGitHub fc33e62736 fix(hub): restart beszel-hub.service after update (#2410)
restartService only looked for beszel.service, but install-hub.sh installs
the unit as beszel-hub.service, so the restart was skipped on a standard
install and the hub kept running the old binary.

Try the installer's name first and keep beszel.service as a fallback for
hand written units. Same for the OpenRC branch.
2026-09-24 10:00:18 -04:00
a99fe5e997 feat: add TLS certificate expiry check to HTTPS network monitors (#2401)
Co-authored-by: henrygd <hank@henrygd.me>
2026-09-23 17:07:29 -04:00
henrygd 8bf6917fe0 fix: prevent WebSocket reconnect loops on slow agent collections (#2294)
The hub waited only 5s (the request manager default) for stats over
WebSocket and closed the connection on any error. On hosts where
`zpool list` stalls (seen on Proxmox, up to its 10s timeout), collection
exceeded that limit, so the hub sent a close (code 1000) and the agent
reconnected. The refresh ran every other cycle, which caused a
disconnect roughly every 2 minutes.

Hub:
- Wait up to 30s for WebSocket stats responses.
- Keep the connection open when a stats request times out; only close
  it (and fall back to SSH) for other errors.

Agent:
- After the first collection, refresh `zpool list` pool stats and
  `zfs list` dataset usage in the background and serve cached values
  meanwhile, so a hung utility cannot delay the stats response.
2026-09-23 11:21:51 -04:00
spatiumstasandGitHub 2d5ea3fa08 fix: preserve status alerts through pending recovery (#2375) 2026-09-22 19:14:54 -04:00
Sven van GinkelandGitHub 8047f005d4 fix(ui): preserve paused systems in network monitors table (#2391) 2026-09-22 18:40:46 -04:00
henrygd c54dbfba7c test: wait for hub setup in universal token integration test 2026-09-19 00:14:19 -04:00
henrygd 0509053a69 test: wait for hub system status in agent WebSocket integration test 2026-09-19 00:02:29 -04:00
henrygd 187dc886a9 fix: resync network monitors after SSH reconnect and retry failed syncs 2026-09-18 23:49:54 -04:00
henrygd f7fd3ef403 force oauth created users to start with user role 2026-09-18 17:10:37 -04:00
bb1b39928e feat: network monitoring from agents (#2266, #1911)
Co-authored-by: Sven van Ginkel <svenvanginkel@icloud.com>
Co-authored-by: xiaomiku01 <xiaomiku01@outlook.com>
2026-09-18 13:22:50 -04:00
José M. Requena PlensandGitHub 4bf70700f2 feat(hub): add TRUSTED_PROXY_IPS allowlist for TRUSTED_AUTH_HEADER (#2327)
With TRUSTED_AUTH_HEADER set, the hub authenticates a request from the
header alone, whichever address it comes from. That is right when every
request passes through the reverse proxy, and not when the hub can also
be reached directly: anyone who can reach it sets the header themselves.

TRUSTED_PROXY_IPS takes a comma-separated list of IPs or CIDR ranges.
When set, the header is only honored on requests whose peer address is
in the list; other requests fall through to the normal authentication.
When unset, nothing changes.

The check uses the connection's RemoteAddr, not a forwarded header, so
the list names the proxy itself. IPv4-mapped IPv6 entries are treated as
IPv4. Entries that do not parse are skipped with a warning on the
console; a list with no valid entry trusts nobody, so a typo narrows the
allowlist instead of widening it.
2026-09-17 13:48:46 -04:00
50f6fc075d Merge commit from fork
* fix: make first-user bootstrap atomic

* add tests

---------

Co-authored-by: henrygd <hank@henrygd.me>
2026-09-16 20:13:32 -04:00
henrygd a0bf338796 hub: raise max batch requests and lower max batch body size 2026-09-16 19:39:07 -04:00
f204dc17e6 feat(agent): Add docker image update available flag (#2211)
Co-authored-by: henrygd <hank@henrygd.me>
2026-09-10 19:39:40 -04:00
henrygd 6d82ee70b1 chore: replace google/uuid with new go uuid package 2026-09-10 10:39:11 -04:00
8d6a5d5f6e feat(agent): report btrfs filesystems as storage pools (#2315)
Co-authored-by: henrygd <hank@henrygd.me>
2026-09-09 19:53:39 -04:00
henrygd 98687be2f2 fix(hub): reject null systemd service entries to prevent hub panic 2026-09-08 10:08:33 -04:00
henrygd e39e153ca0 fix(hub): prevent readonly users listing tokens of their shared systems via api 2026-09-08 09:57:58 -04:00
henrygd 997adc19bb fix: show idle GPU utilization in systems table (#2312) 2026-09-07 13:13:05 -04:00
henrygd 6cb302fcf6 fix(hub): bound realtime metric fetching and enforce access control by system
- synchronize realtime subscription state
- prevent overlapping fetches per system
- add realtime worker lifecycle tests
- reject subscriptions without system access
- test access revocation and shared-system permissions
2026-09-06 13:24:53 -04:00
5969d36856 feat(alerts): add container health alerts with log excerpt on notifications (#2225)
Add a new "ContainerHealth" alert type that fires when a Docker container's
health check reports unhealthy, and resolves when it recovers. This mirrors
the existing Status (up/down) alert pattern: an alert can be armed per system
and honors the "min minutes" delay before firing.

When the alert fires, the notification (email and any configured webhook,
including Discord via shoutrrr) includes a log excerpt fetched live from the
agent for up to 2 of the unhealthy containers, prioritizing lines containing
"error" or "fatal" (falling back to the log tail if none match), capped to
keep the message well under Discord's size limit.

---------

Co-authored-by: hank <hank@henrygd.me>
2026-09-02 12:46:23 -04:00
097180e8d7 feat(alerts): add alert for failed systemd services (#2173)
Adds a user-configurable "Failed Services" alert that notifies when any
tracked systemd service enters the failed state, and again when all services
recover.

---------

Signed-off-by: Martin Stenröse <martin@stenrose.se>
Co-authored-by: henrygd <hank@henrygd.me>
2026-09-01 20:41:48 -04:00
spatiumstasandGitHub ed88e6efae feat(alerts): add CPU state notifications (#2249) 2026-09-01 19:10:31 -04:00
917d069ab3 feat: add ZFS monitoring (#2209)
- track pool capacity, health, I/O, scrub status, and vdev errors
- report dataset usage and correct ZFS filesystem metrics
- add pool charts, detail views, refresh controls, and health alerts
- persist pool details and include ZFS usage in disk alerts
- support configurable detail intervals and legacy agent compatibility

---------

Co-authored-by: hank <hank@henrygd.me>
2026-09-01 12:19:36 -04:00
Aditya Raj SinghandGitHub 3af6512514 fix(hub): don't read the SSH client after it is closed (#2277)
createSessionWithTimeout checked sys.client for nil and then dereferenced
it again inside the goroutine that calls NewSession. update() runs the
SMART fetch in its own goroutine, so closeSSHConnection can clear the
field between those two reads and the goroutine dereferences a nil
client, panicking the whole hub process.

Make client an atomic.Pointer, load it once before starting the
goroutine, and clear it with Swap so a concurrent close cannot be
observed mid-session-creation. NewSession on an already-closed client
returns an error, which the existing retry path already handles.

Closes #2157
2026-08-30 13:34:32 -04:00
henrygd 6f92b9396d fix(hub): user alerts idor
fixes very unlikely scenario where user guesses another user's 15
character random system id and adds alerts for it
2026-08-21 17:25:09 -04:00
henrygd 5f383c0eb1 fix(tests): stop system updaters on app termination 2026-08-17 12:32:34 -04:00
Sai Asish YandGitHub adaf6f338d systems: synthesize error when getRecord returns nil record (#1968) 2026-08-16 14:44:30 -04:00
eb5dd230cf fix(hub): remove stale smart_devices records when a drive is no longer reported (#2178)
* Fix duplicate /dev/sdg-style entries

* only prune devices after complete refreshes

---------

Co-authored-by: henrygd <hank@henrygd.me>
2026-08-15 13:40:30 -04:00
Sven van GinkelandGitHub 6607d4c0d6 fix(hub): check X-Real-IP header to resolve agent's real source IP (#1973) 2026-08-14 10:13:26 -04:00