Remote Agents
The private-network half of the dashboard: the agents that poll out of a site for work, and the hypervisor connections they carry it out against. They share a page because a connection reached through an agent is named in that agent's own file — so the two are usually filled in together. Feature guide.
Containerised agents that run inside a private network and poll out to this dashboard for work — so on-premises hypervisors can be discovered and managed without opening a single inbound firewall rule. Each agent authenticates with an Ed25519 key it generates itself; no reusable credential ever crosses the wire.
Enrolment codes are blocked
The Identity tab shows the pinned audience and offers a reset; Public base URL is in Settings → Integrations → Remote Agents.
Remote agents are not enabled
Turn them on in
Settings → Integrations → Remote Agents.
Enabling publishes /api/agent for agents to reach,
so terminate TLS in front of the dashboard first — see
the remote agent docs.
You cannot see the agent list
Registering and revoking agents is administrator work; the connections they reach are governed separately.
Enrolled Agents
Migrating to SPIRE moves the key into memory: on a cloud VM nothing is stored at all,
and on a bare Docker host only SPIRE's own hourly-rotated key remains. A migrated
agent can then fetch its hypervisor credentials from the dashboard per job
(dashboard_secret: true), so none are stored on its host.
This dashboard releases the credentials it holds only to SPIRE-attested agents, so jobs on these agents that need one are refused until they migrate.
| Name | Site | Status | Registered by | Source IP | Version | Last seen | Running | ||
|---|---|---|---|---|---|---|---|---|---|
| update canary paused | |||||||||
|
|||||||||
Lifecycle
Upgrade and restart need an agent attested through SPIRE, on 2.10 or newer, whose
policy.yaml enables upgrades: and
which has the updater container beside it. The updater verifies each image's
signature before it pulls; a release recorded here is only a choice.
How it works
Releases
Rollouts
Every eligible agent: the canary ring first, the rest once every canary is up on the release. Any failure stops the rollout.
Its updater verifies the release's signature, swaps the container, and rolls back if the new agent does not come up. It currently reports .
Starts at this time, and is marked missed if it has not started within the grace period — it will never run late.
No change windows are defined yet. An administrator can add them in Settings.
Next:
–
UTC
Register Agent
Enrolment code for
Shown once. It expires in 15 minutes and can only be redeemed a single time.
The agent image is Linux; on Windows it runs in Docker Desktop's Linux VM, so keep Docker Desktop in Linux containers mode. See Running on Windows.
Alternative: keep the code out of docker inspect
Mounts the code as a file instead of an environment variable, so nothing durable in
Docker's metadata holds it. Follows the toggle above. To keep the code out of your
shell history too, create agent-enroll-code with an
editor — just the code, on one line — and paste only the
docker run that follows.
Save it as plain ASCII or UTF-8 without a byte-order mark — Notepad's "Unicode" and "UTF-8 with BOM" options both produce a file the agent cannot read. PowerShell also writes its history to disk as you type, so an editor is the only way to keep the code out of it.
The agent needs a policy.yaml naming the networks it may
scan — it refuses all work without one. See
the remote agent docs
for a starting file.
Migrate to SPIRE
New SPIRE join token for
Its SPIRE identity expired while its host was offline, and a join token works only
once. Only the token changes: leave the rest of the agent's
.env and its spire/bootstrap.crt as they are.
The SPIRE entries exist and the agent is bound to
.
Its current key keeps working until it first attests, so nothing breaks in between.
The join token below is shown once, works once, and expires in minutes.
-
In the agent's
.env, replace theSPIRE_JOIN_TOKEN=line with: -
Recreate its containers. Never
down -v: that deletes the SPIRE agent's data.
-
On the agent host, beside its
docker-compose.yml, save the trust bundle asspire/bootstrap.crt: -
Add these to the agent's
.env: -
Restart it with the SPIRE overlay:
Needs agent image 2.6.0 or newer, and outbound access to the SPIRE server's port (8081) — a TLS-inspecting proxy needs a bypass for it. To go back, use Re-enrol: it clears the SPIRE binding and issues a fresh code.
Discover via
Unauthenticated probes only — a TCP connect and a protocol banner. Nothing ever attempts a login. The agent will refuse any target outside its own policy file.
Probes never authenticate, so a WinRM answer identifies Windows — not necessarily a Hyper-V host. Those findings are marked possible only.
Deployed agents
Agents the dashboard builds for you in AWS, Azure or Google Cloud, to run Config Management on the VMs in that network. A host has no public address and no inbound rule. It can stay up, go away at a set time, or come up just before each occurrence of a change window and go away after it. How deployed agents work.
No deployed agents yet.
| Agent | Where | Lifecycle | Host | Ranges | |
|---|---|---|---|---|---|
|
agent ·
at once · Kubernetes
|
· routed
|
Deploy an agent
The agent runs Config Management only, against the ranges below. Its identity is , minted fresh every time its host starts.
No region of this cloud has a VM subnet configured (Settings → Clouds).
Comma- or space-separated. Written into the agent's own policy, which it enforces.
Clusters in its cloud can then choose to run their Kubernetes work on it, which hands it their cluster-admin kubeconfig for each job. Needs SPIRE attestation.
Where each on-premises hypervisor lives and how to authenticate to it. You can have more than one of each kind — a second vCenter, a Proxmox cluster per site — and the default is what a page uses when it isn't told otherwise. A connection bound to a remote agent never holds the host or username here — the agent has those, and this row names which of its connections to use. It may hold the credential, so the agent can fetch it per job and store nothing.
You cannot see the connection list
| Name | Kind | Endpoint | Reached via | Credential | Status | Actions |
|---|---|---|---|---|---|---|
| default | Dashboard |
Held by dashboard
Not fetched by the agent yet
On the agent host
None set
connections.yaml
|
Error OK Untested |
|
The dashboard cannot dial this endpoint, so it never stores the host or the
username — those always come from the agent's own
connections.yaml, and this row
names which entry to use.
Must match the name: of an entry in that agent's file exactly.
The agent then fetches it for each job, encrypted to a key that exists only
for that fetch, and stores nothing. Takes effect once that agent's
connections.yaml sets
dashboard_secret: true on this
entry — until then the agent keeps using its own credential and this is
ignored.
Recommended. The managed account id — the dashboard then holds no password either: it checks one out per job, checks it back in, and rotates it on release. Leave blank to use one of the two below.
bt_safe://, aws_sm://,
azure_kv:// or gcp_sm:// — the dashboard
stores a pointer and resolves it per job.
Stored encrypted, but a standing hypervisor password in this database is the weakest of the three — prefer a managed account or a reference above. Leave blank to keep the existing one.
Leave blank to keep the stored one.
Which agent executes a Config-Management run against an address range.
Without a route, a run goes to the agent whose hypervisor connection discovered the VM —
which is right until that agent has no network path to the guests it can see. The most
specific range wins, so a /32 overrides a /24.
Feature guide.
You cannot see the route list
| Range | Scope | Executes on | Covers | Status | Actions |
|---|---|---|---|---|---|
| worker fallback |
not granted Config Management
|
Active Inactive |
This designates who runs the playbook, never
what it runs against. The address still comes from the synced VM
row, reported by the agent that discovered it. The agent you name needs its own
agent_ansible grant on the Agents tab, and its own
ansible.targets entry covering this range in its
policy.yaml — two agents means two policy files, and the second one
is the step people miss.
A CIDR range, or a single host. The most specific matching range wins.
That agent is not granted the Config-Management job type yet. Grant
agent_ansible to it on the Agents tab, or every run in this range
will be refused.
Dashboard-deployed VMs in this cloud whose private address is in the range, and databases whose subnets all are, run their Config Management on this agent instead of the remote worker. Run the agent inside that VPC or VNet. Their SSH key or database login is sealed to the agent per job: consider "Release dashboard-held credentials only to SPIRE-attested agents".
Only guests discovered through this connection — for two sites that use the same range. The agent above still executes; the connection's own agent only discovers.
Only VMs deployed to this region — for VPCs in different regions that use the same range, such as the default VPCs.
Only VMs deployed into this VPC, VNet or network — the exact answer when two networks share a range. Listed from the networks this dashboard has deployed into.
Only VMs deployed in this workstream — for teams whose networks use the same range in one region. It also keeps one team's agent from ever being handed another team's VMs or their keys.
Otherwise a run is refused while the agent is down. A run booked into a time a deployed agent will be up stays on the agent. Only playbooks fall back.
You cannot see the agents' identity
This tab needs the agents permission.
Signing audience
The address every agent signs its requests against. It is pinned by the first enrolment code and never moves on its own, so a corrected Public base URL leaves enrolled agents working and refuses new codes until the two agree.
Not pinned yet. The next enrolment code pins it permanently to .
New enrolment codes are refused until this is resolved.
Clears the pin so the next enrolment code re-pins it from Public base URL. Every enrolled agent stops authenticating and has to be re-enrolled with a fresh code.
Public base URL is set in Settings → Integrations → Remote Agents.