kogutdocs

Agent

The agent in Docker

Run the agent in Docker or Podman.

Get a host token from Hosts → Add a server first.

Start with Compose

  1. Save this file:
agent.compose.yml
services:
  kogut-agent:
    image: ghcr.io/piotrkowski/kogut-agent:0.1
    command: ["agent"]
    restart: unless-stopped
    network_mode: host
    pid: host
    group_add:
      - "${DOCKER_GID:?set DOCKER_GID to the group id of /var/run/docker.sock}"
    environment:
      - KOGUT_SERVER=https://kogut.acme.com
      - KOGUT_TOKEN=${KOGUT_TOKEN}
      - KOGUT_HOST_ROOT=/host
      - KOGUT_STATE_DIR=/data
    volumes:
      - agent-state:/data
      - /:/host:ro,rslave
      - /var/run/docker.sock:/var/run/docker.sock:ro

volumes:
  agent-state:
  1. Set your server URL above and put the token in a .env file beside the Compose file:
.env
KOGUT_TOKEN=<token from the panel>
  1. Start the agent with the socket’s group id:
DOCKER_GID=$(stat -c %g /var/run/docker.sock) docker compose -f agent.compose.yml up -d

The same file is in deploy/docker/agent.compose.yml.

  • Host networking gives network metrics, listening-port discovery, and Caddy access.
  • pid: host gives the host’s processes and mount table.
  • The host-root mount gives metrics, filesystems, temperatures, and nginx configuration; rslave includes later host mounts. Only the state volume is writable.

ghcr.io/piotrkowski/kogut-agent holds the agent-only build. The server image ghcr.io/piotrkowski/kogut runs the same agent with command: ["agent"].

The image runs as uid 65532, so socket access needs group_add. It has no systemctl or journalctl; for systemd states and logs, install on the host. When the agent cannot use the socket, see When the agent cannot read a source.

Run the agent inside the server container

On the host that runs kogut, KOGUT_LOCAL_AGENT=1 runs the agent inside the server, with no token or agent container. Give the server container what the agent service above has: network_mode: host, pid: host, KOGUT_HOST_ROOT=/host with the /:/host:ro,rslave mount, and the Docker socket with group_add and DOCKER_GID. Host networking replaces the ports: mapping: kogut listens on port 8484 of the host. Monitor the same host has the Compose file.

Container alerts

The agent reports each container’s state, health, restart count, exit code, image, and OOM kills. A container of a service raises an alert when it restarts in a loop, exits with an error, or stays unhealthy; see Containers. An OOM kill becomes the likely cause of the incident, and a new image is recorded as a deploy.

Exit codes, OOM kills, and image ids need an updated agent. Older agents report restarts and health only.

Use a socket proxy instead of the socket

The Docker socket grants control of the host even when mounted read-only (Permissions). A socket proxy limits the API the agent can use.

  1. Start the proxy on 127.0.0.1:2375 with container and image reads enabled (CONTAINERS=1, IMAGES=1) and writes disabled (POST=0). Without IMAGES=1, the rollback hint shows image ids, not digests.
  2. Remove group_add and the Docker socket mount from the agent’s Compose service.
  3. Add DOCKER_HOST=tcp://127.0.0.1:2375 to its environment and recreate the agent.

Do not expose the proxy beyond loopback.

Use Podman

For rootful Podman, mount /run/podman/podman.sock at /var/run/docker.sock and use its group id. For rootless Podman, run the agent as the socket’s owner and mount $XDG_RUNTIME_DIR/podman/podman.sock instead.

Rootless Podman reports container state, health, restarts, and exit codes, so container alerts work, but no CPU or memory: the agent reads those only from the Docker and rootful Podman cgroup v2 layouts. Socket selection and token files are in agent environment variables.