Enrolling Windows hosts

Enrollment has two halves: the host installs the agent and registers itself, then an administrator approves it into an access group. A host cannot join your fleet on its own.

Install the agent

The agent ships as a single MSI. Installing it needs local administrator rights on the target machine and the URL of your Portrait server. The GUI installer prompts for the server URL; an unattended install passes it on the command line:

msiexec /i PortraitAgent.msi /qn SERVERURL=https://portrait.example.net

The MSI installs a Windows service running as SYSTEM, a separate isolated execution host for scripts, and the bundled PowerShell runtime. The agent is self-contained - it does not depend on the machine’s installed .NET or PowerShell version.

Use https://. An agent pointed at a plaintext http:// URL is refused by the server and the failure is not always obvious from the host. The agent protocol only runs over TLS.

Hostname-only registration

On first start the agent generates its keypair, binds it to the TPM where one is available, and registers with the server presenting only its hostname. There are no registration tokens and no shared secrets to distribute - that concept was removed because a stale token value is an invisible failure mode and the hold zone below makes it unnecessary.

The pending-approval hold zone

A freshly registered host lands in a pending state. It is not managed, receives no activities, and appears in a separate list from your live fleet:

GET /api/v1/agents?status=pending

This is a real, enforced quarantine, not a label. Nothing a pending host says is trusted and nothing is dispatched to it until an administrator acts.

Approving a host

Approval is a sensitive action (permission key agent.approve): you are admitting an unvetted, self-registered machine into your fleet. Approving a host places it into a chosen access group, which is what determines who can see and act on it from then on.

POST /api/v1/agents/{id}/approve   { "access_group": "root.workstations" }

If a policy requires TPM-bound identity for a given access group, that requirement is enforced here, at approval time - not at registration, since a token-less registration does not yet know which access group it is destined for.

Approve a host you did not expect, whose hostname you do not recognize, only after you have accounted for it. A pending host that never gets approved simply sits in the hold zone doing nothing.

Agent identity

Each agent holds a per-machine keypair. Where the host has a TPM, the private key is generated inside it and is non-exportable, which improves on a file-based secret that a cloned VM would carry with it. Portrait detects duplicate identities (a cloned VM presenting an existing agent’s key), suspends both claimants rather than guessing, and provides a signed recovery path that has the affected agent re-enrol cleanly.

Decommission and removal

Removing a host from management is a two-step, deliberately asymmetric process:

  • Decommission (agent.decommission) stops management and refuses further exchanges from that host. It is reversible: you can re-enrol the machine.
  • Delete (agent.delete, sensitive) permanently removes an already-decommissioned host together with its entire inventory, activity and alert history. This is irreversible.

To move a machine to a clean slate - a re-image, a repurpose - decommission it, then delete it, then install the agent fresh.