Skip to content
Kaiov0.6.1

Other ways to install

Both give the same product as the systemd install, which is the one to prefer: one command, and Kaio is supervised like any other service. Reach for the image when you want a look without installing anything on the host, and for the tarball when the host cannot fetch a script from the network, or when you would rather read the installer before it runs.

Nothing to install on the host but Docker itself: the image carries the server with its dashboard compiled in, the Docker CLI with its Compose plugin, and Skopeo.

Terminal window
docker network create --subnet 172.31.80.0/24 kaio
docker run -d --name kaio --network kaio \
-p 127.0.0.1:8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./data:/app/data \
-e KAIO_ADDR=0.0.0.0:8080 \
-e KAIO_ALLOWED_NETWORKS=172.31.80.0/24 \
-e KAIO_DB=sqlite:/app/data/kaio.db \
ghcr.io/rgaidot/kaio:latest

That is enough to try it, at http://127.0.0.1:8080. The network is Kaio’s alone, and a connection through the published port reaches the container from it, which is why it is the network Kaio accepts; without KAIO_ALLOWED_NETWORKS, the container refuses to start on 0.0.0.0. For a setup that survives a reboot, with the same options in a file you keep, use Deploy with Compose.

Nothing here turns on the MCP endpoint, because it stays off until you ask for it. An agent reaching a container needs two more variables, one to pick the rung and one to name the Host it answers:

Terminal window
-e KAIO_MCP=read \
-e KAIO_MCP_ALLOWED_HOSTS=kaio.example.net \

Prometheus metrics work the same way: off until you ask, then two variables, one to serve /metrics and one to put a token in front of an endpoint that names every stack and image you run.

Terminal window
-e KAIO_METRICS=on \
-e KAIO_METRICS_TOKEN=a-long-random-string \

Neither is needed to run Kaio, and nothing watches you from outside until you turn one on.

To stand up the whole thing rather than try it, this compose.yml is complete: Kaio with its metrics on, a Prometheus scraping it, an Alertmanager and a Grafana. Save it, docker compose up -d, and Grafana answers on :3000 with admin / admin.

services:
kaio:
image: ghcr.io/rgaidot/kaio:latest
container_name: kaio
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
- KAIO_ADDR=0.0.0.0:8080
- KAIO_ALLOWED_NETWORKS=172.31.80.0/24
- KAIO_DB=sqlite:/app/data/kaio.db
- KAIO_METRICS=on
# Prometheus carries this same value below. Change one, change the other.
- KAIO_METRICS_TOKEN=kaio-scrape-token
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- kaio:/app/data
networks:
- kaio
- monitoring
prometheus:
image: docker.io/prom/prometheus:v3.15.0
container_name: kaio-prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=90d
networks:
- monitoring
depends_on:
- kaio
alertmanager:
image: docker.io/prom/alertmanager:v0.34.1
container_name: kaio-alertmanager
restart: unless-stopped
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
networks:
- monitoring
grafana:
image: docker.io/grafana/grafana:13.2.3
container_name: kaio-grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana:/var/lib/grafana
networks:
- monitoring
depends_on:
- prometheus
networks:
kaio:
ipam:
config:
- subnet: 172.31.80.0/24
monitoring:
volumes:
kaio:
prometheus:
grafana:

Kaio sits on two networks. kaio, which it has to itself, is the one the published port reaches it through and the one KAIO_ALLOWED_NETWORKS names. monitoring is shared with Prometheus, and Kaio accepts nothing from it but the routes that carry their own proof: /metrics with its token is one, the API is not.

It needs two small files beside it. prometheus.yml:

global:
scrape_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: [alertmanager:9093]
scrape_configs:
- job_name: kaio
metrics_path: /metrics
authorization:
credentials: kaio-scrape-token
static_configs:
- targets: [kaio:8080]

And alertmanager.yml, which groups alerts and sends them nowhere until you give it a receiver:

route:
receiver: none
receivers:
- name: none

Grafana starts empty here: add Prometheus at http://prometheus:9090 as a data source, then import the dashboard from packaging/grafana/dashboard.json. The repository carries the same stack with the dashboard, the data source and nine alert rules already provisioned, which is one command instead of this file: see Prometheus and Grafana.

Every tag publishes one archive per architecture, built by CI, holding the two binaries and the systemd files:

Terminal window
VERSION=0.6.1
ARCH=amd64 # or arm64
curl -fsSLO https://github.com/rgaidot/kaio/releases/download/v${VERSION}/kaio-${VERSION}-linux-${ARCH}.tar.gz
curl -fsSLO https://github.com/rgaidot/kaio/releases/download/v${VERSION}/kaio-${VERSION}-linux-${ARCH}.tar.gz.sha256
sha256sum -c kaio-${VERSION}-linux-${ARCH}.tar.gz.sha256
tar -xzf kaio-${VERSION}-linux-${ARCH}.tar.gz
cd kaio-${VERSION}-linux-${ARCH}
sudo ./install.sh
sudo systemctl enable --now kaio
kaio-<version>-linux-<arch>/
├── kaio-server
├── kaio-cli
├── kaio.service the systemd unit
├── kaio.env.example the configuration file
├── monitoring/ the Prometheus, Alertmanager and Grafana stack,
│ installed only with --with-monitoring
└── install.sh

Building that same archive from a checkout is a make dist away, described in Build and release.

What install.sh writes, the unit it installs and the configuration it seeds are all in Installation, which describes the same installer reached the short way.

Kaio, built by Régis Gaidot