Ditch the Terminal: Managing Ansible Playbooks with Semaphore UI and Docker

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

The 2 AM Infrastructure Meltdown

It was 2:14 AM on a Tuesday. My Uptime Kuma dashboard was a wall of red. A critical security patch needed to hit 15 Docker containers and three Debian VMs immediately. Usually, this is a five-minute job, but exhaustion had turned my brain to mush. My terminal history was a chaotic graveyard of ansible-playbook commands, missing -i flags, and typos in --extra-vars.

Squinting at the screen, I couldn’t remember which subdirectory held the SSH key for the new database node. My HomeLab had officially outgrown the “run it from my laptop” phase. I needed a centralized, visual way to trigger automation. More importantly, I needed to stop myself from accidentally nuking a production-grade file server while sleep-deprived.

The Friction Point: Why CLI-Only Ansible Scales Poorly

Ansible is powerful, but manual execution in a growing lab is a recipe for disaster. It lacks a persistent state and a centralized audit log. When you run a playbook from your laptop, only you know it happened. If you use multiple machines or share your lab with a friend, tracking who ran what—and with which variables—becomes a detective project.

The frustration usually stems from three specific issues:

  • Scattered Secrets: SSH keys and Vault passwords live in random folders across different machines.
  • Zero Visibility: You can’t see execution history without scrolling through 5,000 lines of terminal buffer.
  • Cognitive Load: Running a simple “Update All” task requires remember long, error-prone CLI strings every time.

The Weigh-In: AWX vs. Semaphore UI

Most people first look at AWX, the open-source version of Red Hat’s Ansible Automation Platform. While it’s the gold standard, AWX is a resource hog. It essentially requires a dedicated Kubernetes cluster or a beefy VM with at least 8GB of RAM just to sit idle. For a HomeLab running on a few Intel NUCs or a Raspberry Pi 5, AWX is massive overkill.

Then there is Semaphore UI. Written in Go, it is incredibly snappy and uses less than 150MB of RAM. It provides exactly what a HomeLab enthusiast needs without the enterprise bloat:

  • A responsive web interface to trigger playbooks.
  • Centralized storage for SSH keys and Vault secrets.
  • Real-time logs and a searchable history of every run.
  • Inventory management that doesn’t involve wrestling with flat .ini files daily.

I switched my primary lab controller to Semaphore six months ago. Since then, my deployment reliability has skyrocketed because the “human error” factor of the CLI is gone.

The Setup: Deploying Semaphore with Docker Compose

We will use Docker Compose with a PostgreSQL backend to keep things portable. This setup ensures your logs and configurations are easy to back up or migrate if you upgrade your hardware later.

1. Preparing the Environment

Start by creating a dedicated project folder. Keeping your infrastructure tools in /opt or your home directory ensures they don’t get lost in the shuffle.

mkdir -p ~/homelab/semaphore && cd ~/homelab/semaphore
touch docker-compose.yml

2. The Docker Compose Configuration

Paste this configuration into your docker-compose.yml. This uses the latest stable Semaphore image and Postgres 14.

services:
  postgres:
    image: postgres:14-alpine
    volumes:
      - ./semaphore-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=your_secure_password
      - POSTGRES_DB=semaphore
      - POSTGRES_USER=semaphore
    restart: unless-stopped

  semaphore:
    image: semaphoreui/semaphore:latest
    ports:
      - "3000:3000"
    environment:
      - SEMAPHORE_DB_USER=semaphore
      - SEMAPHORE_DB_PASS=your_secure_password
      - SEMAPHORE_DB_HOST=postgres
      - SEMAPHORE_DB_PORT=5432
      - SEMAPHORE_DB=semaphore
      - SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
      - SEMAPHORE_ADMIN_PASSWORD=admin_password
      - SEMAPHORE_ADMIN_NAME=Admin
      - [email protected]
      - SEMAPHORE_ADMIN=admin
    depends_on:
      - postgres
    restart: unless-stopped

3. Launching the Service

Bring the stack online with one command. Once the containers are healthy, browse to http://your-server-ip:3000.

docker compose up -d

Mastering the Four Pillars of Semaphore

After logging in, you’ll need to configure the core components that make Semaphore work: Keys, Repos, Inventories, and Templates.

Step A: The Key Store

Centralize your security here. Instead of SSH keys floating around your file system, you upload them to Semaphore’s encrypted store. It handles standard SSH keys, login credentials, and even Ansible Vault passwords. Pro tip: Create a dedicated “Ansible” user on your nodes and give its key to Semaphore.

Step B: Repositories

Connect your Git repo (GitHub, GitLab, or Gitea). Every time you hit “Run,” Semaphore pulls the latest version of your code. This eliminates the “Is the script on my laptop newer than the server?” headache forever.

Step C: Inventory

Define your hosts directly in the UI. You can group them into “Production,” “Staging,” or “Lab.” It supports standard hosts.ini or YAML formatting. You can simply copy-paste your existing inventory files and they will work immediately.

Step D: Task Templates

This is where your automation comes to life. A Task Template links a Git repo, an inventory, and a specific playbook. For example, I have a “Weekly Security Patch” template. One click runs the update across 20 nodes, showing me a live, color-coded terminal output in the browser. If a specific task fails on node #12, the UI highlights it in red instantly.

Advanced Tip: Handling Encrypted Secrets

If you use ansible-vault to protect sensitive data—which you absolutely should—add your Vault password to the Key Store. When you create a Task Template, link that Vault key. Semaphore will decrypt your variables on the fly during execution without ever leaking the password into your logs.

The Verdict: Professional Grade, Minimal Effort

Switching to Semaphore UI was the single best upgrade for my sanity. It turned high-stakes late-night maintenance into a simple button-click process. If something breaks, I have a clear, visual record of why it happened.

If you run playbooks more than once a week, stop using the CLI manually. Semaphore is light enough to run on a “potato” server but robust enough to handle a complex professional lab. Your future 2 AM self will thank you for the peace of mind.

Share: