ADMIN

2026

09

2026-08-30T12:00:00

Software-definierte Infrastrukturen

SCHWERPUNKT

084

Automatisierung

Infrastructure as Code

DevOps

Mit Semaphore UI Ansible, Terraform und OpenTofu verwalten

Taktstock für Skripte

von Philip Lorenz

Veröffentlicht in Ausgabe 09/2026 - SCHWERPUNKT

Wer Ansible-Playbooks im Team betreibt, riskiert durch kursierende SSH-Keys auf Laptops fatale Sicherheitslücken. Die vermeintliche Rettung AWX entpuppt sich oft als komplexes Kubernetes-Setup und wird mangels aktueller Releases zum ungepatchten Compliancealbtraum. Zudem droht der Plattform-Lock-in, da alternative Werkzeuge wie Terraform oder Bash außen vor bleiben. Semaphore UI versteht sich als leichtgewichtige Automatisierungsplattform, die alle wichtigen Tools dirigiert.

Semaphore UI [1] ist kein neues Projekt. Das in Go geschriebene Open-Source-Werkzeug existiert seit 2016 und hat sich von einem einfachen Ansible-Frontend zu einer vollwertigen Automatisierungsplattform entwickelt. Die aktuelle Version 2.17 steht unter der MIT-Lizenz.
Vier Kernkonzepte strukturieren Semaphore UI
Das Kernversprechen lautet: Eine zentrale Weboberfläche für alle gängigen Automatisierungswerkzeuge wie Ansible, Terraform, OpenTofu, Terragrunt, Bash, Python und PowerShell. Wer mit AWX arbeitet, bindet sich doppelt an eine Plattform und an eine einzige Automatisierungssprache. Semaphore bricht diesen Zweifach-Lock-in auf. Das Werkzeug bildet jedes Tool als eigenständigen App-Typ mit passendem Ausführungsmodell ab.
Die Architektur baut auf vier Kernkonzepten auf: "Projects" sind logische Container für Repositorys, Inventories, Credentials und Templates. "Task Templates" definieren wiederverwendbar, welches Playbook oder Terraform-Modul mit welchem Inventory, welchen Credentials und welchen Variablen läuft. Der "Key Store" legt SSH-Keys, Vault-Passwörter und API-Token verschlüsselt ab. Schließlich dienen "Runners" als externe Execution-Agenten für verteilte Setups, sodass der Semaphore-Server keinen direkten Netzwerkzugriff auf die Zielsysteme benötigt.
Semaphore UI [1] ist kein neues Projekt. Das in Go geschriebene Open-Source-Werkzeug existiert seit 2016 und hat sich von einem einfachen Ansible-Frontend zu einer vollwertigen Automatisierungsplattform entwickelt. Die aktuelle Version 2.17 steht unter der MIT-Lizenz.
Vier Kernkonzepte strukturieren Semaphore UI
Das Kernversprechen lautet: Eine zentrale Weboberfläche für alle gängigen Automatisierungswerkzeuge wie Ansible, Terraform, OpenTofu, Terragrunt, Bash, Python und PowerShell. Wer mit AWX arbeitet, bindet sich doppelt an eine Plattform und an eine einzige Automatisierungssprache. Semaphore bricht diesen Zweifach-Lock-in auf. Das Werkzeug bildet jedes Tool als eigenständigen App-Typ mit passendem Ausführungsmodell ab.
Die Architektur baut auf vier Kernkonzepten auf: "Projects" sind logische Container für Repositorys, Inventories, Credentials und Templates. "Task Templates" definieren wiederverwendbar, welches Playbook oder Terraform-Modul mit welchem Inventory, welchen Credentials und welchen Variablen läuft. Der "Key Store" legt SSH-Keys, Vault-Passwörter und API-Token verschlüsselt ab. Schließlich dienen "Runners" als externe Execution-Agenten für verteilte Setups, sodass der Semaphore-Server keinen direkten Netzwerkzugriff auf die Zielsysteme benötigt.
Als Datenbank-Backend stehen SQLite für den Schnelleinstieg sowie PostgreSQL und MySQL zur Verfügung. Wer später auf eine High-Availability-Infrastruktur wechseln möchte, sollte von Anfang an PostgreSQL einplanen.
Listing 1: Semaphore UI produktiv einrichten
# docker-compose.yml – Produktives Setup
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: semaphore
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: semaphore
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U
   semaphore"]
      interval: 10s
      retries: 5
  semaphore:
    image: semaphoreui/semaphore:latest
    ports:
      - "3000:3000"
    environment:
      SEMAPHORE_DB_DIALECT: postgres
      SEMAPHORE_DB_HOST: postgres
      SEMAPHORE_DB_USER: semaphore
      SEMAPHORE_DB_PASS: ${POSTGRES_PASSWORD}
      SEMAPHORE_DB: semaphore
      SEMAPHORE_ADMIN: admin
      SEMAPHORE_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      SEMAPHORE_ADMIN_NAME: "Admin"
      SEMAPHORE_ADMIN_EMAIL: admin@example.com
      # PFLICHT: 32 Byte base64 - verloren = alle Secrets unbrauchbar
      SEMAPHORE_ACCESS_KEY_ENCRYPTION:
   ${ENCRYPTION_KEY}
    volumes:
      - semaphore-data:/var/lib/semaphore
    depends_on:
      postgres:
        condition: service_healthy
volumes:
  postgres-data:
  semaphore-data:
Flexible Setups von Docker bis Kubernetes
Die Installation ist einer der stärksten Trümpfe gegenüber AWX. Während AWX einen laufenden Kubernetes-Cluster, den AWX Operator und mindestens 8 GByte RAM voraussetzt, reichen bei Semaphore 512 MByte RAM sowie ein einziger docker-run-Befehl:
docker run -p 3000:3000 --name semaphore
  -e SEMAPHORE_DB_DIALECT=sqlite
  -e SEMAPHORE_ADMIN=admin
  -e SEMAPHORE_ADMIN_PASSWORD=changeme
  -e SEMAPHORE_ADMIN_NAME="Admin"
  -e SEMAPHORE_ADMIN_EMAIL= admin@localhost
  -d semaphoreui/semaphore:latest
Nach wenigen Sekunden ist die Weboberfläche unter "http://localhost:3000" erreichbar. Für den Produktionsbetrieb empfiehlt sich PostgreSQL mit persistentem Storage (Listing 1). Aber Achtung: "SEMAPHORE_ACCESS_KEY_ ENCRYPTION" verschlüsselt alle Secrets im Key Store. Verlieren oder ändern Sie diesen Wert, haben Sie keinen Zugriff auf gespeicherte SSH-Keys und Passwörter mehr. Der folgende Befehl erzeugt einen zufälligen 32-Byte-Schlüssel als Base64-Wert:
head -c 32 /dev/urandom | base64
Die Ausgabe lässt sich anschließend als Wert für "SEMAPHORE_ACCESS_KEY_ENCRYPTION" verwenden.
Um Semaphore in Kubernetes zu betreiben, steht Ihnen ein offizielles Helm-Chart auf ArtifactHub zur Verfügung, der Zugriff gelingt via:
helm repo add semaphoreui https://semaphoreui.github.io/semaphore
helm install semaphore semaphoreui/semaphore
  --namespace automation
  --create-namespace
  -f values.yaml
Die values.yaml-Datei konfiguriert Datenbankverbindung, Ingress mit TLS und Secrets via Kubernetes-Secret-Objekt. Für den systemd-Betrieb gibt es offizielle DEB- und RPM-Pakete mit "/etc/semaphore/config.json" als Konfigurationsdatei. Nach dem Login startet eine aufgeräumte Oberfläche, in der Sie im ersten Schritt ein Projekt anlegen. Danach folgt ein klarer Workflow: Key Store befüllen, Repository einbinden, Inventory anlegen, Task Template erstellen und Task ausführen.
Das Semaphore-Dashboard zeigt die Task-History mit User, Startzeitpunkt und Status auf einen Blick. Ansible, Terraform und PowerShell laufen nebeneinander in derselben Oberfläche.
Als letzte Variante sind Sie in der Lage, ein Demo-Setup in nur fünf Minuten hochzuziehen. Dazu benötigen Sie Docker und Docker Compose und starten zunächst den Stack:
git clone https://github.com/philiplorenz-code/heinemann.git
cd heinemann/semaphore
cp .env.example .env
docker compose up -d
Dann richten Sie das Projekt für Ansible, Terraform und PowerShell ein:
GITHUB_REPO=https://github.com/philiplorenz-code/heinemann
REPO_BRANCH=main \
bash <(curl -fsSL https://raw.githubusercontent.com/philiplorenz-code/heinemann/main/ semaphore/scripts/setup-demo.sh)
http://localhost:3000 — admin / Admin1234!
Das Skript legt automatisch drei lauffähige Task Templates an (alle Repos werden direkt von GitHub geklont):
- Ansible-Playbook (Hello World, läuft lokal ohne SSH)
- Terraform-Beispiel mit random- und local-Provider (kein Cloudaccount nötig)
- PowerShell-Report via pwsh
Den Aufbau stoppen Sie einfach mit docker compose down. Nutzen Sie den Parameter "-v", löscht dieser auch die Daten.
Ansible-Workflows im Schichtenmodell
Der Ansible-Workflow in Semaphore folgt einem Schichtenmodell, das Verantwortlichkeiten klar trennt. Die unterste Schicht bildet der Key Store. Hier hinterlegen Sie SSH-Keys, Become-Passwörter, Ansible-Vault-Passwörter und API-Token. Das Werkzeug legt alle sensitiven Daten mit dem Encryption Key verschlüsselt ab, sodass kein Klartext in der Datenbank landet.
Darüber liegt die Repository-Schicht. Semaphore klont das Git-Repository bei jedem Task-Run frisch und berücksichtigt dabei die Branch-Auswahl. Das verhindert lokalen State auf dem Server und vermeidet eine Drift zwischen dem ausgeführten Code und den Daten im Git, das hier als Single Source of Truth fungiert.
Das Inventory definiert die Zielhosts. Semaphore unterstützt statische Inventories (Listing 2) im INI- oder YAML-Format sowie dynamische über Skripte. Zudem liest das Werkzeug Dateien direkt aus dem Repository ein.
Listing 2: Statisches Inventory im INI-Format
[webservers]
web-01.example.com ansible_user=deployer
web-02.example.com ansible_user=deployer
[dbservers]
db-01.example.com ansible_user=deployer
[prod:children]
webservers
dbservers
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Environment-Variablen und "extra_vars" hinterlegen Sie über "Variable Groups" im JSON-Format:
{ "env": { "ANSIBLE_STDOUT_CALLBACK": "yaml", "ANSIBLE_HOST_KEY_CHECKING": "False" }, "extra_vars": { "deploy_env": "production", "app_version": "2.4.1", "notify_slack": true }
Das Task-Template bindet alles zusammen: Repository, Playbook-Pfad, Inventory, Key-Store-Eintrag und Variable-Group. CLI-Argumente wie "--tags deploy" lassen sich direkt hinterlegen. Arbeiten Sie mit Ansible Vault, wählen Sie im Template den Vault-Passwort-Key. Semaphore übergibt diesen automatisch als "--vault-password-file", sodass der Klartext den Key Store niemals verlässt.
Die Task-Ausführung verfolgen Sie in Echtzeit im Browser. Alle Runs landen mit Timestamp, auslösendem User und vollständigem Output in der Datenbank. Wenn Sie nach einem Incident wissen wollen, wer wann welches Playbook gegen welche Umgebung ausgeführt hat, liefert das Werkzeug eine eindeutige Antwort.
Infrastructure-as-Code via Terraform
Wer Terraform-Code bisher aus dem lokalen CLI ausführt, unterschätzt das dahinterstehende Sicherheitsproblem: Cloud-Credentials auf Entwicklerlaptops, kein Vier-Augen-Prinzip vor dem "apply" und kein Audit-Trail. Semaphore löst das nativ. Die Konfiguration unterscheidet sich von Ansible nur im "App Typ"-Feld. Wählen Sie hier "Terraform" oder "OpenTofu", führt Semaphore vor jedem Lauf automatisch "terraform init" aus. Der eigentliche Workflow folgt dem aus Terraform Cloud bekannten Plan-Apply-Muster. Konkret führt Semaphore den folgenden Befehl aus:
terraform plan -out=tfplan
Das Werkzeug zeigt den Output im Browser an, ein berechtigter User gibt den Plan frei, und erst dann folgt dieser Aufruf:
terraform apply tfplan
Dieses Muster fehlt in vielen Teams – nicht weil niemand es will, sondern weil der Aufwand ohne passendes Tooling zu hoch ist. Semaphore macht es zum Standard. Cloud-Credentials hinterlegen Sie dabei nicht als Datei, sondern injizieren sie über Environment-Variablen aus dem Key Store (Listing 3).
Listing 3: Cloud-Credentials übergeben
  "env": {
    "AWS_ACCESS_KEY_ID": "{{ semaphore_secret.aws_access_key }}",
    "AWS_SECRET_ACCESS_KEY": "{{ semaphore_secret.aws_secret_key }}",
    "AWS_DEFAULT_REGION": "eu-central-1",
    "TF_LOG": "ERROR"
  },
  "extra_vars": {
    "environment": "production",
    "vpc_cidr": "10.0.0.0/16"
  }
}
Das Terraform-Modul bleibt vollständig unverändert. Für die State-Verwaltung funktioniert der übliche Weg über S3, Azure Blob oder GCS. Mit Semaphore Pro lässt sich Semaphore selbst als HTTP Backend nutzen:
terraform { backend "http" { address = "http://localhost:3000/ api/terraform/***" username = "***" password = "***" } }
Webhooks und REST-API im Praxiseinsatz
Semaphore ist kein Silo. Das vollständige REST-API mit OpenAPI/Swagger-Dokumentation macht die Plattform zum First-Class-Citizen in bestehenden Toolchains. Webhook-URLs pro Task Template ermöglichen eine sehr einfache Integration: Ein HTTP-POST genügt, um einen Run zu triggern (Listing 4).
Listing 4: Task per Webhook starten
curl -X POST \
  "https://semaphore.example.com/api/v1/ project/1/tasks?token=WEBHOOK-TOKEN" \
  -H "Content-Type: application/json" \
  -d "{"template_id": 5}"
# Task per Bearer-Token starten und Status pollen
curl -X POST https://semaphore.example.com/api/v1/project/1/tasks \
  -H "Authorization: Bearer ${SEMAPHORE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{"template_id": 5, "environment": "{\"deploy_version\": \"2.5.0\"}"}"
# Antwort: {"id": 42, "status": "waiting", ...}
# Status prüfen
curl -H "Authorization: Bearer ${SEMAPHORE_TOKEN}" \
  "https://semaphore.example.com/api/v1/ project/1/tasks/42"
In der Praxis ergeben sich daraus mehrere konkrete Szenarien: Als Erstes API-gestützte Pipelines, die das Deployment steuern. GitHub Actions oder GitLab CI triggert nach einem erfolgreichen Build automatisch das Deployment-Template in Semaphore und pollt den Status. Der Pipeline-Job schlägt fehl, wenn das Deployment nicht gelingt. Dadurch entfällt der manuelle Eingriff, und Administratoren erhalten einen vollständigen Audit-Trail auf beiden Seiten.
Für den Self-Service in Operations ruft ein internes Ticketsystem oder ein einfaches Intranet-Formular das Semaphore-API auf. Der L1-Supporter klickt beispielsweise auf "Neustart Web-Cluster". Semaphore führt das Playbook aus, während der Supporter zu keinem Zeitpunkt einen SSH-Key sieht. Dieses Modell funktioniert für alle Vorgänge, die sich als Template abbilden lassen – von Passwort-Resets über Zertifikatserneuerungen bis hin zu Datenbankbackups on demand.
Drittens lässt sich eine eventgetriebene Infrastruktur realisieren, indem ein Monitoringsystem wie Grafana oder Zabbix bei einem Alarm direkt ein Remediation-Playbook triggert. Läuft ein Server voll, räumt Semaphore auf und antwortet ein Dienst nicht, startet das Werkzeug ihn neu. Die Reaktionszeit sinkt dadurch von "jemand muss nachts das Telefon abnehmen" auf wenige Sekunden. Benachrichtigungen lassen sich pro Task-Status für Slack, Microsoft Teams und generische Webhooks konfigurieren. Semaphore unterscheidet dabei zwischen "success", "error" und "stopped", was ein differenziertes Alerting ermöglicht.
Rollenprofile schützen den Infrastrukturzugriff
Semaphore steuert Zugriffsrechte auf zwei Ebenen: global und pro Projekt. Auf Projektebene stehen vier Rollen zur Verfügung:
- Admin: Vollzugriff auf die Projektkonfiguration, Templates, Inventories, den Key Store und die Team-Verwaltung.
- Manager: Darf Templates, Inventories und Variable-Groups anlegen und bearbeiten.
- Task Runner: Darf konfigurierte Templates ausführen, aber nicht ändern und sieht keine Credential-Details.
- Viewer: Ausschließlich Lesezugriff auf Task-Logs und die Ausführungshistorie.
Das Task-Runner-Prinzip markiert den entscheidenden Unterschied zum SSH-Zugang für alle Mitarbeiter. Ein Level-Eins-Supporter kann ein Deployment starten, ohne SSH-Keys zu sehen, ohne Zugriff auf Playbooks zu haben und ohne Templates ändern zu können. Das Vier-Augen-Prinzip lässt sich damit technisch erzwingen. Jede Ausführung landet im Audit-Log mit Timestamp, auslösendem User, Template und vollständigem Output. In vielen Compliance-Frameworks ist das eine harte Anforderung.
Fünf Best Practices für Ansible-Workflows
1. Naming Convention: Templates konsistent benennen mit Umgebung und Funktion.
2. Vault-Strategie: Ansible Vault für alle Secrets nutzen, Vault-Passwort ausschließlich über den Key Store übergeben.
3. Environments isolieren: Pro Umgebung eigene Variable Groups, nie eine Group für dev, staging und prod gleichzeitig.
4. Branch-Strategie: Produktions-Templates auf main fixieren, Staging-Templates auf develop.
5. Dry-Run first: Für kritische Playbooks ein separates Template mit "--check" als Pflichtschritt vor dem echten Deploy.
Erweiterte Lizenzen und Einsatzgebiete
Die Open-Source-Version deckt für die meisten Teams 80 bis 90 Prozent der Anforderungen ab. Die Pro- und Enterprise-Lizenzen liefern operativen Mehrwert für spezifische Szenarien. Die Pro-Version bringt zusätzlich Zwei-Faktor-Authentisierung (2FA) inklusive TOTP, ein Terraform-HTTP-Backend, Syslog-Forwarding, Projektexport und -import via CLI (Disaster-Recovery- und Migrationsszenarien) sowie Datenbankmigrationen mit Rollback.
Die Enterprise-Edition adressiert sehr große Umgebungen und Managed-Service-Provider (MSPs). Das technische Herzstück bildet ein Active-Active-High-Availability-Betrieb. Im HA-Betrieb laufen mehrere Semaphore-Instanzen gleichzeitig hinter einem Loadbalancer – ohne Primary und ohne Standby. Darüber hinaus umfasst die Lizenz die Integration in Entra ID, Okta, Keycloak und andere OIDC-Provider. Auch hat sie ein granulares RBAC mit Custom Roles an Bord. Die automatische Skalierung der Runner-Instanzen mit der Task-Last, die Drift Detection und Priority Support mit SLA runden dieses Paket ab.
Beim Kostenvergleich zur Red Hat Ansible Automation Platform wird der Unterschied deutlich: AAP-Subskriptionen beginnen im fünfstelligen Jahresbereich. Semaphore Pro liegt in der größten Ausbaustufe bei etwa 1000 Dollar pro Jahr. Die Enterprise-Preise kommuniziert der Hersteller jedoch nur auf Anfrage.
Aus den genannten Kosten und dem Feature- set ergibt sich die logische Frage: Welche Automatisierungsplattform ist die passende? Sie treffen mit Semaphore die richtige Wahl, wenn Ihr Team keine dedizierte Kubernetes-Infrastruktur betreibt, wenn neben Ansible auch Terraform zentral verwaltet werden soll oder wenn Sie ein funktionsfähiges Setup in Minuten benötigen. Für MSPs mit Mandanten-Isolation ist das Projektkonzept ebenfalls gut geeignet.
AWX ergibt Sinn, wenn das IT-Team bereits Kubernetes betreibt und ein Upgrade auf AAP konkret geplant ist, sobald die Entwicklung nach dem Refactoring wieder läuft. Für Neuinstallationen bildet das Produkt heute kein stabiles Fundament. Die Ansible Automation Platform ist richtig, wenn ein kommerzieller Supportvertrag regulatorisch gefordert ist, das Unternehmen im Red-Hat-Ökosystem verwurzelt ist und AAP-spezifische Features wie Execution Environments zwingend erforderlich sind.
Fazit
Semaphore UI füllt die Lücke zwischen "Ansible-Playbook auf dem Laptop" und "drei Kubernetes-Nodes für die Automatisierungsplattform". Das Werkzeug ist kein AWX-Klon. Es verfolgt ein anderes Konzept: leichtgewichtig, Multi-Tool, MIT-lizenziert und aktiv entwickelt. Wer heute Terraform und Ansible parallel einsetzt, bekommt mit Semaphore erstmals eine einzige Plattform für beide Workflows mit demselben Audit-Trail, demselben RBAC-Modell und denselben Webhook-Triggern.
(jp)
Links
[1] Semaphore UI: https://it-a.eu/q9z31