Linux binary
Route status: PUBLISHED — acceptance steps 1–7 passed on 2026-08-07/08 against agent 0.1.1,
in the field and against production, including a restart on the persisted credential.
If this host can run containers, the Docker route is shorter — one line and no unit file. This route exists for the hosts that cannot: corporate policy, an older distribution, an appliance, a single-board machine on a factory floor.
Get your token first (step 1); the enrolment panel renders this block with the token and your server URL already substituted.
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') &&curl -fsSL -O https://github.com/WireWatch/agent-releases/releases/download/agent-v0.1.3/agent_0.1.3_linux_$ARCH.tar.gz -O https://github.com/WireWatch/agent-releases/releases/download/agent-v0.1.3/SHA256SUMS -O https://github.com/WireWatch/agent-releases/releases/download/agent-v0.1.3/SHA256SUMS.cosign.bundle &&cosign verify-blob --bundle SHA256SUMS.cosign.bundle --certificate-identity https://github.com/WireWatch/wirewatch/.github/workflows/agent-release.yml@refs/tags/agent-v0.1.3 --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS &&sha256sum --ignore-missing -c SHA256SUMS &&tar -xzf agent_0.1.3_linux_$ARCH.tar.gz &&sudo install -m 0755 agent /usr/local/bin/wirewatch-agent &&sudo timeout 90 sh -c 'f="/var/lib/wirewatch/agent.key /var/lib/wirewatch/agent.crt /var/lib/wirewatch/agent.json"; /usr/local/bin/wirewatch-agent --token=<your-token> --server=<your-server-url> --config-dir=/var/lib/wirewatch & p=$!; while ! ls $f >/dev/null 2>&1 && kill -0 $p 2>/dev/null; do sleep 1; done; kill $p 2>/dev/null; wait $p 2>/dev/null; ls $f >/dev/null 2>&1' &&sudo tee /etc/systemd/system/wirewatch-agent.service >/dev/null <<'EOF' &&[Unit]Description=Wirewatch agentAfter=network-online.targetWants=network-online.target
[Service]ExecStart=/usr/local/bin/wirewatch-agent --config-dir=/var/lib/wirewatchRestart=alwaysRestartSec=5
[Install]WantedBy=multi-user.targetEOFsudo systemctl enable --now wirewatch-agentThe archive holds a single bare agent — no nested directory. ./agent --version prints 0.1.3.
cosign is a prerequisite, and the block enforces it rather than asking
Section titled “cosign is a prerequisite, and the block enforces it rather than asking”Every step is &&-chained, and that is the load-bearing part. On a host with no cosign the third
line exits non-zero and nothing after it runs: no binary is installed, no unit is written, and —
the one that cannot be undone — your single-use enrolment token is not spent, so the same token
still works once you have installed cosign. The same holds for a signature that does not verify, a
checksum that does not match, or an enrolment the control plane refuses.
Install cosign from its own release page first. Why the signature runs before the checksum it signs is in Verify a release.
The --certificate-identity names this release’s tag and no other — the enrolment screen
renders it for whichever version it is offering you.
Two lines of that unit are the whole point of this route
Section titled “Two lines of that unit are the whole point of this route”WantedBy=multi-user.target is what systemctl enable acts on, so the agent starts again after a
reboot with nobody logged in; Restart=always brings it back from a crash, an OOM kill or a control
plane that was unreachable at boot.
Without them the agent runs until the machine does not, and the first power cut ends your monitoring
silently — the app will show NO DATA and open no incident, which is correct and no help if nobody
is looking. Confirm both with systemctl is-enabled wirewatch-agent (enabled) and by rebooting
the host once before you rely on it.
Enrolment and execution are separate steps, and that keeps the token out of the unit file
Section titled “Enrolment and execution are separate steps, and that keeps the token out of the unit file”The timeout 90 sh -c … line runs the agent once in the foreground with the token: it enrols and
the line ends itself. The unit installed on the next line carries no --token at all — it
starts from the credential already on disk. So the single-use token never reaches
/etc/systemd/system, and a restart never needs it again.
What ends that line is the whole credential being on disk — the private key, the leaf and the metadata, which is every file the next start needs to resume rather than re-enrol. Waiting on any one of them would make the line depend on the order the agent happens to write them in, and killing the process between two of those writes spends the single-use token on a credential that is not there. It is bounded a second time by the agent itself: if the token is rejected or expired the process exits, the wait notices, and the line ends immediately with the agent’s own error rather than 90 seconds later.
That line’s exit status is “the credential is complete” — it ends by re-testing the same three
files, not by reporting how the process died. A refused token therefore stops the chain and no unit
is installed for a service that could never start; and if the agent is killed outright after writing
a complete credential, the install still proceeds instead of stranding a spent token. The 90 is a
backstop above the agent’s own 60-second HTTP timeout, never the thing that normally ends the wait.
Where the credential lands
Section titled “Where the credential lands”--config-dir=/var/lib/wirewatch appears in the enrolment line and in the unit’s ExecStart, and
they must name the same directory: enrolling into one and starting from another spends the
single-use token and leaves the service with nothing to resume from. The directory is created 0700
with agent.key at 0600, owned by root, since both steps run under sudo.
With no --config-dir at all the agent resolves os.UserConfigDir() and persists under
~/.config/wirewatch-agent — which a unit running as another user cannot read, and which does not
exist at all when HOME is unset (cannot determine the user config dir; pass --config-dir). That
is why the flag is explicit on both lines rather than left to the default.