zyris-dockerContainer node

When a server goes down, an agent is the first to know

zyris-docker is a Zyris node that runs inside a container and connects it — and the Docker and Kubernetes infrastructure around it — to Attacca. It reads state, edits files and runs commands, and when something it watches goes down, it opens an agent session to diagnose and fix it.

Built for a containerised host rather than a machine with a display. To connect a desktop computer, use the Zyris desktop app.

docker-compose.yml
services:
  zyris-docker:
    image: ghcr.io/attacca-cc/zyris-docker:latest
    restart: on-failure:3
    environment:
      - ZYRIS_NODE_TOKEN_FILE=/run/secrets/zyris_token
      - ZYRISD_WATCH_CONTAINERS=web,db
      - ZYRISD_WATCH_PROCESSES=nginx
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./secrets/zyris_token:/run/secrets/zyris_token:ro
      - ./data:/data

What it does

Monitoring

System snapshots, the process list, Docker container state and logs, and Kubernetes pod and node state — all through the monitor capability.

A self-healing loop

It samples the processes, containers and cluster you name, and when one is down it opens an agent session with the incident. It never blindly restarts things; the agent makes the call.

Fenced to its roots

File access and command execution stay inside the roots you configure, and every exec has a timeout and an output cap.

Tokens from a Secret

Mount a Kubernetes Secret or a docker secret through ZYRIS_NODE_TOKEN_FILE. It is re-read on every reconnect, so rotating the Secret needs no restart.

Docker and Kubernetes

Mount docker.sock to see Docker; give it a kubeconfig or an in-cluster service account to see Kubernetes.

Exit codes that mean something

Exit code 2 means a person has to act. Wire it into your restart policy so a node that needs a human does not loop forever, printing enrolment codes into a log nobody reads.

Deploy

Enrol once to get a znt_ node token, then mount it into the container as a file. Started without one, the node prints an eight-character enrolment code into the container log — in that case give ZYRIS_CONFIG_DIR a named volume, or every restart enrols again.

Docker
docker run --rm \
  -e ZYRIS_NODE_TOKEN_FILE=/run/secrets/zyris_token \
  -e ZYRISD_WATCH_CONTAINERS=web,db \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v "$PWD/secrets/zyris_token:/run/secrets/zyris_token:ro" \
  ghcr.io/attacca-cc/zyris-docker:latest

Kubernetes

Set ZYRISD_WATCH_K8S=1 and mount a kubeconfig, or rely on an in-cluster service account. Mount the token from a Secret and point ZYRIS_NODE_TOKEN_FILE at it — and since a pod's hostname changes when it is recreated, give ZYRIS_NODE_NAME a stable value.

deployment.yaml
env:
  - name: ZYRIS_NODE_NAME
    value: prod-cluster
  - name: ZYRIS_NODE_TOKEN_FILE
    value: /run/secrets/zyris_token
  - name: ZYRISD_WATCH_K8S
    value: "1"

Binary and source

Or take the filev0.1.1
Verify with SHA256SUMS
$git clone https://github.com/attacca-cc/zyris-docker.git
$cd zyris-docker && cargo build --release

Recovery stays with an agent that has judgement

zyris-docker does not restart a stopped service on its own. An agent uses this node's monitor and exec tools to find out why, does what is needed, and reports back. The image runs as the unprivileged zyris user, and files and commands stay inside the roots you set.