Reports a Windows machine the way the Linux agent does, replacing the
"planned" stub in agent/windows: scheduled tasks plus hostname, IPv4
addresses, CPU model/cores/current load, memory, every fixed disk, and
TCP/UDP listening ports with the owning process (which feed the Ports
card, localhost-only listeners included).
Scripts (plain ASCII by design -- they are downloaded as text and Windows
PowerShell 5.1 reads BOM-less files as ANSI):
- report-tasks.ps1: collects and POSTs to /api/agent/report. Works in
Windows PowerShell 5.1 and PowerShell 7. -DryRun prints the JSON.
Microsoft's own \Microsoft\ tasks (hundreds) are left out unless
INCLUDE_MICROSOFT_TASKS is set. Triggers are turned into readable text
("Weekly on Mon, Wed at 03:00", "At logon", "..., repeating every 15 min").
Self-signed certificates work via API_INSECURE on both PowerShell
versions (they need different mechanisms).
- install.ps1: elevated only; downloads the agent to ProgramData, writes
agent.json with permissions locked to SYSTEM and Administrators *before*
the token goes in, and registers a SYSTEM scheduled task (every 15 min
plus at startup with a 2 min delay). Reinstalling replaces the task.
- uninstall.ps1: removes the task and only the files the agent installed.
Server: accepts schedule_type "windows_task"; a server can be registered
as Windows (Add a server has an operating system choice); an agent's
reported os_type ("linux"/"windows", anything else ignored) corrects the
stored one. The Servers page shows the right install and uninstall
command for each OS (Windows PowerShell 5.1 one-liners, with a self-signed
variant and a note about PowerShell 7), and Windows tasks are labelled
"Windows scheduled tasks". The Linux commands are unchanged.
Verified on this Windows machine, in both PowerShell 5.1 and 7:
- Real dry runs found and fixed bugs before anything shipped: tasks and
ports came out as one nested item (return , $out wrapped twice), integer
keys in an ordered dictionary index by position (wrong weekday names),
and generic "Trigger" labels.
- End to end against the real agent-report router: HTTP, self-signed HTTPS
refused by default and accepted with API_INSECURE, wrong token gives a
clear one-line error and exit 1, and Swedish letters plus a euro sign
survive JSON -> UTF-8 -> HTTP -> SQLite.
- 35 checks on trigger/action/duration descriptions, 20 on the installer's
building blocks (task parts built but not registered, credentials file
content and ACL, download over HTTP and self-signed HTTPS), 18 on the
server rules, and the generated one-liners run through PowerShell's
parser. The documented one-liners were run through iex and stop at the
administrator check without changing anything.
- Found that PowerShell 7 ignores the ServicePointManager certificate
override, so the installer's own download now uses -SkipCertificateCheck
there.
NOT verified: the elevated install itself. Registering a SYSTEM scheduled
task needs elevation and changes the machine, so it was not run: the task
registration, that the repeating trigger really runs indefinitely, and
the agent running as SYSTEM under Task Scheduler have not been exercised.
Windows 10 / Server 2016 or newer is assumed; older is untested.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Windows agent
Reports a Windows machine to Homelab Manager the same way the Linux agent does: its
scheduled tasks, plus hostname, IP addresses, CPU / memory / disk usage and listening ports. It
runs as a scheduled task (as SYSTEM, every 15 minutes) and pushes to POST /api/agent/report, so
the machine never needs to be reachable from Homelab Manager.
Install
-
In Homelab Manager, Servers → Manage servers → Add a server, choose Windows as the operating system, and copy the install command shown once for the new token.
-
On the Windows machine, open Windows PowerShell as administrator and paste it. It looks like:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $env:API_URL = 'https://homelab.example.lan'; $env:API_TOKEN = 'hlm_xxx' iex ((New-Object Net.WebClient).DownloadString("$env:API_URL/agent/windows/install.ps1"))
The installer downloads the agent to C:\ProgramData\HomelabManager\, stores the URL and token
there in agent.json (readable only by SYSTEM and Administrators), registers a scheduled task named
Homelab Manager Agent, and sends a first report so you see straight away whether it worked.
If Homelab Manager uses a self-signed certificate, tick the box in the Servers page: the command
then also skips certificate checks for the download and sets API_INSECURE, which makes the agent
skip them for every report. Only do that on a trusted LAN. That form is for Windows PowerShell 5.1
(the one built into Windows); in PowerShell 7 use -SkipCertificateCheck for the download step.
Set INTERVAL_MINUTES before installing to report more or less often (default 15).
What it reports
- Scheduled tasks — name, what they run (program and arguments), a readable description of their
triggers ("Daily at 02:00", "Weekly on Mon, Wed at 03:00", "At logon", "…, repeating every 15 min"),
next run time and whether they're enabled. They show up under Windows scheduled tasks. Microsoft's
own tasks (the
\Microsoft\folder — several hundred) are left out; setINCLUDE_MICROSOFT_TASKS=true(environment variable, or"includeMicrosoftTasks": trueinagent.json) to report them too. - System — IPv4 addresses (not loopback or 169.254.x), CPU model, cores and current processor load,
memory, and every fixed disk (
C:,D:, …). - Listening ports — TCP listeners and UDP endpoints with the program that owns them, so they appear on the server's Ports card, including services bound to localhost only.
Unlike the Linux agent's CPU figure (a load average), the Windows one is the processor's actual current load.
Try it without installing
$env:API_URL = 'https://homelab.example.lan'; $env:API_TOKEN = 'hlm_xxx'
.\report-tasks.ps1 -DryRun # prints the JSON it would send, sends nothing
.\report-tasks.ps1 # sends one report
Works in Windows PowerShell 5.1 and PowerShell 7, with or without administrator rights.
Check on it
Get-ScheduledTaskInfo -TaskName 'Homelab Manager Agent' # LastRunTime, LastTaskResult (0 = fine)
Start-ScheduledTask -TaskName 'Homelab Manager Agent' # run it now
Uninstall
In an elevated Windows PowerShell (the Servers page shows the exact command for that server):
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
iex ((New-Object Net.WebClient).DownloadString('https://homelab.example.lan/agent/windows/uninstall.ps1'))
This removes the scheduled task, the agent script and agent.json. The server's entry and history in
Homelab Manager are kept — delete it from the Servers page if you no longer want it tracked.
Notes
- Written for Windows 10 / Windows Server 2016 or newer. Older releases are untested; the repeating trigger is created without an end date, which very old Task Scheduler versions may not accept.
- The scripts in this folder are deliberately plain ASCII: they're downloaded as text, and Windows PowerShell 5.1 reads a file without a byte-order mark as ANSI, so anything else would be garbled.
- Task names, commands and ports are sent to your Homelab Manager server; see its Privacy page for what it stores.