Semaphore: Ansible UI When the Team Grows

Panel de control con switches e indicadores LED representando automatización de operaciones

Semaphore (or Semaphore UI) is the open-source web interface for running Ansible playbooks. Simple, lightweight, self-hostable. Born as a pragmatic alternative to AWX (upstream open-source of Ansible Tower / Red Hat Ansible Automation Platform) — fewer features, but dramatically simpler to operate. For mid-size teams that have outgrown “run from laptop” but don’t need AWX complexity, it’s the sensible choice.

What Semaphore Solves

Problems arising as teams grow:

  • Audit: who ran which playbook when against which hosts?
  • Permissions: which users can run which playbooks against which inventory?
  • History: what output did that execution a week ago produce?
  • Schedules: periodic playbooks without dedicating a cron host.
  • Centralised secrets: vault keys, SSH keys, without distributing across laptops.

Without a central UI, all this becomes ad-hoc and fragile.

Architecture

Minimum components:

  • Semaphore server (Go, single binary).
  • Database: MySQL/MariaDB, PostgreSQL, or embedded BoltDB.
  • Ansible available on the server or container.

No distributed workers or complex queues. For teams with <100 simultaneous runs, enough.

Docker Install

version: "3.8"
services:
  semaphore:
    image: semaphoreui/semaphore:latest
    ports:
      - "3000:3000"
    environment:
      SEMAPHORE_DB_DIALECT: postgres
      SEMAPHORE_DB_HOST: postgres
      SEMAPHORE_DB_USER: semaphore
      SEMAPHORE_DB_PASS: ${DB_PASS}
      SEMAPHORE_DB: semaphore
      SEMAPHORE_PLAYBOOK_PATH: /tmp/semaphore
      SEMAPHORE_ADMIN_PASSWORD: ${ADMIN_PASS}
      SEMAPHORE_ADMIN_NAME: admin
      SEMAPHORE_ADMIN_EMAIL: admin@example.com
    volumes:
      - semaphore_data:/etc/semaphore
      - semaphore_tmp:/tmp/semaphore
    depends_on:
      - postgres

  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: semaphore
      POSTGRES_PASSWORD: ${DB_PASS}
      POSTGRES_DB: semaphore
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  semaphore_data:
  semaphore_tmp:
  postgres_data:

Start and log into http://localhost:3000 as admin.

Key Concepts

Project: isolated space with its inventory, keys, templates.

Inventory: list of hosts. Can be static (direct list) or dynamic (script, AWS, etc).

Key Store: SSH keys, passwords, vault passwords. Used when running playbooks.

Repository: Git repo where your playbooks live. Semaphore pulls and executes.

Task Template: associates a playbook + inventory + keys. This is what runs.

Schedule: a template that runs on cron.

Typical Flow

  1. Your team has a Git repo with Ansible playbooks.
  2. Create project in Semaphore, pointing at the repo.
  3. Define inventory (production, staging, etc).
  4. Load SSH key with host access.
  5. Create templates: “deploy web service”, “rotate certs”, “restart postgres”.
  6. Team members run templates from UI, with live logs.

All with permissions: admin can everything, others only what you assign.

Permissions and RBAC

Semaphore has:

  • Global admin: manage users, settings.
  • Project owner: manage their project.
  • Manager: can run + edit templates.
  • Task runner: only run existing templates.
  • Guest: read-only.

For teams with clear dev/ops separation, this covers. For complex multi-tenancy, AWX has more granularity.

CI/CD Integration

Semaphore exposes REST API. Common patterns:

  • Gitea / GitHub Actions calls Semaphore API after PR merge.
  • Repo webhook to Semaphore for dynamic-inventory rebuild.
  • ChatOps: Slack bot running templates via API.
  • Monitoring: alerts trigger remediation templates.

Example curl:

curl -X POST https://semaphore.example.com/api/project/1/tasks \
  -H "Cookie: semaphore=..." \
  -d '{"template_id": 5, "debug": false}'

Semaphore vs AWX

Aspect Semaphore AWX
Deploy complexity Simple (Docker) Complex (Kubernetes recommended)
Database Simple PostgreSQL PostgreSQL + Redis
RBAC Basic-medium Advanced
Custom collections Yes Yes
Workflows Limited Advanced (graph)
Notifications Basic Advanced
Commercial support Yes (Red Hat)
Resource consumption Low (~500MB RAM) High (~4GB RAM)
Learning curve Low Medium-high

Semaphore for teams <50 with moderate needs. AWX for large teams with complex requirements.

Where It Falls Short

Honestly:

  • Complex multi-step workflows: AWX does better.
  • Enterprise SSO with complex SAML: Semaphore has basic OIDC.
  • Multi-organisation: Semaphore has “projects”, AWX has orgs.
  • Horizontal scaling: Semaphore runs on one node; AWX distributes.
  • Fine-grained metrics: AWX has more built-in observability.

Real Cases

Patterns we see:

  • 20-50 admin company: Semaphore as centralised runner.
  • MSP managing 100 clients: one project per client in Semaphore.
  • Platform engineering team: self-service for dev teams via pre-approved templates.
  • Compliance: audit log to show who did what when.

Security

Operational checklist:

  • Mandatory HTTPS via reverse proxy (Traefik, Nginx).
  • Integrated auth with OIDC or LDAP if available.
  • SSH keys with passphrase or Vault for secrets.
  • Regular backup of data volume + DB dump.
  • Monitor failed login attempts.
  • Update versions — read changelog.

HashiCorp Vault Integration

Semaphore can query Vault secrets at runtime:

- name: fetch secret
  set_fact:
    api_key: "{{ lookup('hashi_vault', 'secret=secret/data/api token=VAULT_TOKEN') }}"

With VAULT_TOKEN in Semaphore as env var. Secrets never on disk.

Conclusion

Semaphore is the pragmatic option for mid-size teams wanting an Ansible UI without AWX complexity. Its simplicity focus is its strength: install in minutes, operate painlessly, covers real cases. For large organisations with complex workflow requirements, enterprise SSO, and multi-tenancy, AWX remains the reference. Choice should be based on team size and needs sophistication. Often, simple is right.

Follow us on jacar.es for more on Ansible, automation, and practical DevOps.

Entradas relacionadas