# Install the agent

Install and connect the agent on a Linux server.

The agent collects host metrics, containers, and systemd states. It needs no inbound
port. The full `kogut` binary runs it, and so does the smaller
[agent-only build](https://docs.kogut.dev/reference/cli/#the-agent-only-build).

## Get a host token

1. Set kogut's [public URL](https://docs.kogut.dev/reference/configuration/#server) to an HTTPS address.
2. Open **Hosts → Add a server**, name the host, and click **Create install command**.
3. Copy the command. The panel shows the token only once.

Each token reports only for its host. To replace a lost token, add the server again with
the same name; the old token stops working.

## Install the agent

**Linux**

Run the install command on x86_64 or arm64 Linux:

```sh
curl -fsSL https://kogut.dev/install | sudo sh -s -- agent --server https://kogut.acme.com --token <token>
```

The script downloads the agent-only build and checks its checksum, installs
`/usr/local/bin/kogut`, writes `/etc/kogut/agent.env` with mode `0600`, and starts
`kogut-agent.service`. Where `/usr/local/bin/kogut` already runs the server, it installs
the full binary instead. Options are in
[install-script settings](https://docs.kogut.dev/reference/environment-variables/#install-script).

**Docker**

Use the Compose file in [Docker](https://docs.kogut.dev/agent/docker/). It runs the `ghcr.io/piotrkowski/kogut-agent`
image, mounts the host read-only, and keeps unsent data in a volume. A containerised
agent does not report systemd units or their logs.

**NixOS**

Enable the NixOS module:

```nix
{
	services.kogut-agent = {
		enable = true;
		server = "https://kogut.acme.com";
		tokenFile = "/run/secrets/kogut-agent-token";
	};
}
```

The module passes the token as a systemd credential, outside the Nix store. See
[NixOS](https://docs.kogut.dev/installation/nixos/).

Metrics appear under **Hosts** within a minute. The host's **Discovered** list
[suggests checks for its services](https://docs.kogut.dev/agent/discovery/).

## Check the service

For a systemd installation:

```sh
systemctl status kogut-agent
journalctl -u kogut-agent -f
```

The service runs as a dynamic user with extra groups for container access and incident
logs. See [Permissions](https://docs.kogut.dev/agent/permissions/) before changing them.

### Collected data

The host page shows CPU, memory, swap, load, filesystems, disk and network throughput,
temperatures, and containers and systemd services with their states, CPU, and memory.
Container and service CPU and memory need cgroup v2, and services also systemd's CPU and
memory accounting; both are the default on current distributions. An agent in a container
reports no services. Containers of a service raise
[alerts of their own](https://docs.kogut.dev/alerts/how-alerts-work/#containers).

History older than raw metrics comes from five-minute and hourly rollups, which keep the
30 largest containers and services of each host. A container keeps its history across
restarts and recreation under the same name; a renamed one starts anew. While CPU,
memory, a disk, or swap is over its [alert limit](https://docs.kogut.dev/alerts/how-alerts-work/), the host
page says so at the top and, for CPU and memory, names the top containers and services.

Service states are checked with every sample. The agent sends the list when a state
changes and once a minute otherwise; a service's CPU is its average since the last list.
Each service's highest CPU and memory are shown as far back as raw metrics are kept
([`host_metrics`](https://docs.kogut.dev/reference/configuration/#retention), a day by default). Restart
counts are refreshed every 5 minutes.

The agent reports OS and hardware details at startup, discovers services hourly, and
sends logs only when the server requests them for an incident. See
[Agent data](https://docs.kogut.dev/agent/permissions/#agent-data).

## Configure the connection

The agent has no config file; the server supplies metric intervals and checks. To start
it by hand:

```sh
kogut agent --server https://kogut.acme.com --token <token>
```

See the [CLI reference](https://docs.kogut.dev/reference/cli/#kogut-agent) and
[agent environment variables](https://docs.kogut.dev/reference/environment-variables/#agent) for token files,
failover servers, state storage, and certificate pinning.

### Connection and buffering

The agent validates certificates against its bundled Mozilla root store. Plain HTTP is
accepted only for loopback and Tailscale addresses unless explicitly allowed.

Keep the agent's state directory writable and persistent. While the server is
unreachable, the agent buffers up to one hour or 20 MiB, then drops the oldest data, and
sends the buffer with the original timestamps when the connection returns.

Update agents after the server; see
[Agent compatibility](https://docs.kogut.dev/installation/upgrading/#agent-compatibility). An older agent
skips check types and options it does not know, runs its other checks, and logs
"update the agent" for each skipped check. Older agents also send HTTP checks without
newer request headers and report neither container exit codes nor OOM kills.

### Pin the server key

Set `KOGUT_SERVER_KEY` to the SHA-256 pin of the certificate's public key
(SubjectPublicKeyInfo). Print the pin from the live certificate:

```sh
echo | openssl s_client -connect kogut.acme.com:443 -servername kogut.acme.com 2>/dev/null \
	| openssl x509 -pubkey -noout \
	| openssl pkey -pubin -outform der \
	| sha256sum | awk '{print "sha256:" $1}'
```

Most certificate renewals change the key, and a pinned agent refuses the server until its
pin is updated. While switching keys, list the old and new pins separated by a comma.
Pinning is checked in addition to certificate validation.

## Remove the agent

Stop the service and remove its configuration:

```sh
sudo systemctl disable --now kogut-agent
sudo rm /etc/systemd/system/kogut-agent.service /etc/kogut/agent.env
sudo systemctl daemon-reload
```

The host's history stays until [retention](https://docs.kogut.dev/reference/configuration/#retention)
removes it. Removing the agent does not revoke its token; adding the host again with the
same name replaces it.
