Install a runner
Every method needs two things: the server URL and a registration token from a runner pool (slipway runner token <pool>, or Settings, Runners in the UI). Treat the token like a credential. See Pools and labels.
After first contact the runner stores its own id and credential in a state file (--state-file), so the registration token is only needed once and rotation of the pool token does not disconnect existing runners.
Linux packages (deb, rpm, apk)
Section titled “Linux packages (deb, rpm, apk)”The packages install /usr/bin/slipway, a systemd unit and an environment file.
sudo apt install ./slipway_<version>_amd64.deb # or rpm -i / apk add --allow-untrustedsudoedit /etc/slipway/runner.envSLIPWAY_RUNNER_SERVER=https://slipway.example.comSLIPWAY_RUNNER_TOKEN=<registration token>SLIPWAY_RUNNER_EXECUTOR=shellSLIPWAY_RUNNER_LABELS=linux,x64SLIPWAY_RUNNER_CONCURRENCY=2sudo systemctl enable --now slipway-runnerjournalctl -u slipway-runner -fThe unit runs as the unprivileged slipway-runner user with NoNewPrivileges, ProtectSystem=strict, ProtectHome and PrivateTmp, and gives running jobs up to an hour to finish on stop (TimeoutStopSec=3600). To use the docker executor add the user to the docker group (SupplementaryGroups=docker in a drop-in).
Container image
Section titled “Container image”The runner image contains the binary plus git, the docker CLI with buildx and compose, kubectl, helm, kustomize, yq and jq, and runs as a non-root user.
docker run -d --restart unless-stopped --name slipway-runner \ -e SLIPWAY_RUNNER_SERVER=https://slipway.example.com \ -e SLIPWAY_RUNNER_TOKEN \ -e SLIPWAY_RUNNER_EXECUTOR=docker \ -e SLIPWAY_RUNNER_LABELS=linux,docker \ -v /var/run/docker.sock:/var/run/docker.sock \ ghcr.io/slipway-systems/slipway-runner:latest runnerMounting the Docker socket gives the runner (and every job) control of the host’s Docker daemon. Prefer rootless Podman, a dedicated VM or the Kubernetes executor. See the security model.
The docker executor
Section titled “The docker executor”Works with Docker and Podman (any Docker-compatible API).
slipway runner --executor docker \ --docker-host unix:///run/user/1000/podman/podman.sock \ --server https://slipway.example.com --token-file /etc/slipway/tokenOptions (YAML docker: block): default_image (used when a job has no container, default ubuntu:24.04), pull_policy (always, missing, never), allow_privileged, allowed_volumes (host path prefixes jobs may bind-mount), registries (pull credentials), selinux_label (appends :z, needed on Fedora and RHEL; default on) and network.
The shell executor
Section titled “The shell executor”Runs steps directly on the host in a per-job workspace under --workdir. Steps inherit the runner’s environment unless shell.inherit_env: false. Use it where containers are impractical (macOS, hardware access) and run it on disposable or dedicated machines.
The kubernetes executor
Section titled “The kubernetes executor”Creates a pod per job in a namespace. Run the runner inside the cluster (recommended, uses its service account) or point it at a cluster with --kubeconfig.
slipway runner --executor kubernetes --k8s-namespace slipway-jobs \ --server https://slipway.example.com --token-file /etc/slipway/tokenSee Runners on Kubernetes for the Helm values and RBAC.
Verify and troubleshoot
Section titled “Verify and troubleshoot”slipway runner check # validates configuration, the executor and the path to the server, then exitsslipway runner versionslipway runner list --status online| Symptom | Likely cause |
|---|---|
| Runner never appears | Wrong server URL, an egress proxy or firewall blocking outbound HTTPS, or a private CA (use --ca-file). Run slipway runner check --server <url> --executor shell from the runner host: it opens the control stream without registering and says whether a proxy on the way blocks it |
| Runner registers, then no jobs arrive | A proxy between runner and server (Cloudflare, an HTTP/1.1 load balancer) buffers the bidirectional stream. The default --transport auto uses a WebSocket, which such proxies pass end to end; make sure the proxy allows WebSocket upgrades on /api/v1/runner/connect |
unauthorized at start |
Expired or rotated registration token; create a new one |
Jobs stay queued |
No online runner in the pool matches the job’s runs_on labels |
| Docker steps fail to start | Socket permissions, wrong --docker-host, SELinux (selinux_label) |
Upgrades
Section titled “Upgrades”The runner can check for updates (self_update.check, channel stable, every 6 hours by default). On shutdown (SIGTERM) it stops accepting jobs and waits up to --drain-timeout (default 10 minutes) for running jobs. A runner is compatible with a control plane one minor version older or newer.