Run your playbooks from a browser tab.
Playbook Runner is a self-hosted web UI for Ansible: inventory, SSH credentials, playbooks, schedules and a live log of every run, without the weight of AWX or Tower.
curl -fsSL https://raw.githubusercontent.com/Nonetss/playbook-runner/main/scripts/bootstrap.sh | bashWhat you get
Your inventory, with the right key attached.
Devices and groups live in the database. Each device points at an SSH credential, so picking a group is enough: the right user and key follow every host. Generate an ed25519 pair in the browser and copy a ready-made script that provisions the user on a new host.
Watch every task as it happens.
Pick a playbook and a group, confirm, run. PLAY and TASK lines stream into the browser as ansible-runner emits them, with no polling. Close the tab and the run is cancelled on the executor.
Or keep your playbooks in Git.
Add a repository over HTTPS or SSH, pick a branch and a subdirectory. Its playbooks show up read-only and run from a checkout of the synced commit, so roles, templates and group_vars next to them just work.
Schedule it, then check what happened.
Give a job a cron expression and the backend fires it on time. A job never overlaps with itself, and the history keeps the status, duration and hosts of every run.
Script it through the API.
Every endpoint is documented in an interactive OpenAPI reference served at /scalar. Create a personal API key and call it from scripts or CI.
And the rest of the toolbox
- Scripts
- Save Bash or Python scripts and run them on a selection of hosts, with the same live console.
- Ad-hoc commands
- Run the shell or command module against any selection, with optional become, for one-offs that don't deserve a playbook.
- Users and roles
- No public sign-up. Admins create accounts and assign admin, user or pending, which can sign in but waits for approval.
- Single sign-on
- Any OIDC provider (Keycloak, Authentik, Google…) next to email and password. Three variables turn it on.
- API keys
- Personal keys sent as x-api-key, for scripts and CI pipelines.
- Installable on mobile
- The interface is a PWA: add it to your phone's home screen and check a run from anywhere.
How it fits together
Four services and PostgreSQL, run with Docker Compose. Browsers only talk to the Caddy gateway, which sends the API to the backend and everything else to the frontend. The backend owns the database and reaches the Ansible executor over gRPC, through the gateway's internal router.
Request paths
- → HTTPS
- :80Caddy→ /*
- :4321Astro SSR
- → /rpc
- :80Caddy
- :3000Hono · oRPCPostgreSQL→ gRPC
- :50050Caddy→ /run.*
- :50051ansible-runner→ SSH
Gateway routing
| Request | Goes to |
|---|---|
| /rpc /api /scalar /openapi.json | backend:3000 |
| any other path | frontend:4321 |
| gRPC /run.* on :50050 | ansible:50051 |
| any other gRPC service | UNIMPLEMENTED |
- Private keys stay on the server.
- SSH keys are encrypted at rest with AES-256-GCM and never returned by the API. They are decrypted only to build a run, and the executor deletes the key files when it finishes.
- The executor has no database.
- The backend resolves the playbook, the hosts and their keys, then sends one complete payload over gRPC, authenticated with a shared service token. Output streams back on the same call.
- Runs are bounded.
- At most eight Ansible processes run at once by default; extra requests are refused instead of queued. SSH host keys are verified, trusting a host on first contact and rejecting changed keys.
Up in one command.
On a Linux host with Docker, curl and openssl, from an empty directory:
curl -fsSL https://raw.githubusercontent.com/Nonetss/playbook-runner/main/scripts/bootstrap.sh | bashPrefer to set it up by hand? Deploy with Docker Compose
What the script does
- Asks for the public URL, the port and the first admin, plus optional OIDC settings.
- Generates every secret with openssl, including the key that encrypts stored SSH keys.
- Writes .env and compose.yml in the current directory.
- Pulls the images from ghcr.io and starts the stack. The backend migrates the database and creates the admin on startup.