Polaris Agent - rogers-group-inc/polaris GitHub Wiki
A small Go binary installed on Windows, Linux and macOS hosts. It pushes monitoring samples back to Polaris over HTTPS and holds a long-lived outbound WebSocket for on-demand probes.
Managed from the Integrations β Polaris Agents tab, and per-device from the asset slide-over.
The agent is a satellite. It never self-acts, and it refuses unknown
actions. It accepts two queued actions: run_script β see
Automation scripts β and reboot, only on a host
that opted in (Reboots).
| Platform | Runs as |
|---|---|
| Linux | a hardened systemd unit β DynamicUser, NoNewPrivileges, ProtectSystem=strict β at one of two tiers |
| Windows | LocalSystem, under the Service Control Manager |
| macOS | a LaunchDaemon, as root |
| Tier | Grants | Enough for |
|---|---|---|
unprivileged (default) |
nothing extra | all monitoring |
ptrace |
CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH
|
Application Map connection attribution |
The pair is load-bearing β do not grant one without the other. A foreign
/proc/<pid>/fdis an owner-only directory whose open is a plain DAC check that onlyCAP_DAC_READ_SEARCHpasses;CAP_SYS_PTRACEis consulted only at the readlink step. A SYS_PTRACE-only unit fails at the open, every socket comes back unattributed, and the agent collects zero connection rows while looking perfectly healthy.A unit that holds only
CAP_SYS_PTRACEstays broken until reinstalled β the unit text is written only at install or reinstall.
The security cost is stated in every warning, and it is real:
CAP_DAC_READ_SEARCH bypasses read permission checks on all files, and
CAP_SYS_PTRACE reads any process's memory. Grant it deliberately.
Pick the tier on the per-asset install modal or the bulk Deploy Agent modal (confirmation-gated). An existing Linux agent changes tier via Reinstall.
privilegeTier is only what was requested at install. The Linux agent
reports its actual capability mask on every heartbeat, and the
installed-agents list renders the Privilege column three ways:
| Rendering | Means |
|---|---|
| pair-verified β | the running unit really holds both capabilities |
| "reinstall" in red | a stale unit β the tier was requested but the unit does not deliver it |
| unverified, amber | no report yet |
So a reinstall visibly updates the column within one heartbeat.
Polaris can reboot a host through its agent from the asset's
Reboot button, now or on a schedule β but only a host that
opted in (rule 115). Off by default. Turn it on
with Allow Polaris to reboot this host in the install modal (or these
hosts in the bulk Deploy Agent modal), or later with Enable⦠on the
Reboots row of the agent card; Disable turns it off. Both need
assets:fullwrite, and both sign in with the agent's stored install
credential to change the host itself:
| Platform | What the opt-in installs |
|---|---|
| Linux | a polkit rule letting the polaris-agent user (or the polaris-agent service) ask systemd-logind to reboot β the logind reboot actions and nothing else β written for both polkit rule formats, plus a root-owned marker file /etc/polaris-agent-reboot.enabled. The agent unit and its privilege tier are not changed, so nothing is reinstalled. The host needs systemd and polkit; without them the opt-in fails and says which is missing |
| Windows | a marker file reboot.enabled in the agent's %ProgramData%\Polaris\agent folder, writable only by Administrators and SYSTEM. The service already runs as LocalSystem, so the marker is the opt-in rather than a new privilege |
| macOS | a marker file /etc/polaris-agent/reboot.enabled
|
The agent refuses a reboot unless the marker is there, and reports on every heartbeat whether the host will let it reboot (on Linux: the marker is present and logind answers yes to the agent). The Reboot button is offered only when both Polaris and the host say yes, and the Reboots row reads Enabled β, Enabled β waiting for the agent to confirm, or Enabled β the host refuses (turn it off and on again to reinstall the permission). Disabling stops Polaris from sending reboots straight away, even when the host cannot be reached to remove the permission β the Event says so. Uninstalling the agent removes the marker and the polkit rule.
Rebooting needs agent 0.26.0 or newer. The agent acknowledges the reboot first and restarts the host five seconds later; Windows closes open applications without asking. An agent that does not pick the reboot up within about two and a half minutes never runs it β Polaris withdraws it β so an offline host never reboots hours after it was asked.
The host stays in maintenance through the reboot until monitoring has recorded it from the agent's first report of the new uptime β the agent reconnecting does not end the window, because it reconnects before that report. An automation's reboot action can book a reboot of an opted-in host too.
Three routes, all needing assets:fullwrite
(rule 43) β deploying runs an installer on someone
else's host over a stored credential and leaves a service behind.
| Route | |
|---|---|
| Per asset | the asset slide-over's System tab carries a Polaris Agent card with an Install Agent button on every server and workstation that could take one β no need to pick "Polaris Agent" as a polling method first. Any other device type shows the card once an agent exists or a stream is set to the agent method. The edit modal's Monitoring tab has the same button. Neither appears on a FortiManager- or FortiGate-discovered asset or on an ESXi host: FortiOS and ESXi take no agent. On a Windows host the modal adds a Transport choice β SSH (preselected; needs OpenSSH Server running on the host) or WinRM β and shows the credential picker for whichever is chosen. Linux and macOS are SSH-only, and the row is hidden. Allow Polaris to reboot this host installs the reboot opt-in with the agent |
| Bulk | the Assets bulk bar's Deploy Agent β one modal collects SSH + WinRM credentials and arch; OS and transport are resolved server-side, an asset whose last install failed is retried with the credentials you pick, and other ineligible assets come back as skips with reasons |
| Auto-deploy | a per-class toggle on the AD / Entra / Arc workstation and server blocks and the vCenter Virtual Machines block, off by default β pushes to newly discovered agent-less devices during discovery, bounded and paced |
Enabling an integration's auto-deploy checkbox is the same grant, chained
onto integrations:write β a capability with two doors has to be gated at both.
Only the on transition is gated; a role that inherits an enabled block can
still switch it off.
Writes the binary, writes agent.conf, installs the service, starts it. The
agent then enrols on first boot, receives a bearer token, and persists it back
into agent.conf.
Over SSH, everything is first uploaded into a folder created for that one run,
which no other account on the host can open: a fresh mktemp folder on Linux
and macOS, a new folder in the SSH account's own temp folder on Windows. The
installer checks the binary's SHA-256 before installing it, and the folder is
deleted afterwards, whether the install worked or not. Upgrades, uninstalls and
reboot-permission changes work the same way
(rule 119). The SSH account's temp folder must not
be C:\Windows\Temp; Polaris refuses to stage there.
agent.conf is readable only by the agent's service account and
administrators. On Linux and macOS it is mode 0600. On Windows the installer
makes Administrators the owner of %ProgramData%\Polaris\agent, and limits
that folder to SYSTEM and Administrators, before it writes anything there. The
agent (0.26.1+) protects each rewrite of the file the same way before the
token goes into it (rule 117).
One Linux trap worth knowing, because its failure mode is silent from Polaris's side: the installer must chown
agent.confto the state directory's owner, never to root. systemd chowns the StateDirectory to the dynamic UID at start but leaves files already inside it alone β so a root-owned conf is readable on a first install and unreadable on every reinstall. The installer exits 0, the row reaches "enrolling", and the host crash-loops on a permission error forever with nothing marked failed, until the enrollment token expires.
Integrations β Polaris Agents β SSH Deployment. Polaris generates the ed25519 keypair used to install the agent over OpenSSH, owns the credential holding it, and emits the scripts that authorise the public half fleet-wide.
The private half is sealed at rest and never returned by any read path. Recovery is regenerate and re-run the script, which is why the scripts are idempotent. The public key is deliberately non-secret so the script can be re-rendered without rotating the key.
Generating it carries a chained gate: serverSettingsSystem:write
and credentials:write, since it mints a fleet-wide admin credential.
Settings are per platform, and Polaris maintains one managed credential per
platform β a credential holds one username, and a Windows DOMAIN\user is
meaningless on Linux.
| Script | Does |
|---|---|
| Remediation | installs and starts the SSH server, optionally creates the local admin account, installs the public key with the right ACL/ownership, optionally scopes inbound TCP/22, and on Windows settles the firewall profile (below) |
| Detection | exit 0 = onboarded, 1 = remediate |
Pairing them under an Intune Remediation or an SCCM Configuration Baseline is what makes rollout self-healing β a plain platform script runs once per device and never retries.
The remediation installs OpenSSH Server only when Windows reports it missing.
It never checks the version, and it never reinstalls. A machine can report
OpenSSH Server as Installed while its sshd.exe is years out of date. The
service then times out on start (error 1053), and the script stops before it
reaches the account and key steps.
When that happens, both scripts name the cause in the Intune output columns:
| Script | Output |
|---|---|
| Detection | remediate: sshd not running (sshd.exe OpenSSH_7.7p1 for Windows; last SCM event 7009 at β¦: A timeout was reached β¦) |
| Remediation |
error: sshd failed to start - β¦, then the same version and Service Control Manager event, and exit 1 |
An sshd.exe version far older than a healthy machine on the same Windows
build means a stale install. Remove and reinstall the capability on that
endpoint (Remove-WindowsCapability, then Add-WindowsCapability, with a
reboot between them if Windows asks for one). The next remediation run then
finishes on its own. A current version together with a timeout points instead
at something stopping sshd.exe, such as endpoint security or application
control.
Platform differences that matter:
-
Windows β the key goes in
administrators_authorized_keyswith the Administrators+SYSTEM ACL sshd demands. -
Linux β the key goes in the user's
~/.ssh/authorized_keys(700/600, correctly owned) with arestoreconfor SELinux, and the script installs a NOPASSWD sudoers drop-in, validated withvisudo -cfbefore install since a bad one locks sudo out for everyone. The agent installer runssudo -n, so key auth alone cannot install an agent. It deliberately does not installopenssh-server.
Installing the OpenSSH Server capability makes Windows create its own rule,
OpenSSH-Server-In-TCP, and that rule is Private profile only and accepts
any source. Both halves of that are wrong for a fleet:
- On a domain-joined endpoint the active profile is Domain, so the rule never applies. sshd is installed, running and unreachable, with nothing in the service or the event log to say why.
- On a Private network it leaves port 22 open to every host on it. Firewall rules are additive allows, so a tightly scoped Polaris rule alongside it narrows nothing.
What the remediation script does about it depends on Polaris server address:
| Server address | Windows firewall after the run |
|---|---|
| set |
Polaris SSH (TCP 22) allows TCP/22 from that address on every profile, and OpenSSH-Server-In-TCP is disabled β the Polaris rule is the only inbound path to sshd |
| blank | nothing is opened; OpenSSH-Server-In-TCP is widened from Private to Domain, Private so a domain-joined endpoint is reachable. Which sources may connect is unchanged, so restrict port 22 some other way |
Public is deliberately never added. Reachable-from-Domain is the problem being solved; an any-source TCP/22 rule on the profile a laptop picks up in an airport is not. Both paths are idempotent.
The detection script checks the firewall too, against whichever of the two states the same Polaris server address produces:
| Server address | Detection reports "needs remediation" when |
|---|---|
| set |
Polaris SSH (TCP 22) is missing, disabled, not on every profile, or allows a different address; or OpenSSH-Server-In-TCP is still enabled |
| blank |
OpenSSH-Server-In-TCP does not cover the Domain profile. Whether it is enabled is not checked, because the remediation never turns back on a rule you turned off |
So a machine set up some other way (by hand, or by another script) is caught and remediated too. Otherwise, on a domain network, sshd would be listening with nothing able to reach it, and the first sign would be an agent install timing out while waiting for the SSH handshake. Detection and remediation are built from the same saved address, so change the address and re-publish both.
The script does not decide who may use SSH. It never writes
sshd_config, so stock Windows OpenSSH rules apply: noAllowUsers/AllowGroups, and password authentication on. Every account the endpoint lets log on can authenticate once sshd is running β the account on the card is only the one whose key is authorized. The firewall scope above is what limits who can reach the port. On an endpoint that already ran sshd, the script leaves its config alone: it starts the service only if stopped, appends the key, and sets the service to start Automatically.
Section 2 of the card, and the setting most likely to bite:
| Mode | What the script does |
|---|---|
| Use an existing administrator account | installs the key only. It does not create the account or change its group membership β but it does verify both, and stops with error: account β¦ does not exist on this host rather than installing a key for an account that is not there |
| Create a dedicated local account on each endpoint | creates it with a random password it never reports (key auth only), and adds it to Administrators |
Existing mode verifies without changing anything: choosing an account you already have is not asking Polaris to create one, or to promote one to administrator. If the check fails, the fix is yours to make β then the next remediation pass succeeds on its own.
A created Windows name is capped at 20 characters β the limit New-LocalUser
enforces β and is refused on save rather than failing later on every endpoint.
DOMAIN\user is legal only with an existing account: a domain account
cannot be created locally.
Troubleshooting a login that fails after a successful onboarding run. If an
agent install or upgrade reports All configured authentication methods failed,
the account is the first thing to check, not the key. administrators_authorized_keys
is machine-wide β it authorises any member of Administrators β so the key
lands correctly even when the account named on the card does not exist, and
every later login then fails in a way that reads like a key problem.
Detection catches this, on both platforms (business rule 72). It checks the account as well as the key, and reports which part is missing:
| Detection output | Meaning |
|---|---|
remediate: local account <name> missing |
the account is not on the endpoint |
remediate: local account <name> is disabled |
it exists but cannot log in |
remediate: <name> is not a member of Administrators |
it exists but the agent installer cannot use it |
ok: Polaris SSH onboarding present (<name> is a local administrator) |
ready |
A domain account (DOMAIN\user) is invisible to Get-LocalUser, so for one of
those only the group membership is checked.
If you want to confirm by hand, run Get-LocalUser and Get-LocalGroupMember -Group Administrators on the endpoint against the username the managed
credential carries. On an Entra-joined endpoint Get-LocalGroupMember may list
members as raw S-1-12-1-β¦ SIDs, or fail outright; the detection script falls
back to the WinNT:// provider for exactly that reason, so trust its verdict
over a bare Get-LocalGroupMember that errored.
Without the account check, an endpoint whose account was never created would report Detection: Without issues and Remediation: Not run β indistinguishable, in the Intune console, from a healthy one. The scripts are generated, not live: regenerate both halves from the card after upgrading Polaris, and machines in that state report as needing remediation on their next pass and fix themselves.
The scripts are delivery-neutral and fleet-generic β no machine-specific values β so the same body runs under Intune, GPO startup, SCCM, Arc, an RMM or a one-off remote invocation.
Operator input (username, the Polaris server IP) is rejected, not escaped:
it lands in a script an admin runs fleet-wide as SYSTEM.
Two vehicles, each opt-in per integration:
- Intune β Windows only, and Polaris never assigns the Remediation.
- Azure Arc Run Command β Windows and Linux, the only vehicle reaching Linux or Windows Server, with explicit target selection as the review gate.
On for every credential unless its Verify the server's host key box is unticked, and it fails closed (rule 21, rule 113).
Trust-on-first-use:
| State | Result |
|---|---|
| no pin stored | stores and accepts |
| pin matches | accepts |
| key changed | refuses the connection and stamps an event |
| internal error | refuses β it never silently skips |
Pins are per (host, port) in their own table, never on the credential. WinRM over HTTPS gets the same treatment for its TLS certificate when Verify TLS certificate is off. Both kinds of pin are listed under Windows SSH Deployment β Pinned server identities; delete one to trust a host that was legitimately rebuilt, re-keyed or re-certified. TLS certificates are also on Server Settings β Web Server: View pinned certificates opens a list with the asset each certificate belongs to, and a changed certificate shows both fingerprints and Trust new certificate pins exactly the one shown.
The agent does not use system roots. It compares the server's leaf
certificate SHA-256 against a pin set carried in agent.conf.
The pin embedded at install comes from the same certificate file nginx serves, and a reinstall re-reads the live certificate rather than trusting the stored one β otherwise a reinstall against a host first enrolled before a rotation would bake in the stale pin, the handshake would fail, and the agent would sit forever at "enrolling".
Server Settings β Maintenance β Polaris Agent β Cert pin rotation. Each agent carries a canonical pin plus a list of staged additional pins; the union is its trust set.
- Stage the new pin. It propagates fleet-wide; online agents apply within seconds over the WebSocket, offline agents on their next config poll.
- Rotate the server certificate. Agents keep working β both pins are trusted.
- Retire the old pin. If the canonical one is removed and a staged pin remains, the first staged pin is promoted.
The union must never be empty for an active agent β a removal that would empty it is skipped and reported. An empty pin set bricks the agent's TLS dialer until a manual reinstall.
agent.conf always carries both the multi-pin key and a single-pin key, so a
downgrade to an older binary keeps working.
| Stream | |
|---|---|
| responseTime | its own heartbeat |
| cpuMemory, temperature, interfaces, storage | host telemetry |
| β interface link state | agent 0.25.0+ reads each NIC's real link state, negotiated speed and duplex from the OS (sysfs on Linux, the network adapter on Windows). An older agent reports a NIC as up whenever it is enabled and sends no speed, so an unplugged cable reads up and an interface-down automation on that host never fires β upgrade the agent before relying on one |
| β interface addresses | each interface's address goes onto the asset's Addresses list with the source Agent. Because the agent's key belongs to that one asset, these count as strong evidence in the address confidence score, and so does the private address the agent connects from |
| β per-core CPU and the memory breakdown | the agent's own accounting β see below. vCenter reports both too, in its own vocabulary |
| processes | agent-default-ON β an installed agent collects its process inventory automatically |
| services | the unit / service inventory for the asset's Services tab, with per-service CPU and memory (agent 0.22.0+ on Windows). Ticking a service's Monitor box also collects its log: the journal on Linux, its Event Log entries on Windows (0.22.0+) |
| installed software | agent 0.24.0+; the program list for the asset's Software tab, read every six hours β the Windows Apps & features list (machine-wide installs; per-user installs are not seen) or the dpkg / rpm package database on Linux. Change the interval with software_inventory_interval_sec in agent.conf |
| eventLog | opt-in, behind a global master switch (PII and volume) |
| Application Map connections | needs the ptrace tier on Linux |
| Path checks | agent 0.21.0+; runs only the checks an operator created and pointed at this host. HTTP / HTTPS / TCP / ICMP plus traceroute, no extra privilege on any tier |
The storage and interface collectors run under a 30-second guard, because
statfs and interface ioctls can block indefinitely on a hung filesystem or
an unresponsive NIC β without it the whole push loop freezes while the heartbeat
keeps running and the agent looks connected.
A dead host sends nothing, so Polaris treats the agent's silence as the missed poll. Once an agent that finished deploying has been silent for two polling intervals, each further miss counts toward your down-detection automation, and the asset goes Down and raises Asset down just as a host that stopped answering pings would. Restarts and updates of Polaris itself, and agent upgrades, do not count. See rule 86.
Alongside the telemetry streams the agent reports what the machine is: hostname, OS and version, manufacturer, model, BIOS version and serial number. Because it runs on the host, this beats what a directory or MDM holds β those describe the machine as it was when it enrolled.
The serial comes from the firmware: /sys/class/dmi/id/product_serial on
Linux, the IORegistry on macOS, and the SMBIOS table on Windows.
Windows needs agent 0.20.1 or later for a real serial. Windows publishes no serial number in the registry; the agent reads the firmware table directly and reports the same value
Get-CimInstance Win32_BIOSshows. An agent below 0.20.1 reports the system SKU instead β a model code, identical on every unit of that model (a PowerEdge R740 reportsSKU=NotProvided;ModelName=PowerEdge R740). Upgrade the agent, and the serial corrects itself on the next check-in. Two things you may see when it does: a serial that changes on a Windows asset for no other reason, and β where the firmware has no serial to give β one that clears instead, which is deliberate. Both are recorded in Events.
On a hardened Linux host product_serial is often root-only, so an agent on
the unprivileged tier reports no serial and Polaris falls back to another
source. A serial the hardware never had programmed (To Be Filled By O.E.M.
and friends) is reported as no serial at all rather than passed on β see
Business Rules.
Each collection runs on its own cadence, and each one starts at a different offset inside the minute β so they never run at the same instant.
That matters more than it sounds. Several collections share a cadence: four
of them run every five minutes, and on Windows two of those shell out, one to
tasklist and one to PowerShell. Fired together, they make a visible CPU
spike every five minutes on a small host β and because the agent measures its
own response time by timing a round trip to Polaris, the spike lands on that
measurement too. Both charts on the System tab grow a five-minute sawtooth that
describes the agent rather than the host.
If you are looking at an agent host with that pattern, check the agent version: the stagger needs agent 0.19.0 or later, and an installed agent keeps its schedule until it is upgraded.
Each agent also picks a small random offset of its own at startup, so a fleet deployed in one batch does not arrive at the server in lockstep.
The offsets stagger when each collection starts. They cannot control how long one takes, and on a small or busy host a collection often overruns into the next one's slot β which is why nothing the agent measures is allowed to depend on having a quiet instant to itself. See the CPU reading below.
Every CPU figure the agent reports is an average over the whole gap since
its previous sample β by default the last 60 seconds, whatever
telemetry_interval_sec is set to. The agent reads the kernel's running CPU
counters and reports the difference; it does not sample a moment and it does
not pause to watch.
That matters on small hosts. A single short window once a minute would describe 1 second in 60 and say nothing about the other 59. On a single-vCPU VM that is actively misleading: if one of the agent's own collections is still running when the window opens, it holds the only core, and the sample reports ~100% CPU for a host that is otherwise idle β the chart describes the agent, not the machine. Spreading the collections across the minute does not prevent that, because a collection that starts in its own slot can still be running when a short window opens.
Two things follow, both worth knowing before you read a chart or set a threshold:
- The agent's own overhead cannot dominate a sample. It shows up as what it actually costs β a few percent of the interval β instead of as the entire reading on the ticks where it collides.
-
The cadence is the smoothing. A brief spike is averaged across the
whole interval rather than caught or missed at random, so the chart is
flatter than a point sample would draw, and CPU thresholds fire on a sustained average rather than on a
lucky sample. If you want a sharper chart on a particular host, shorten
telemetry_interval_sec; that shortens the averaging window with it.
This needs agent 0.20.0 or later. An agent below that takes a single 1-second sample once a minute until it is upgraded.
An agent-monitored host's Assets β System tab splits CPU & Memory into two charts: a CPU chart drawing one coloured line per logical core alongside the cross-core average, and a Memory chart that is a stacked area in bytes. FortiOS, SNMP, WinRM and SSH can report neither, so those assets keep the single combined CPU & Memory chart on one 0β100% axis. vCenter splits too, in its own vocabulary β it measures the same host from outside.
The split follows the CPU/Memory stream's polling method, not the presence of an agent: a host with the agent installed but that stream still pointed at SNMP is collecting one CPU figure per sample, and gets the combined chart.
What the agent sees and vCenter does not, and the reverse, is the point of running both on one VM. The agent reports the guest's own accounting β buffers and page cache, and which processes hold the rest. It cannot see ballooning or host swap at all: those are the hypervisor reclaiming memory from underneath the guest, and to the guest they simply look like memory it never had.
On the CPU chart:
- The Average line is the one every automation threshold reads. It stays on top and is the only line that dives to the baseline across a missed poll.
- The legend lists Average plus a chip per core. Click a chip to isolate that core; click it again, or click Average, to bring the rest back. The isolation survives the chart's automatic refresh.
- Hovering names the six busiest cores at that moment (or just the isolated one). On a host with many cores, isolate before you hover.
- Per-core detail is kept for the detail-retention window only (7 days by default β Server Settings β Retention). Longer ranges are served from hourly/daily rollups, which keep the average alone; the chart says so when that is why the cores are missing.
On the Memory chart the bands stack to what is actually in use, against a dashed line at the installed total β the gap between the two is free memory:
| Band | |
|---|---|
| Processes | resident in running programs |
| Buffers | Linux block-layer buffers (absent on Windows) |
| Cache | page cache (Linux) / system cache (Windows) |
| Swap / page file | a dashed line, not a band β it is backing store, not RAM, so it stacks with nothing |
Two figures here are commonly misread elsewhere and are deliberately not: Windows cache is the standby cache, which the usual API hides inside "available" memory, and Windows page file is the page file itself rather than the commit charge (which counts pages never written to disk and reads far higher).
An upgrade never refuses for want of a credential it can find itself, and never records one it has not proved (rule 49).
The credential is resolved in one order:
an explicit credentialId on the request
β the credential recorded at install
β the Polaris-managed SSH deployment credential for the platform
- An id that no longer resolves counts as absent, not as an error β deleting a credential would otherwise silently strand every agent installed with it, and some installs have no recorded credential at all.
- Only an explicit credential that fails to resolve is an error: an operator who names a credential is told it is wrong rather than quietly connected with another.
- The transport follows the credential's type, never the row's recorded transport.
-
An adopted credential is written back only on success. Reaching the host
is the proof. A genuinely WinRM-only box fails, keeps what it had recorded,
and lands as
upgrade_failedwith a real reason β itself an upgradeable status. - An operator override is never adopted; Polaris does not record a choice it did not make.
- A host the fan-out still cannot upgrade writes an
agent.upgrade_skippedEvent rather than being skipped silently. -
A host that monitoring shows as down is skipped, not attempted, by
Upgrade all out-of-date and by the automatic upgrade after a new build:
connecting to it would only sit out a timeout while the reachable hosts
wait. Nothing about the agent changes β it stays out of date, so the next
fan-out picks it up once the host is back, or you can use the host's own
Upgrade button, which is never skipped. Each one writes an info-level
agent.upgrade_deferredEvent (deliberately notagent.upgrade_skipped, so an automation watching for stranded hosts does not page about one that is simply off), and the toast says how many were skipped. A device that is not monitored is still attempted.
Upgrade only. Install, reinstall and uninstall require a credential on file; force-remove is the escape hatch.
An upgrade stops the agent service, which drops the agent's connection and
raises agent.disconnected β so Polaris puts the asset into a maintenance
window for the duration and the built-in disconnect automation stays quiet
(rule 80). The same applies to a reinstall and an
uninstall. A first install and a retry take no window: there is no agent running
to disconnect.
The device reads maintenance while it runs, and its Maintenance tab names the operation. The window ends when the agent reconnects β or immediately if the upgrade fails, because an agent that is down for that reason is worth an alert. Nothing can leave it open: it expires after 20 minutes (30 for a reinstall) whatever happened to the operation, and the suppressed alert then fires late rather than never.
It silences the whole device for that minute or two, not just the agent β Maintenance Windows has the detail.
The Polaris Agent card on Integrations β Polaris Agents carries the build: cross-compile the agent for the platform matrix from the Go toolchain on the Polaris host, with an optional code-signing step for Windows binaries against your internal CA.
Go is needed only for this. Java is needed only for signing. Without either, nothing else changes β you can download prebuilt binaries instead.
The jsign jar is not a field on the card. Polaris finds it at tools/jsign.jar
under the app or state directory (or /opt/polaris/tools/jsign.jar), and a jar
elsewhere is named with the POLARIS_JSIGN_JAR environment variable, because the
jar is run as code by the service account (rule 107).
The server URL the agents call back to can be overridden under Server Settings
β Agents. It must be a plain http:// or https:// address with an optional
port and path of letters, digits and . _ ~ - /; anything else is refused.
The card above the build card. Named rules that pin process and service items on the assets they select β now and on assets discovered later.
Each rule has a mode:
| Mode | |
|---|---|
| Monitor + map | Application Map and telemetry β mapping implies monitoring |
| Monitor only | per-program CPU/RAM and logs, per-unit log collection (journal / Event Log); never touches map pins |
A four-step wizard: name β devices β items β summary. The item step is scope-driven β it lists only what the selected devices report, which is what keeps a rule from pinning a unit on every host that happens to run it.
Rules only ever target workstations and servers, since nothing else reports an inventory.
Auto rules: ticking Monitor or Map on an asset's Services tab mints a single-item auto rule for that asset; pinning the same item elsewhere consolidates into it; un-ticking removes the asset, and an auto rule losing its last asset is deleted. Editing an auto rule in the wizard converts it to manual.
Mapping implies monitoring, one way. Nothing ever writes a map pin from a monitor pin. Removing an item or disabling a rule stops future auto-pinning; a separate Unmap everywhere action does the actual strip.
| Symptom | Look at |
|---|---|
| Stuck at "enrolling", host crash-looping | the Linux agent.conf ownership trap above β reinstall |
| Agent connected but the Application Map is empty | the Linux privilege tier. Check the Privilege column for "reinstall" β a SYS_PTRACE-only unit collects nothing while looking healthy |
| TLS handshake fails after a certificate rotation | the pin. Stage the new pin before rotating |
| Samples stop but the heartbeat continues | a hung filesystem or NIC in a collector β the 30 s guard bounds this |
| Upgrade skips a host | check for agent.upgrade_skipped Events |
An ICMP path check fails with icmp unsupported on this host (ping_group_range)
|
Linux only. The agent opens ICMP without privilege, which needs the service's group inside net.ipv4.ping_group_range. Modern distributions allow every group; RHEL 8 does not. Fix it on the host: echo 'net.ipv4.ping_group_range = 0 2147483647' | sudo tee /etc/sysctl.d/90-polaris-ping.conf && sudo sysctl --system. HTTP, TCP and traceroute are unaffected |
| A path check never produces results | the agent version (0.21.0+ runs checks β upgrade it), and whether the host is listed on the check's Results view. A host that is not listed does not match the check's Sources |
Every traceroute hop after the first shows *
|
the network drops ICMP errors (Time Exceeded) on the way back. The check result itself is unaffected |
| An agent host is powered off but the asset still reads Up | whether an automation covers it (no automation means Passive, rule 36); whether the agent is revoked or not yet active; and, with a single agent, whether Polaris just restarted. The agent gets a full window from boot (rule 86) |
A burst of agent.disconnected alerts right after an in-app update or restart |
the reason at the end of each Event's message. heartbeat timeout is a server too busy to answer while every agent redials it at once. A redialing agent's superseded connection closing does not raise a disconnect β Polaris ignores the old connection once the new one is up |
agent.disconnected alerts never clear |
the counterpart reset β an event automation should clear on agent.connected, scoped to the same subject (rule 32e) |