Skip to content

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.

Terminal window
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 agent
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/wirewatch-agent --config-dir=/var/lib/wirewatch
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now wirewatch-agent

The 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.

--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.