← All articles
a close up of a piece of electronic equipment

Running Ansible Semaphore in Your Home Lab

Automation 2026-02-15 · 8 min read ansible semaphore automation configuration-management web-ui self-hosted
By HomeLab Starter Editorial TeamHome lab enthusiasts covering hardware setup, networking, and self-hosted services for home and small office environments.

If you've been using Ansible for home lab automation, you've probably run playbooks from the command line: ansible-playbook -i inventory.yml site.yml. This works fine when you're the only person managing infrastructure, but it's not ideal for:

Photo by Vishnu Mohanan on Unsplash

Ansible Semaphore solves all of this. It's a modern, self-hosted web UI for Ansible — lighter and easier to deploy than AWX/Ansible Tower, but still powerful enough for serious home lab automation.

Ansible Semaphore logo

What is Ansible Semaphore?

Semaphore is an open-source web interface for running Ansible playbooks. It provides:

It's not as feature-rich as AWX (Red Hat's Ansible Tower open-source version), but it's much simpler to deploy and maintain. For home labs, Semaphore is the sweet spot.

Semaphore vs AWX vs Ansible CLI

Feature Ansible CLI Semaphore AWX/Tower
Installation apt install ansible Docker Compose K8s operator or Docker (complex)
Learning curve Steep Moderate Very steep
Web UI No Yes Yes
Scheduling External (cron) Built-in Built-in
Multi-user No Yes (RBAC) Yes (advanced RBAC)
API No Yes Yes
Inventory management Files Web UI + files Web UI + dynamic inventory
Best for Solo sysadmin Small teams, homelabs Enterprises

When to use Semaphore: You want a web UI for Ansible, scheduled runs, and multi-user access without the complexity of AWX.

When to use AWX: You need advanced features like dynamic inventories, workflows, or integrate with Red Hat ecosystem.

Installation: Docker Compose

The easiest way to run Semaphore is via Docker Compose.

Prerequisites

Docker Compose Setup

Create a project directory:

mkdir -p ~/semaphore
cd ~/semaphore

Create docker-compose.yml:

version: '3'

services:
  semaphore:
    image: semaphoreui/semaphore:latest
    container_name: semaphore
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      SEMAPHORE_DB_DIALECT: bolt  # Use BoltDB (file-based, no separate DB needed)
      SEMAPHORE_ADMIN_PASSWORD: changeme  # Change this!
      SEMAPHORE_ADMIN_NAME: admin
      SEMAPHORE_ADMIN_EMAIL: [email protected]
      SEMAPHORE_ADMIN: admin
      SEMAPHORE_ACCESS_KEY_ENCRYPTION: "your-32-char-encryption-key-here"  # Generate a random key
    volumes:
      - ./semaphore:/etc/semaphore  # Config and database
      - ./playbooks:/playbooks      # Mount your Ansible playbooks
      - ./keys:/keys                # SSH keys for Ansible

Generate an encryption key:

openssl rand -hex 16

Replace SEMAPHORE_ACCESS_KEY_ENCRYPTION with the output.

Start Semaphore:

docker-compose up -d

Access Semaphore at http://your-server-ip:3000. Log in with:

Change the admin password immediately after first login (Settings → Users).

Reverse Proxy with Caddy (Optional)

If you want HTTPS and a proper domain:

# Caddyfile
semaphore.homelab.local {
    reverse_proxy localhost:3000
}

Or use Nginx, Traefik, or Cloudflare Tunnel.

Like what you're reading? Subscribe to HomeLab Starter — free weekly guides in your inbox.

Initial Configuration

Once logged in, you'll configure:

  1. Key Store: SSH keys for Ansible to connect to target hosts
  2. Repositories: Git repos or local directories with playbooks
  3. Inventory: Ansible inventory files
  4. Environment: Variables and Vault passwords
  5. Task Templates: Playbook configurations

1. Add an SSH Key

Go to Key StoreNew Key.

If you don't have a dedicated Ansible key:

ssh-keygen -t ed25519 -f ~/.ssh/ansible -C "ansible@semaphore"
ssh-copy-id -i ~/.ssh/ansible user@target-host

Upload the private key (~/.ssh/ansible) to Semaphore.

2. Add a Repository

This is where your Ansible playbooks live. You can use a Git repo or mount a local directory.

Option A: Git Repository

Go to RepositoriesNew Repository.

Option B: Local Directory

In docker-compose.yml, you already mounted /playbooks. Put your Ansible project there:

cp -r ~/homelab-ansible/* ~/semaphore/playbooks/

In Semaphore:

3. Add an Inventory

Go to InventoryNew Inventory.

Example (YAML):

all:
  children:
    servers:
      hosts:
        proxmox:
          ansible_host: 192.168.1.10
          ansible_user: root
        nas:
          ansible_host: 192.168.1.50
          ansible_user: admin
    pis:
      hosts:
        pi-vpn:
          ansible_host: 192.168.1.61
          ansible_user: pi

Or you can reference an inventory file from your repository.

4. Add an Environment (Optional)

If you use Ansible Vault or extra vars:

Go to EnvironmentNew Environment.

Example extra vars:

timezone: America/Los_Angeles
ntp_servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org

Creating a Task Template

Task Templates define how to run a playbook.

Go to Task TemplatesNew Template.

Example: Weekly System Updates

Survey variables (optional): If your playbook accepts variables (e.g., --extra-vars "reboot=yes"), you can define a form here. Users can check a box to enable reboots when running the template.

Running a Playbook

Once a task template is created:

  1. Go to Task Templates
  2. Click the Run button next to your template
  3. Semaphore executes the playbook in the background
  4. Click the task in Task Queue to see live output

Output looks like standard Ansible output, color-coded with success/failure.

Scheduling Playbooks

Go to your task template → SchedulesNew Schedule.

Common cron patterns:

Semaphore will automatically run the playbook on schedule.

Use Cases for Home Labs

1. Scheduled System Updates

Create a playbook update-all.yml:

---
- name: Update all Debian/Ubuntu hosts
  hosts: all
  become: true
  tasks:
    - name: Update apt cache
      apt:
        update_cache: true
        cache_valid_time: 3600
    - name: Upgrade packages
      apt:
        upgrade: dist
    - name: Autoremove
      apt:
        autoremove: true
    - name: Check if reboot required
      stat:
        path: /var/run/reboot-required
      register: reboot_required
    - name: Reboot if needed
      reboot:
      when: reboot_required.stat.exists

Schedule it to run every Sunday at 2 AM. Your entire homelab stays updated automatically.

2. Backup Automation

Playbook backup.yml:

---
- name: Backup critical data
  hosts: nas
  tasks:
    - name: Run Restic backup
      command: restic backup /data --repo /mnt/backups/restic
      environment:
        RESTIC_PASSWORD: "{{ vault_restic_password }}"

Schedule nightly. Semaphore logs the output, so you can verify backups succeeded.

3. Deploy Docker Stacks

Playbook deploy-monitoring.yml:

---
- name: Deploy Prometheus monitoring stack
  hosts: pi-monitor
  become: true
  tasks:
    - name: Copy docker-compose file
      copy:
        src: files/monitoring-compose.yml
        dest: /opt/monitoring/docker-compose.yml
    - name: Start stack
      community.docker.docker_compose_v2:
        project_src: /opt/monitoring
        state: present

Run this from Semaphore whenever you update your monitoring config.

4. Trigger from Webhooks

Use Semaphore's API to trigger playbooks from external events.

Example: Trigger a deployment when you push to a Git repo.

curl -X POST http://semaphore.homelab.local:3000/api/project/1/tasks \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"template_id": 5}'

Get an API token from Settings → API Tokens.

Multi-User Access and Permissions

Semaphore supports multiple users with role-based access.

Add a User

Go to Settings → Users → New User.

Assign Permissions

Go to Settings → Projects → [Your Project] → Team.

Add the user with a role:

Example: Give a family member "Task Runner" access. They can click "Run" on the "update-all-systems" template but can't see SSH keys or modify playbooks.

LDAP Integration (Optional)

Semaphore supports LDAP for centralized authentication. If you run an LDAP server (OpenLDAP, FreeIPA), you can integrate it:

Settings → LDAP → Enable LDAP.

Configuration (example):

LDAP Server: ldap://192.168.1.100:389
Bind DN: cn=admin,dc=homelab,dc=local
Bind Password: your-ldap-password
Search Base: ou=users,dc=homelab,dc=local
Username Attribute: uid

Comparison to AWX

Semaphore is simpler and lighter:

AWX is more powerful but complex:

When to use AWX over Semaphore:

For 95% of home labs, Semaphore is the better choice.

Troubleshooting

Playbook fails with "Permission denied (publickey)"

Semaphore can't SSH to target hosts. Check:

  1. SSH key is uploaded to Key Store
  2. The key is the correct private key (not public)
  3. The public key is in ~/.ssh/authorized_keys on target hosts
  4. ansible_user in inventory matches the user with the authorized key

Test manually:

docker exec -it semaphore ssh -i /keys/ansible [email protected]

Playbook runs but tasks fail with "sudo: a password is required"

Your ansible_user doesn't have passwordless sudo. Fix:

# On target host
echo "ansible_user ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ansible

Or add ansible_become_password to your inventory.

Semaphore can't find playbook

Check:

View repository contents:

Go to Repositories → [Your Repo] → Browse.

Can't access Semaphore web UI

Check Docker logs:

docker logs semaphore

Verify the container is running:

docker ps | grep semaphore

Check port binding:

curl http://localhost:3000

If using a reverse proxy, check proxy logs.

Best Practices

Use Git for playbooks: Store playbooks in version control. Semaphore pulls from Git, so you have history and rollback.

Secrets in Ansible Vault: Don't put passwords in plain text in playbooks. Use Ansible Vault and store the vault password in Semaphore's Environment settings.

Test playbooks in CLI first: Before adding a playbook to Semaphore, run it manually via ansible-playbook to debug. Semaphore just wraps Ansible; it doesn't change behavior.

Schedule carefully: Don't schedule heavy playbooks (OS upgrades, reboots) during business hours. Use off-peak times (2-4 AM).

Monitor task history: Periodically review Task History to catch failures. Set up notifications (webhook to Discord/Slack) for failed tasks.

Limit task concurrency: Semaphore can run multiple tasks in parallel. If you have limited resources, set Max Parallel Tasks in project settings.

Notifications and Alerts

Semaphore can send notifications when tasks succeed/fail.

Go to Project Settings → Integrations.

Webhook (send to Discord, Slack, or custom endpoint):

Example Discord webhook payload:

{
  "content": "Playbook **{{ .alias }}** {{ if eq .status \"success\" }}succeeded{{ else }}failed{{ end }}!"
}

Or use email notifications (requires SMTP configuration).

Conclusion

Ansible Semaphore turns Ansible from a CLI tool into a fully-fledged automation platform. You get scheduled runs, a web UI, multi-user access, and task history — all without the complexity of AWX.

For home labs, it's the perfect middle ground: more powerful than raw Ansible CLI, simpler than enterprise tools. Install it via Docker Compose, load your existing playbooks, and start scheduling automation.

Your home lab will thank you when weekly updates, backups, and deployments happen automatically — and you have logs to prove it.

Get free weekly tips in your inbox. Subscribe to HomeLab Starter