Skip to content
Deploying / Runners

Runners

The machine Kamal runs on, and what preparing it installs.

A runner is the machine that runs kamal. KamalCloud reaches it over SSH with the account’s control key and runs the pinned official Kamal image against its Docker daemon – the Kamal Handbook’s way of running Kamal without installing Ruby.

A runner is not where your app runs. It is where deploys happen from.

Adding one

The account’s SSH keys have to exist first; until they do, the Runners page asks you to generate them and will not add one.

Runners → Add runner. A dialog asks for a name and a host: either one of your servers, or any machine you can reach over SSH, with its port. The SSH user must be root, because preparing installs packages and Docker.

Preparation starts as soon as the runner is added. It runs, in order:

  1. git and curl, by whichever package manager the machine has
  2. Docker, via Docker’s own script, started if the distribution installs it stopped
  3. tonistiigi/binfmt, so the runner can build images for another CPU architecture
  4. The account’s deploy key, which is what Kamal will use to reach your servers
  5. An SSH config that points git and Kamal at that key
  6. The Kamal image itself, pulled so the first deploy does not wait for it

The output streams as it goes. When it finishes the runner is ready and records the Kamal version it has. Prepare on the runner’s page runs it again.

One runner, many apps

One runner can deploy every app in the account. Each app gets its own working directory on it, holding a shallow checkout of the repository and the destination files KamalCloud writes.

Reasons to have more than one:

  • Architecture. Kamal builds the image on the runner. A runner whose CPU matches your servers builds one architecture; a mismatch means a slower multi-arch build.
  • Separation. A runner per environment keeps a staging build off the machine that ships production.
  • Location. A runner near your servers pushes images over a shorter wire.

Disk

A runner accumulates: checkouts, built images, layer caches. Its page shows disk usage. Clean up prunes what Docker has left behind – build cache older than a week, dangling images, stopped containers older than a day. When nothing is deploying it also removes the kamal-docker-registry container, since Kamal’s local registry never frees space and Kamal recreates it on the next build. Then it runs kamal prune all for each environment that has been deployed from the runner.

The same cleanup runs on every ready runner nightly at 4am.

Where a runner should live

Anywhere KamalCloud can reach and that can reach your servers. A small dedicated machine is the tidy answer, because builds want CPU and disk and you would rather they did not compete with anything serving traffic. A machine that is also a deploy target works; it just has to have room.

If a runner is gone

Deploys for its apps fail to start, and the environment page says the runner is the reason. Point the app at another prepared runner and deploy again – nothing about the app or its servers depends on which runner did the last one.

The Kamal version

The image is pinned, so every deploy in the account uses one known Kamal. Preparing a runner again pulls whatever the current pin is.