Dashboard updates: agent self-update, server self-update, logs & version - #3
Draft
Mischa323 wants to merge 30 commits into
Draft
Dashboard updates: agent self-update, server self-update, logs & version#3Mischa323 wants to merge 30 commits into
Mischa323 wants to merge 30 commits into
Conversation
Push the latest agent build to online devices from the dashboard:
- POST /api/devices/{id}/update-agent and POST /api/orgs/{id}/update-agents
send a one-time, token-authorised installer URL over the agent socket.
- install.msi now also authorises via ?token= so the agent can pull the MSI
without a browser session.
- New agent updater module applies the update in place (Windows: detached
msiexec major-upgrade + relaunch; Linux: extract agent.zip over the install
dir, preserving config + device id, then restart the service).
- Device drawer gets an Agent section (installed vs latest + Update button);
Downloads gets Update all online agents.
Annotate each used one-time key with the hostname of the device it enrolled (from the device_id recorded when the key was consumed), and add a Device column to the enrolment-key list.
- Server keeps recent log records in an in-memory ring buffer (root + uvicorn loggers) and exposes them via GET /api/logs (admin only, level filter). - New GET /api/version; /api/settings now also returns RMM_VERSION. - Settings gains a Logs section (level filter + refresh, newest last) and an About card in General showing the server version.
SERVER_VERSION now resolves at startup from RMM_VERSION, a baked VERSION file,
or 'git describe' (native installs), falling back to a static default. The
Docker build accepts --build-arg RMM_VERSION and compose passes ${RMM_VERSION},
so the deployed git tag/commit shows in Settings.
- docker_update.py talks to the Docker socket (no extra deps) to pull the latest image and recreate this container watchtower-style: it prepares a create-spec cloning the running container's config onto the new image and launches a detached helper (the new image) that stops the old container, recreates it under the same name, and starts it — rolling back on failure. - Endpoints: GET /api/server/update (status), POST /api/server/update/check (pull + compare), POST /api/server/update/apply (recreate). Admin only, gated on the socket being mounted. - Settings → General 'About this server' gains Check for updates + Update & restart, with an auto-reconnect spinner while the server comes back. - compose: default to the GHCR image, mount /var/run/docker.sock, and pass RMM_SERVER_IMAGE so the updater knows what to track (build-from-source path kept as commented fallback). - New CI workflow publishes the server image to ghcr.io/<repo>-server on pushes to main/beta and version tags.
- power: run lock/logoff in the interactive console session (the agent runs as SYSTEM in session 0, where LockWorkStation/shutdown /l have no effect). Lock launches rundll32 via CreateProcessAsUserW on the active session token; logoff targets the active console session id. - get_device now attaches a node's configured subnets so the device drawer lists them after promotion / adding. - Collect the logged-in/console user in agent inventory and show it in the device drawer header + Inventory panel (new logged_in_user column + migration).
The agent includes logged_in_user in each metrics payload; the server updates the device on every heartbeat (writing only when it changes), so the dashboard tracks sign-in/out within ~30s instead of waiting for a re-register.
Single source of truth: /VERSION = 1.1.0. Server resolver + Dockerfile read it, AGENT_VERSION bumped to 1.1.0, server-image tags ghcr :1.1.0, and the Windows MSI publishes a v1.1.0 release with MSI version 1.1.<run>.0 (monotonic upgrade over the 1.0.x line).
- Subnet add/remove (and promote/demote) from a device drawer now refresh the org cache and re-render the Nodes + Network views, so they no longer show stale subnets. - Network scan now folds in hosts from the ARP table within the scanned subnets, not just ICMP responders — so devices that drop ping (e.g. Windows' default firewall) are discovered too. Results are flagged online.
A node's previously-seen hosts that are absent from its latest scan are marked offline (last_seen preserved), and flip back online on rediscovery.
The MSI keeps server URL + key in machine env vars set from its properties; the self-update reinstalled without them, so a major-upgrade wiped the config. Now: - the Windows self-update re-passes RMM_SERVER_URL/RMM_API_KEY/RMM_INSECURE_TLS as msiexec properties (from the running agent's config), and - the agent persists its resolved config to %ProgramData%\LeuffenRMM (which the installer never touches), so it survives any reinstall via the file fallback.
- Subnets are normalised to their network address and de-duplicated on add (idempotent); a migration removes any existing duplicate (node, subnet) rows. - Windows agents add a best-effort, idempotent firewall rule allowing inbound ICMP echo from the local subnet, so a relay node in the same org can reliably discover them and confirm on-LAN reachability. Linux answers ICMP by default.
- The auto inbound-ICMP rule now allows any source (so a relay node in a different VLAN can ping across subnets) but applies only to the Domain and Private firewall profiles — a device on an untrusted Public network (café/ airport WiFi) still won't answer pings. - Agents enable 'Wake on Magic Packet' on physical NICs (best-effort) so they can actually be woken by the node; the OS firewall doesn't gate WoL (the NIC catches the magic packet in hardware while the machine is off).
- The device drawer's Update button now compares the installed agent version against the latest release: when they match it shows 'Up to date' (disabled) instead of always offering an update. - Bump VERSION/AGENT_VERSION to 1.1.1 so today's accumulated agent fixes (config preservation, ping rule + trusted profiles, WoL, subnet dedupe, discovery) are a distinct, detectable version.
Agent-update and installer-download operations mint one-time tokens to authorise a re-download; these are never consumed (the device is already enrolled), so they piled up as 'unused' enrolment keys. Tokens now carry a kind: 'enroll' (shown, user-generated for onboarding) vs 'internal' (hidden download/update auth). The onboarding-keys list shows only 'enroll'; a migration reclassifies existing agent-update/installer tokens and prunes expired internal ones.
- Every org tab (devices/approvals/network/nodes/monitors/scripts) and the global overview now refresh in the background on a timer (5-10s), pausing when the browser tab is hidden. Downloads is left static. - The current location (global vs org + tab) is stored in the URL hash, so a browser refresh restores the same page instead of snapping back to the global dashboard.
- Agent reports per-volume disk usage each heartbeat; the device Overview shows
the primary drive (C:/) by default and expands to all drives on click.
- Remote file management: new Files tab in the device drawer to browse folders,
download/upload (<=25MB), create folders, and delete — bridged to agent file
handlers (file_list/get/put/delete/mkdir). Folder sizes are computed on demand
(bounded walk) via a per-folder 'calc' button.
- Server: file endpoints under /api/devices/{id}/files/*, disks_json column +
heartbeat update, python-multipart for uploads.
The global Fleet overview is now widget-driven and customisable per user: - Widget catalog: totals, organisations, needs-attention, pending approvals, storage pressure, monitor alerts, agent-version spread. - Customise panel toggles widgets on/off and reorders them; saved per user (dashboard_prefs table). New GET/PUT /api/dashboard with aggregated data. - Attention/disk rows drill into the device; approvals/org cards navigate in. Server + UI only; agent unchanged.
Per decision, the ransomware behaviour monitor + auto-isolate is out of scope. Phase 3 is now just the (shipped) configurable dashboard widgets.
The Files tab now launches a large centered popup instead of rendering in the narrow device drawer, giving room to browse/upload/download. Closing it returns to the Overview tab.
A wake with no explicit broadcast was sent as 255.255.255.255, which never leaves the relay node's own L2 segment — so waking a device in a different VLAN than the node failed. The server now resolves the matching node subnet's directed broadcast (e.g. 192.168.50.255) and passes it to the node, so the packet can be routed into the target VLAN.
- Metrics kept 30 days (was 7); device Overview gains a History section with 24h/7d/30d range charts (server down-samples to ~120 buckets per range). - Agent collects GPU name(s) (WMI / nvidia-smi / lspci); shown as 'Graphics' in the device inventory (new gpu column + migration). - WoL now logs the target MAC, broadcast, port, relay node, and the agent's ack to Settings -> Logs, to help diagnose wake failures.
Fast Startup (hybrid shutdown) powers the NIC fully down, so a normal shutdown leaves the machine unwakeable even with 'Wake on Magic Packet' enabled — the most common cause of WoL silently failing after a Windows update/reboot. The agent now also sets HiberbootEnabled=0 (disables Fast Startup, keeps hibernation).
- install.sh extracts the agent with Python's stdlib zipfile when 'unzip' isn't present (it was failing with 'unzip: command not found' on minimal hosts). - Wake-on-LAN is now an admin-controlled policy (Settings -> Agents, off by default) instead of always-on. When enabled, agents configure the full set of NIC settings for WoL (magic packet, allow-to-wake, disable EEE/green ethernet) and disable Fast Startup; when disabled they leave/restore Windows defaults. Pushed over the agent socket on connect and immediately when the toggle changes.
…ates - The Monitors nav/tab is now 'Policies' (add monitors or standards). - Wake-on-LAN is a global Device Policy shown in the Policies -> Template rules view (global-admin only) with an enable/disable toggle, instead of a Settings -> Agents per-server toggle. Backed by the existing RMM_ENABLE_WOL setting, which pushes to connected agents immediately.
- WoL is now a 'policy' template in Policies -> Template rules, added like any monitor (with scope: global/site/group/device). One standard config (no thresholds). Declares os_support=[windows, windows_server]. - The agent WoL policy is computed per device from effective rules and whether its OS supports it; pushed on connect and immediately when a WoL rule changes. - Device drawer gains an 'Applied policies' section listing every rule/policy targeting the device, each flagged active or 'not supported' for its OS. - Alert pipeline skips the wol metric; removed the old global RMM_ENABLE_WOL setting and the Settings/Device-Policies toggles.
The copy value was stored in data-c via escapeHtml, which doesn't escape double quotes — so a command like curl -fsSL "https://..." was cut off after 'curl -fsSL '. Use escapeAttr (escapes " and ') for the data-c attributes.
'pip3: command not found' on minimal hosts, and modern Debian/Ubuntu block system-wide pip. The installer now creates an isolated virtualenv (installing python3-venv/pip via the host package manager if needed) and installs only the core deps (psutil, websockets) into it — the screen extras are skipped for headless installs. The systemd unit runs the venv's python.
The agent collects installed programs on demand (Windows uninstall registry;
Linux dpkg/rpm/apk) via a software_list control message. A new device Software
tab pulls a fresh list when the device is online (cached in software_json) and
shows the cached list when offline, with a filter. Endpoint:
GET /api/devices/{id}/software.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A batch of dashboard/maintenance features.
1. Agent self-update from the dashboard
msiexecmajor-upgrade + relaunch, Linux extractsagent.zipover the install dir preserving config + device id, then restarts. New MSI (1.0.16.0) already published.2. Enrolment key → device mapping
3. Logs & version in Settings
RMM_VERSIONenv → bakedVERSIONfile →git describe→ fallback. Docker build accepts--build-arg RMM_VERSION.4. One-click server container update (Docker socket)
docker_update.pypulls the latest image and recreates this container watchtower-style via a detached helper (clones config onto the new image, swaps under the same name, rolls back on failure). Admin-only, gated on the socket being mounted./var/run/docker.sock, and setsRMM_SERVER_IMAGE. New CI workflow publishesghcr.io/<repo>-serveron pushes to main/beta and tags.Testing
Rollout notes
main/beta; the one-click server update only works once an image exists in GHCR and the package is made accessible.https://claude.ai/code/session_018TtX9oATpQWkhMVwvbxNcf