Skip to content
The Kaio dashboard: a Compose stack deployed from the browser, a stack expanded over its containers, a metric chart read point by point, the stack menu open on its actions, the event log underneath, then the Manage menu opening the cluster nodes.

Everything on your Docker hosts, from a browser and a terminal

One container. A web dashboard, a keyboard-driven TUI and a scriptable CLI, all clients of the same core. No agent on your hosts, no orchestrator, no database server, no SaaS account. Deploy a Compose stack, undo a bad one, follow the logs, drop into a shell, see which images carry CVEs, and do it across every server that joined the cluster. Or hand the same server to an AI agent over MCP, on the same port.

The dashboard above is one client. This is another, on the machine itself, with no browser and no port to forward: kaio-cli tui. Same stacks, same versions, same CVE counts, computed once by the same server. Create a stack, write its compose.yml in your own $EDITOR, add a variable and deploy, all under Tab and a handful of keys.

The Kaio TUI walked through with Tab: the Stacks tree, a folded container group, the images, volumes, networks and events tables, then a new stack named in the [n] dialog, its compose.yml written in $EDITOR, a variable added and the stack deployed.
Every tab under [Tab], then a stack created end to end: name it, write its compose.yml in $EDITOR, add a variable, deploy.

Nothing to install on your hosts

No agent, no daemon of ours, no sidecar. Run Kaio on a host and it already manages it; run it on a second and let them join: kaio-cli join enrols a machine with no address typed by hand, and cluster leave takes it back out from the machine itself. A server that changes address is recognised, not duplicated. The API a node already serves is the protocol, so there is no second thing to keep upgraded, and nothing new listening on your servers.

Three interfaces, one truth

Click it in the browser, drive it from the TUI over SSH, script it in CI with --json. All three are clients of the same server, which computes every number once, so nothing can disagree with anything else. There is no second implementation to drift.

Move a stack, data and all

Copy a stack to another server with its variables, its whole version history and the contents of its volumes, streamed through the control plane so the two hosts never need to reach each other. The source is never stopped, written to or removed, and a copy that fails undoes itself. A copy that could never start, because a port is taken, is refused rather than written.

A pipeline is a first-class client

The CLI is a thin HTTP client: no checkout of Kaio, no toolchain, no Docker socket in the runner. Three lines are a deploy that verifies itself: health refuses a server that is down before anything is written, stack deploy blog compose.yml --env-file .env.ci writes it, and a --json status check reads the containers back. A 0 from the deploy only means it was accepted, so that last step is what fails the build when they did not stay up. A failed compose up has already restored the previous version by then, so a bad commit leaves the last working stack running.

Every command speaks JSON

--json turns the CLI into a data source, so a pipeline gates on what the server already knows rather than on scraped output: jq -e over status when the containers did not stay up, over image ls when a scan found a critical CVE, over node ls when a server stopped answering. The same node ls rolls one deploy across every server that answered.

A protocol for your agent, not a chat box

Kaio speaks the Model Context Protocol at /mcp, on the same port as everything else. Point an agent at it and “why is the media stack partial” is answered from the same numbers the dashboard shows, not from scraped output. The endpoint is off by default, and KAIO_MCP is a ladder: read where no tool can change a thing, write for deploys and copies, admin for what has no undo. An agent only sees the tools its rung allows.

Graph it in Grafana, if you want to

An option, not a dependency: Kaio draws its own charts and keeps a day of them. Turn on KAIO_METRICS and it also speaks Prometheus at /metrics, on the same port as everything else, so Grafana keeps the history Kaio deliberately does not. A scrape costs no call to the Docker daemon, your fleet names itself because one Kaio hands Prometheus the rest of the cluster, and make metrics-full-run stands the whole thing up, Kaio included, with the dashboard already loaded.

Alerted on what only Kaio knows

A dashboard helps while you are looking at it. The reason to scrape Kaio is not another CPU graph, it is Alertmanager waking you over state nothing else on the host can see: a stack partial for ten minutes, an image update waiting a week, a critical CVE that appeared overnight on an image you built in March, variables saved and never applied, a server that stopped answering its peers. Nine rules ship written. One of them watches Kaio itself, and fires when it stops reading the daemon while still happily serving pages.

Nothing is held back

No paid tier, no seat count, no node limit, no feature waiting behind a sales call. CVE scanning, the cluster, the gateway, the MCP endpoint: what you read on this page is what one container gives you, on the first host and on the twentieth.

Your files stay your files

A stack is a directory on the host: compose.yml next to its .env, where plain docker compose still works on them. Nothing is locked inside a database, so removing Kaio leaves your stacks running. SQLite keeps the history, and data/ is the one thing worth backing up.

Today's CVE, on last year's image

Trivy runs as a throwaway container, so there is nothing to install. In-use images are rescanned on a schedule you choose, starting at boot. A vulnerability disclosed this morning surfaces on an image you built months ago, without anyone running a command.

Change a variable without holding your breath

A stack’s variables live in a .env at mode 0600 next to its compose file. Names that look like one (*_PASSWORD, *_TOKEN, *_KEY) are flagged secret on their own: reading them back gives null, and leaving one empty keeps the stored value, so you never retype a password to change a tag. From the CLI or the TUI an edit is saved as pending until you apply it, so you pick the moment containers restart. And a failed compose up puts back the previous compose.yml and the previous .env together: a bad variable is an undo, not an outage.

Undo, not regret

Every deploy is a numbered version: the compose file and its variables, captured together. Roll back and both come back as a pair. A failed compose up restores the previous one on its own, so editing a live stack is an undo away, not a gamble.

One fleet, one dashboard

From your entry point, list every server that answered, in the web UI under Manage → Nodes, in the TUI’s Nodes tab, or with kaio-cli node ls. Then drive any of them by name: kaio-cli node web-01 run stack deploy api ./compose.yml. Removing a node closes that path, while its own address stays exactly as reachable as before.

Catches a moving latest tag

The checker asks the registry for the manifest digest and compares it with what you are actually running, so a rebuilt latest is caught where a version string would lie. Nothing is pulled, and nothing is recreated, until you say so.

From a spike to a shell

Live CPU, memory and network per container, summed per stack. When a number looks wrong, stream the whole stack’s logs merged by service, then open an interactive shell inside the container, without leaving the page.

Kaio does not build images from a git repository, run a reverse proxy, issue certificates, turn a database into a managed resource of its own, or decide which host a workload lands on. A PaaS owns all of that, and owning it means choosing it for you: its builder, its proxy, its certificate flow, its database images and the way they are backed up.

Kaio leaves each of those open. Build in the CI you already run and deploy the tag it pushed. Front it with nginx, Caddy, Traefik or none of them. Run Postgres, MariaDB or Redis as a stack like any other, on their own images and your own volumes, or keep pointing at the server you already have. Because a stack stays an ordinary Compose project on disk, the tools you already use keep working on it, and the ones you pick next will too.

Kaio has no authentication: whatever reaches its port controls the Docker daemon, which is root-equivalent on that host. A permissive CORS policy means your own browser is part of that reach. So it is built to sit behind whatever you already trust: a reverse proxy with basic auth, an SSO gateway, a VPN or a mesh network, or nothing at all on a host only you can reach. It expects to be the thing behind the door, not the door.

Bind it to 127.0.0.1, put your own layer in front, and read Security for what that layer needs to cover.

Kaio, built by Régis Gaidot