Skip to content

Fleet Deployment

Iain Smith edited this page Aug 29, 2026 · 6 revisions

Fleet Deployment

Running loadbearer unattended across a managed Windows estate — with PDQ Deploy / PDQ Inventory, Intune, ConfigMgr, or a GPO startup script — and collecting the result files centrally. The guidance is written for PDQ but the shape is the same everywhere.

loadbearer is a good fit for this: one self-contained .exe, no installer, no runtime, no registry writes, no persistence, no service, and it never launches a child process or makes a network call (unless you explicitly pass --net-target).

The deploy step

Install step → Run Command:

loadbearer.exe run --no-gpu --plain --duration short ^
  --target-dir "%ProgramData%\loadbearer" ^
  --output "%ProgramData%\loadbearer\%COMPUTERNAME%.json"

Then a Pull File step for %ProgramData%\loadbearer\%COMPUTERNAME%.json into a share, and a cleanup step (below).

Set the step timeout to at least 300 s — a short run is ~40 s of work, but a slow or busy machine, plus the disk benchmark's scratch-file fill, can take longer, and a step that times out mid-run leaves a scratch file behind.

Why each flag

Flag Why
--no-gpu Skips the GPU component and the OpenCL probe. Without it, every run (and loadbearer info) dlopens OpenCL.dll and enumerates devices; a stale ICD loader left behind by an uninstalled GPU driver can stall that. GPU is not in the grade anyway.
--plain Forces the plain-text report. It's implied when there's no console (PDQ runs as SYSTEM with redirected output), but pass it so a run through PsExec-with-console doesn't try to open the TUI. Use --json instead if you want to parse stdout directly.
--target-dir "%ProgramData%\loadbearer" Always set this. The default is the working directory, which under PDQ is a temp path you didn't choose — so the 1 GiB disk-benchmark scratch file lands somewhere arbitrary, and it measures that volume. Point it at the volume you want the disk numbers for (usually C:).
--duration short ~40 s total. normal is ~2½ min, thorough ~10 min — too long for a fleet sweep.
--output ...\%COMPUTERNAME%.json Writes the full versioned result (loadbearer.result/1) — machine inventory, every raw metric, the scored grade — for the Pull File step. Distinct filename per host.

The workload seed is fixed by default, so every machine runs the exact same benchmark and the results are directly comparable. Don't pass --seed unless you have a reason to.

Exit codes

loadbearer exits 0 on success and non-zero on any failure (unreadable config, unwritable --output, a benchmark error). PDQ marks the step failed on non-zero, so a failed sweep on a subset of machines is visible without parsing output. A panic (very unlikely in the graded CPU / memory / disk path) aborts the process — PDQ still sees a failure.

The scratch file

The disk benchmark creates .loadbearer-scratch.<pid> in --target-dir (1 GiB at normal, ~512 MiB at short), reuses it for every disk subtest, and deletes it on a normal exit. A step that is hard-killed — PDQ timeout, TerminateProcess, a reboot — leaves it behind.

The next loadbearer run against the same directory sweeps it: on start-up the disk benchmark removes any .loadbearer-scratch.<pid> that belongs to a different PID and hasn't been modified in 20 minutes (so a concurrent run is never disturbed), and records a note when it does. So on a recurring schedule the orphan is reclaimed automatically.

If a machine might not run loadbearer again for a while, add a cleanup step to the package to get the space back immediately:

del /q "%ProgramData%\loadbearer\.loadbearer-scratch.*" 2>nul

Signing, SmartScreen and Smart App Control

Releases are Authenticode-signed through SignPath.io's free programme for open source (certificate by the SignPath Foundation); the CI job signs the .exe when the repository's SIGNPATH_API_TOKEN / SIGNPATH_ORGANIZATION_ID are set, and ships it unsigned otherwise.

Control Behaviour
SmartScreen "Unrecognised app" on the first interactive launch until the certificate builds download reputation — More info → Run anyway, or Unblock-File. Does not block a SYSTEM-context deploy.
WDAC / AppLocker Honour explicit rules. Add a publisher rule for the SignPath Foundation certificate, or a file-hash rule for loadbearer.exe — hash from the release's SHA256SUMS (it lists the bare loadbearer.exe hash, not just the archive) or Get-FileHash. Hash rules permit an unsigned binary.
Smart App Control Blocks any binary that isn't signed and known-good to Microsoft's reputation service — "An Application Control policy has blocked this file". No allow rule, no hash exception applies. SAC is on by default on clean Windows 11 installs. A freshly-signed build can still be blocked until reputation accrues. On a SAC estate: deploy from a context SAC doesn't gate, use machines without SAC, or build from source.

For provenance when vetting a build, loadbearer is listed on Tiny Tool Town — its intake checks that the linked repository is real, carries an OSI licence (MIT here), and has a README. That is a directory listing, not a signature or an audit; the signature and the rules above are what actually gate execution.

Do not put these in a package

Command Why not
loadbearer net-server Binds 0.0.0.0:47913 and listens forever — it's the server half of the manual link test, not a fleet task.
loadbearer run --net-target HOST:PORT Makes an outbound connection to another host. Fine for a deliberate two-machine link test, wrong for a broadcast deploy.
loadbearer soak / run --soak Pins every core for 60–120 s. Useful on a single laptop you're assessing; a fleet-wide thermal event is not.

Collecting the results

Once the .json files are in a share, treat them as a corpus:

# rank a fleet, or diff a refresh candidate against the incumbents
loadbearer compare fleet\*.json

# just the headline per machine
jq -r '[.machine.hostname, .overall.score, .overall.grade] | @tsv' fleet\*.json

# build a house baseline from the machines you consider "par", then
# re-grade everything against it without re-running anything
loadbearer baseline fleet\dell-7420-*.json --name our-standard > our-standard.toml
for f in fleet\*.json; do loadbearer score "$f" --baseline our-standard.toml --json; done

The result files keep the full raw metrics, so they can be re-scored against a new baseline or curve at any time (see The Baseline) — you don't need to redeploy to change how the fleet is graded.

The diagnostic log

Every run also writes a plain-text diagnostic log (%LOCALAPPDATA%\loadbearer\loadbearer.log by default, or point it somewhere predictable):

loadbearer.exe run --no-gpu --plain --duration short ^
  --target-dir "%ProgramData%\loadbearer" ^
  --output "%ProgramData%\loadbearer\%COMPUTERNAME%.json" ^
  --log-file "%ProgramData%\loadbearer\%COMPUTERNAME%.log"

Pull it alongside the .json only from the machines that failed the step or graded oddly — it records the resolved settings, every subtest result, the GPU / disk / OpenCL fallbacks, and the error, so you can see why one machine differs without reproducing it by hand. Add --log-level debug for per-subtest detail. --no-log disables it entirely if your policy forbids the extra file. See Configuration.

What a run touches

  • Writes: the scratch file and the --output file under --target-dir, plus a diagnostic log (default %LOCALAPPDATA%, --log-file to place it, --no-log to suppress it). Nothing else on disk, nothing in the registry.
  • Network: none. The network component is loopback (127.0.0.1) only.
  • Privilege: none required. Runs fine as a standard user or as SYSTEM.
  • Processes: none spawned.
  • Persistence: none. It runs and exits.
  • Reads: machine inventory only — CPU, RAM, disks, GPU, and (on a laptop) the battery's charge / health / cycle count via the OS power interface. All of it lands in the --output JSON's machine block. A machine running on battery during the sweep is flagged in the report — its clocks may be power-capped, so prefer scheduling the run when the fleet is docked.

Clone this wiki locally