DocsPer platform

Windows

View source on GitHubdocs/platforms/windows.md

On this page

The Windows agent and the Windows probe have never run on a real Windows machine. They are cross-compiled, linted and unit-tested against hand-written fixtures. Treat everything on this page as untested until it has been tried on a real host. What each method reads is in the platform table.

Agentless over SSH#

Uses the built-in OpenSSH Server and Windows PowerShell 5.1 or later. Elevate PowerShell once to set it up:

  1. Install the feature: Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0, then Set-Service sshd -StartupType Automatic; Start-Service sshd.
  2. Create a dedicated account, for example yarrix. A standard user can read every base metric.
  3. Put the hub's public key in C:\Users\yarrix\.ssh\authorized_keys. For a member of Administrators the key must instead go in C:\ProgramData\ssh\administrators_authorized_keys, with the ACL reset so only Administrators and SYSTEM have access: icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F".
  4. Nothing else. The default shell can stay cmd.exe or be powershell.exe: the hub always runs powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command - and sends the script on stdin, so it works either way with no Yarrix setting.
MetricAgentless
Load averagen/a (Windows has none)
Temperature, GPUunknown
SMARTunknown: needs smartmontools installed and an Administrators account
RAIDn/a

CPU is the average of Win32_Processor.LoadPercentage. Disk and network rates come from cumulative counters on two consecutive polls, so rates appear from the second poll.

Does Windows OpenSSH honour command= in authorized_keys?#

Not verified. No Windows machine or VM was available for this page. A web search found no source that confirms or denies it (Microsoft's server configuration page lists unsupported sshd_config directives, and command= is a per-key option, so it does not appear there). Do not rely on a pinned command="...",restrict key on Windows until someone has recorded the result from a real host. On Windows, a forced command would also run through the account's DefaultShell.

With the agent (Windows service)#

For a Windows machine you would rather not open SSH on, the agent runs as a Windows service. It makes only outbound connections. Needs 64-bit Windows 10, 11 or Server 2019 and later. There are two ways to install it: the setup.exe (a double-click, for most people) and an elevated PowerShell script.

The installer (setup.exe)#

yarrix-agent-setup-windows-x64.exe is a normal installer built with NSIS. It is a thin wrapper: the real work is still yarrix agent install (copy into the protected C:\Program Files\yarrix, set the ACLs, register the service), so the installer and the script end in the same state. It adds a wizard, an Add/Remove Programs entry (Yarrix Agent) and an uninstaller.

  1. In the hub, open Add a host, choose Windows. The Installer tab shows a short address, http://<hub>/connect, and a six-digit PIN such as 458-283. The PIN works once and expires after 15 minutes; New PIN makes another.
  2. On the Windows PC, open that address in a browser (it is short, so type it), download the installer and run it. The file is this hub's own, so the installer already knows the hub. The installer from GitHub or a USB stick works too: it looks for the hub on the network for a few seconds ("Looking for your Yarrix hub...") and then shows the PIN box alone, with the hub it found named above it. With several hubs on the network the PIN picks the right one. If it finds none, it asks for the hub address as well (with Search again); a stamped installer whose hub does not answer searches first and then shows its own address in that box. Type an address instead is always there. It is not signed yet (see Signing), so SmartScreen shows "Windows protected your PC": choose More info, then Run anyway, then approve the administrator prompt.
  3. Enter the PIN (with or without the dash). The installer checks it before it installs anything: a wrong or used PIN keeps you on that page with the reason. Five wrong PINs from one PC lock it out for 15 minutes. The last page says "Connected" once the hub has accepted the PC, or "Installed, but not connected yet" with the last log line; the service keeps retrying either way.

A setup code from an older hub (https://yarrix.example.net#yxe_..., typed in the same box) still works.

The hub address should be https:// (or wss://). A hub on your own network that has no TLS can use http:// (or ws://) instead, so nobody needs Tailscale or a certificate to try it: the installer shows a warning and asks you to confirm (silent installs print the warning and continue), and writes insecure: true into agent.yaml, as the Linux agent does. The enrollment token and every report then cross the network unencrypted, so use plain http only on a network you trust. The installer does not check that the address is private; that is your call. An already-enrolled PC skips the code page: running a newer installer upgrades in place and keeps the connection and agent.yaml. Running an older installer over a newer install asks first (silent runs refuse, see below). Remove it in Settings, then Apps, or with uninstall.exe; that stops and deletes the service, removes state, buffer, log and token, deletes only the files the installer put in Program Files\yarrix (nothing recursively, so a link planted there is never followed) and removes the Apps entry. agent.yaml is kept, as with the script. The host stays in the hub until you remove it there.

Silent install (Intune, scripts, a deploy tool):

yarrix-agent-setup-windows-x64.exe /S /CODE=https://hub.example.net#yxe_...
yarrix-agent-setup-windows-x64.exe /S /HUB=https://hub.example.net /TOKENFILE=C:\path\token.txt
yarrix-agent-setup-windows-x64.exe /S                      (upgrade an enrolled agent in place)
"C:\Program Files\yarrix\uninstall.exe" /S                  (remove)

Optional: /TOKEN=<token>, /WAIT=<seconds> (default 90, 0 does not wait), /REPLACECONFIG, /ALLOWDOWNGRADE. For a fleet, create one reusable token (yarrix-hub enroll create --universal --max-uses N) and pass it with /TOKENFILE. A /CODE or /TOKEN value is on the installer's command line for a few seconds and in your deploy tool's logs, the same exposure as install-agent.ps1 -EnrollToken; the token itself never goes on the agent's command line or into a file the installer writes: the installer hands it to yarrix agent install through its environment (--enroll-token-env), and the agent stores it in the protected data folder as enroll.token, then deletes that file after the first enrollment. uninstall.exe /S returns before it has finished (NSIS runs an uninstaller from a temporary copy); wait for the Apps entry or the service to disappear.

Exit codeMeaning
0Installed and enrolled, or an enrolled agent upgraded (also with /WAIT=0)
2Bad or missing arguments, or not 64-bit Windows. Nothing was installed
3agent.yaml already points at a different hub. Nothing changed; add /REPLACECONFIG to switch (the old file is kept as agent.yaml.bak and the old enrollment is cleared)
4yarrix agent install failed
5Installed but not enrolled within /WAIT; the service keeps retrying
6An older installer over a newer install; add /ALLOWDOWNGRADE

Self-update stays the main way the agent changes version: the installer owns no files the way an MSI would, so the swap described in AGENT.md works unchanged. After an update is committed (the new build passed its trial) the agent writes the running version into the Apps entry, if there is one.

yarrix agent install also changed for both routes: --enroll-token-env / --enroll-token-stdin take a one-time token without a file or command line; the service deletes enroll.token once it has enrolled; and an existing agent.yaml that names a different hub makes it stop with exit code 3 and a message naming both hubs, instead of silently keeping the old one (--replace-config switches). install-agent.ps1 therefore fails on a reinstall for a different hub until agent.yaml is changed or removed.

Signing#

The installer and yarrix.exe are not Authenticode-signed. SmartScreen asks the user to click through, and Defender may flag an unsigned installer (submit it to Microsoft as a false positive). A PC with Smart App Control on blocks unsigned apps with no override, so there the agent cannot run at all, whichever route installed it; use the agentless SSH method or turn Smart App Control off. Signing is undecided (options: Azure Artifact Signing, about US$10 a month; an OV certificate; SignPath for public open-source). When it is decided: sign yarrix.exe in the agent-windows job before the manifest and the installer are built, and sign the setup.exe with YARRIX_SIGN_HOOK=<program> (called with the file path by scripts/release/package.sh before checksums). Signing does not change the minisign chain that gates self-update.

MSI is not offered. Group Policy software installation needs one; an MSI could later wrap the same yarrix agent install. Intune installs the .exe as a Win32 app.

Never run on a real Windows machine. The installer is built and compiled in CI, and CI installs, upgrades and removes it on a Windows runner (scripts/ci/windows-installer.ps1), but nobody has yet clicked through it on a desktop with a real hub. The SmartScreen and Smart App Control behaviour above is from Microsoft's documentation.

The PowerShell script#

# on the hub: yarrix-hub enroll create --host desk-1   (prints a one-time token)
.\install-agent.ps1 -Hub https://yarrix.example.net -EnrollToken <token>

deploy/windows/install-agent.ps1 downloads yarrix.exe, refuses to install it unless its SHA-256 matches (pass -Sha256, or let it fetch the .sha256 published beside the binary), copies it to C:\Program Files\yarrix\, writes the token to a file only SYSTEM and Administrators can read, runs yarrix agent install, waits for enrollment and then deletes the token file. -Hub also takes http:// or ws:// for a hub on your own network (with a warning; insecure: true is written for you, and the binary may then be downloaded from the hub over plain http, though its SHA-256 is still checked). -BinaryPath installs a binary you already have. -Uninstall removes everything but agent.yaml.

What yarrix agent install does (all of it also works by hand): copies itself to C:\Program Files\yarrix\yarrix.exe and registers that copy (never the path it was run from, which may be user-writable); creates C:\ProgramData\yarrix\ and restricts both folders to SYSTEM and Administrators with a protected DACL (full control, inheritable, parent inheritance cut) set directly through Win32 (SetNamedSecurityInfoW; no icacls), using well-known SIDs so it works in any display language. A folder that already exists has its link status and owner checked first, then its DACL is replaced, then every child is checked for link and owner and reset to inherit (nothing is ever re-owned), and finally the whole tree passes one gate: no reparse point (junction, symlink), owner SYSTEM or Administrators, and no allow-ACE for any other SID that grants write, delete, WRITE_DAC or WRITE_OWNER (a missing DACL and unrecognised ACE types are refused too). That gate (winacl::verify_tree) is the same for a fresh install and for "already the installed copy", and the service runs it on the data folder on every start, before it opens its log or reads agent.yaml, the token or the state. install-agent.ps1 applies the same rules with Set-Acl and runs them before any recursive delete. It writes agent.yaml there if none exists, registers the service yarrix-agent (LocalSystem, automatic start, restart after a crash: 5 s, 5 s, 30 s) and starts it. yarrix agent stop | start control it; yarrix agent uninstall stops and deletes the service and removes the state, buffer, log and token, but never agent.yaml. State is in ...\yarrix\state\, the log in ...\yarrix\agent.log (rotated to .1 at 1 MiB on each start). Before the service is installed, a console run of yarrix agent keeps its state under %LOCALAPPDATA%\yarrix instead.

MetricAgent
CPUGetSystemTimes: busy share of the interval
Memory, swapGlobalMemoryStatusEx for RAM; swap is the page files' size and use (SystemPageFileInformation)
Disk per volumeeach fixed drive letter, GetDiskFreeSpaceExW. Volumes mounted into a folder are not listed
Disk I/OIOCTL_DISK_PERFORMANCE on \\.\PhysicalDrive0..31: bytes and operations, per physical disk
NetworkGetIfTable2: physical adapters only (not loopback, tunnels, filter drivers or virtual switch ports), by adapter name
Uptime, boot idSystemTimeOfDayInformation; the boot id is boot-<unix seconds> as on macOS
Load averagen/a (Windows has none), never a zero
Temperatureunknown (no reliable API without vendor drivers), never a zero
GPUnvidia-smi if installed
Servicesservices: globs in agent.yaml, matched against service name or display name, case-insensitive
Sleepsleep_detection is ok when running as the service, unknown in a console run

Services: powershell.exe (found in System32 only, never on PATH) runs one fixed Get-CimInstance Win32_Service query; the globs are applied inside the agent and never reach a command line. A matched service is failed when its start mode is Automatic and it is not Running (a service still starting is not failed); a matched Manual or Disabled service is listed, not failed. List the services you care about, since many Automatic services stop on purpose (trigger-start ones such as Windows Update helpers). The hub's services.failed assert globs are case-sensitive: write the name as Windows spells it (sc query shows it).

Sleep and wake come from SERVICE_CONTROL_POWEREVENT (suspend, resume). The handler holds the suspend for up to 1.5 s (Windows allows about 2 s) until the sleep message is on the wire, so the host shows asleep, not red.

Not on the Windows agent yet: backup-destination probes (answered unknown with a reason). SMART reuses the Linux collector, which looks for smartctl.exe in Program Files\smartmontools\bin; that path has not been exercised.

Verification status. The Windows agent has been cross-compiled and linted for x86_64-pc-windows-gnu and its parsers and arithmetic are unit-tested on Linux and macOS fixtures, but it has never run on a real Windows machine: every Win32 call, the service registration, the ACL calls and the install script's ACL check, power events, the install script and the .sha256 download are untested until it has run on real Windows. Fixtures that stand in for Windows output are hand-written to the documented formats, not captured.