Files
bobbanandClaude Sonnet 5 fea20456e4 Add a Windows agent (PowerShell)
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>
2026-09-27 00:09:00 +02:00

4.2 KiB

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

  1. 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.

  2. 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; set INCLUDE_MICROSOFT_TASKS=true (environment variable, or "includeMicrosoftTasks": true in agent.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.