On this computer
fastestNeeds Docker Desktop. One click and about a minute, plus the image download the first time. The runner then reaches what this computer reaches.
ShellMate runs playbooks through a container, because Ansible needs Linux and a large dependency tree and the portable executable carries neither. You do not install it. ShellMate does, from one click.
In ShellMate, open Settings, choose Ansible, and under Set up a runner pick where it should live. ShellMate installs what is missing, starts the runner, makes the token and the certificate, and fills its own settings in. A progress list shows each step.
Needs Docker Desktop. One click and about a minute, plus the image download the first time. The runner then reaches what this computer reaches.
Pick a saved connection, or give an address and a login. ShellMate does the rest over SSH, including installing Docker if the host has none. A host on the management network reaches devices ShellMate itself may only see through a jump host.
For a host ShellMate cannot reach over SSH. Run this on it:
curl -fsSL https://shellmate.app/runner/install.sh | bash
Paste the last line it prints into ShellMate. Run it again any time; it keeps what it made.
On this computer: Docker Desktop. On a Linux host: nothing — ShellMate installs Docker Engine there if it is missing, which needs the login to be root or to have sudo.
Port 8081 free on the host, and reachable from the machine ShellMate runs on. The host needs a route to the devices; the runner reaches them over SSH from inside the container.
No registry account: the image is public. No source, no Python, no Ansible on the host. Everything is in the image, pinned, and upgraded by pulling a newer tag.
Every step, for the engineer who wants to see it or has to do it by hand. None of this is needed if the click worked.
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER && newgrp docker
sudo dnf -y install dnf-plugins-core sudo dnf config-manager --add-repo \ https://download.docker.com/linux/rhel/docker-ce.repo sudo dnf -y install docker-ce docker-ce-cli \ containerd.io docker-compose-plugin sudo systemctl enable --now docker
wsl --install -d Ubuntu # PowerShell, as administrator # then Docker Desktop, with its WSL2 backend on
mkdir shellmate-runner && cd shellmate-runner curl -O https://shellmate.app/download/runner-compose printf 'ANSIBLE_API_TOKEN=%s\n' "$(openssl rand -base64 32 | tr -d /=+ | cut -c1-43)" > .env docker compose up -d
The compose file pulls the public image and keeps the runner's data in a named volume. The printf line writes a random token into .env; the API refuses to start bound off-loopback without one, deliberately. Then:
docker compose ps # running (healthy) docker compose logs shellmate-runner | grep '^TLS:' # the certificate's fingerprint curl -sk https://localhost:8081/health
The certificate is self-signed, so ShellMate verifies the connection against your copy of it:
docker compose cp shellmate-runner:/runner/tls/api.crt ./api.crt # on the ShellMate machine, in PowerShell: scp you@runner-host:~/shellmate-runner/api.crt $HOME\.ansible\api.crt
The certificate covers localhost, the container name, and the host's own names and addresses. Reaching the runner on a name it does not cover fails verification even though the connection succeeded. Put any other name in API_TLS_SAN in .env before the first start, or delete /runner/tls/api.* in the volume, restart, and copy the new certificate.
| Runner address | https://localhost:8081, or the host's name or address on 8081. |
| Token | The value in the runner's .env. It goes into the vault. |
| CA certificate | Your copy of api.crt. |
| Verify TLS | Leave on. |
| Client certificate, key, Project directory | Leave empty. |
Test connection, then Save. In the Ansible view the light beside the runner pill goes green with Secure; click it and compare the fingerprint against the TLS: line in the runner's log.
docker compose logs says Refusing to start… no ANSIBLE_API_TOKEN. The .env is missing or not beside the compose file.
Almost always the name: you reached it on an address the certificate does not cover. See step 3. If the fingerprint ShellMate shows differs from the log's, stop and find out what is in between.
From the ShellMate machine: curl.exe -sk https://HOST:8081/health. If that fails it is the network or a firewall: sudo ufw allow from SHELLMATE-IP to any port 8081 proto tcp.
The runner reaches devices from the host's network. A runner in WSL2 reaches what the laptop reaches, and no more. Test from the host: docker compose exec shellmate-runner ssh -o BatchMode=yes admin@10.0.0.1.
ghcr.io/sjohnston1972/shellmate-runner:latest | the network collections, Meraki and AWS | about 830 MB |
ghcr.io/sjohnston1972/shellmate-runner:latest-cloud | the above plus the Azure SDK set | about 2.4 GB |
Take the first unless you drive Azure through Ansible. ShellMate builds cloud infrastructure with OpenTofu instead.
docker compose pull docker compose up -d
Playbooks, inventory and artifacts stay in the volume. Pin a version tag, :1.0.0, if an upgrade should be a decision rather than a side effect of a restart.
The image's own code is GPL-3.0. Every other licence in it is written into the image at build time:
docker run --rm ghcr.io/sjohnston1972/shellmate-runner cat /opt/THIRD_PARTY_NOTICES.md