Semaphore: A Self-Hosted Web UI for Ansible Automation
If you run Ansible playbooks regularly, you know the drill: SSH into a control node, navigate to the right directory, remember the right flags, run the playbook, and hope the terminal doesn't close before it finishes. For ad-hoc tasks this is fine. For a team, or for anything you want to schedule and audit, it gets old fast.
Semaphore is a self-hosted web UI for Ansible that solves exactly this. It wraps your playbooks in a clean interface where you can manage inventories, store credentials, schedule jobs, and browse run history — without exposing raw SSH access to everyone who needs to trigger a deployment.
What Semaphore Does
At its core, Semaphore is a job runner for Ansible. You define:
- Projects — a logical grouping (e.g., "production servers" or "homelab")
- Repositories — where your playbooks live (Git repo URL or local path)
- Inventories — the hosts to target, stored in Semaphore rather than flat files
- Environment — variables injected at runtime (without hardcoding secrets)
- Task templates — a playbook + inventory + environment combination, ready to run
Once a task template exists, anyone with access can trigger a run from the browser, see real-time output, and come back later to review what happened. That audit trail alone is worth the setup for a team.
Why Not Just Use AWX?
AWX is the open-source upstream of Red Hat Ansible Automation Platform. It is powerful, feature-complete, and designed for enterprise scale. It also requires Kubernetes to run in its current form, consumes gigabytes of RAM, and takes real effort to maintain.
Semaphore targets a different audience: homelab operators and small teams who want Ansible automation without running a cluster. The binary is under 50 MB. The Docker image is tiny. A machine with 512 MB of RAM can run it comfortably.
If you have 300 servers and a dedicated ops team, AWX makes sense. If you have a homelab or a small VPS fleet, Semaphore is a much better fit.
Installation with Docker
The quickest path is Docker Compose. Create a docker-compose.yml:
services:
semaphore:
image: semaphoreui/semaphore:latest
ports:
- "3000:3000"
environment:
SEMAPHORE_DB_DIALECT: bolt
SEMAPHORE_ADMIN: admin
SEMAPHORE_ADMIN_PASSWORD: changeme
SEMAPHORE_ADMIN_NAME: Admin
SEMAPHORE_ADMIN_EMAIL: [email protected]
volumes:
- semaphore-data:/home/semaphore
restart: unless-stopped
volumes:
semaphore-data:
This uses BoltDB (an embedded key-value store) so you don't need a separate database container. For production or multi-user setups, switch to PostgreSQL or MySQL — Semaphore supports both.
Start it:
docker compose up -d
Navigate to http://your-server:3000, log in with the admin credentials, and you're in.
Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.
Connecting Your Playbooks
Semaphore pulls playbooks from Git. In the UI:
- Go to Key Store and add an SSH key or personal access token for your Git repo
- Go to Repositories and add your repo URL with the key you just stored
- Semaphore will clone the repo on first use
For inventories, you can paste a standard Ansible inventory file directly into the UI, or point to a file inside your repo. Both work fine.
Storing Secrets Safely
Hardcoded passwords in playbooks are a bad idea, but so is leaving them in plaintext environment files. Semaphore has a Key Store specifically for secrets. You can store:
- SSH private keys (for connecting to managed hosts)
- Login credentials (username/password pairs)
- Environment variable sets (JSON key-value pairs injected at runtime)
When a task template runs, Semaphore injects the environment variables and makes SSH keys available to Ansible — without ever writing them to disk in a readable location.
Scheduling Runs
Semaphore includes a built-in scheduler. Once you have a task template, you can set a cron expression on it:
0 2 * * * # Run daily at 2 AM
This is useful for maintenance playbooks: rotating logs, running apt upgrade, checking certificate expiry, updating DNS records. You set it once and forget about it until something fails — at which point the run history shows you exactly what happened.
RBAC and Teams
Semaphore supports multiple users with role-based access control. Roles:
- Admin — full access, can manage users and settings
- Manager — can create and edit task templates, run jobs
- Task runner — can trigger existing templates but not modify them
- Guest — read-only, can view run history and output
This makes it practical for a small team: developers can trigger deployments without having SSH keys to production, and the run history shows who ran what and when.
Monitoring Run Output
One of the most useful things Semaphore gets right: live streaming of playbook output. When a job is running, you can open the run in your browser and watch the output scroll in real time — exactly like watching ansible-playbook in a terminal, but from anywhere.
Failed runs stay in the history with their full output. No more losing context because you closed a terminal window.
Integrating with Other Tools
Semaphore exposes a REST API. Every action you can do in the UI has an API endpoint — trigger a job, fetch run status, manage inventories. This means you can:
- Trigger a deployment from a CI/CD pipeline (GitLab CI, GitHub Actions, Woodpecker)
- Integrate with monitoring tools to auto-remediate known issues
- Build a simple approval workflow around the API
The API is documented at /api/docs on your running instance.
Who Should Use Semaphore
Semaphore is a good fit if you:
- Already use Ansible and want to move beyond ad-hoc CLI use
- Have playbooks other people need to run but shouldn't need SSH for
- Want scheduled Ansible jobs without gluing together cron + shell scripts
- Need an audit trail of what ran, when, and what the output was
It is not a replacement for AWX if you need enterprise features like organizations, workflow templates, or large-scale RBAC. But for most homelab and small-team use cases, Semaphore covers the ground you actually need at a fraction of the operational overhead.
Getting Started
The official documentation covers installation on bare metal, Docker, and Kubernetes. The project is actively maintained and the GitHub issue tracker is responsive.
If you're already running Ansible playbooks manually, Semaphore is one of those tools that's worth an afternoon to set up. The combination of a clean UI, secret management, scheduling, and run history tends to pay back that time quickly.
