Semaphore CI Stack - Lokale Entwicklung
Übersicht
Selbst-gehostete Semaphore CI/CD-Plattform für lokale Entwicklung, die es ermöglicht, CI/CD-Pipelines und Ansible-Playbooks lokal zu testen und auszuführen, ohne Abhängigkeit von externen CI-Services.
Features:
- Selbst-gehostet: Läuft vollständig lokal auf dem Entwicklungsrechner
- Isoliert: Keine externen Zugriffe, nur localhost (127.0.0.1)
- MySQL-Backend: Persistente Datenbank für Projekte, Tasks und Templates
- Web-UI: Intuitive Benutzeroberfläche für Pipeline-Management
- Ansible-Integration: Native Unterstützung für Ansible-Playbooks
- Docker-basiert: Einfaches Setup und Wartung
Einsatzzweck:
- Lokales Testen von CI/CD-Pipelines
- Entwicklung und Test von Ansible-Playbooks
- Experimentieren mit Deployment-Workflows
- Keine Abhängigkeit von externen CI-Services
Services
- mysql - MySQL 8.0 Datenbank für Semaphore-Daten
- semaphore - Semaphore CI/CD Web-UI und API
Voraussetzungen
- Docker und Docker Compose installiert
- Port 3001 auf localhost frei verfügbar (3000 wird von Gitea verwendet)
- Ausreichend Speicherplatz für Docker Volumes (~500MB initial)
Verzeichnisstruktur
semaphore/
├── docker-compose.yml # Service-Definitionen
├── env.example # Environment-Variablen Template
├── .env # Environment-Konfiguration (aus env.example erstellen)
└── README.md # Diese Datei
Quick Start
1. Environment-Datei erstellen
cd deployment/stacks/semaphore
cp env.example .env
2. Konfiguration anpassen (Optional)
Bearbeite .env und passe die Werte an:
nano .env
Wichtig: Generiere einen sicheren Encryption Key:
# Linux/WSL
head -c32 /dev/urandom | base64
# Windows PowerShell
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | % {[char]$_}) | ConvertTo-Base64
Aktualisiere SEMAPHORE_ACCESS_KEY_ENCRYPTION in der .env-Datei.
3. Stack starten
docker compose up -d
4. Semaphore Web-UI öffnen
Öffne im Browser: http://localhost:3001
Standard-Login:
- Username:
admin(oder Wert ausSEMAPHORE_ADMIN) - Password:
admin(oder Wert ausSEMAPHORE_ADMIN_PASSWORD)
5. Erste Schritte in Semaphore
- Projekt erstellen: Klicke auf "New Project" und erstelle ein neues Projekt
- Inventory anlegen: Erstelle ein Inventory mit lokalen Hosts oder Docker-Containern
- Template erstellen: Erstelle ein Template mit einem Ansible-Playbook
- Task ausführen: Starte einen Task und beobachte die Ausführung
Konfiguration
Environment-Variablen (.env)
MySQL-Datenbank
MYSQL_ROOT_PASSWORD=semaphore_root
MYSQL_DATABASE=semaphore
MYSQL_USER=semaphore
MYSQL_PASSWORD=semaphore
Semaphore-Konfiguration
# Port-Binding (Standard: 3001)
SEMAPHORE_PORT=3001
# Admin-Benutzer
SEMAPHORE_ADMIN=admin
SEMAPHORE_ADMIN_NAME=Administrator
SEMAPHORE_ADMIN_EMAIL=admin@localhost
SEMAPHORE_ADMIN_PASSWORD=admin
# Playbook-Pfad (im Container)
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
# Encryption Key (WICHTIG: Für Produktion ändern!)
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
Optionale Konfiguration
LDAP-Integration (Standard: deaktiviert):
SEMAPHORE_LDAP_ENABLED=true
SEMAPHORE_LDAP_HOST=ldap.example.com
SEMAPHORE_LDAP_PORT=389
SEMAPHORE_LDAP_DN=cn=admin,dc=example,dc=com
SEMAPHORE_LDAP_PASSWORD=ldap_password
SEMAPHORE_LDAP_BASE_DN=dc=example,dc=com
SEMAPHORE_LDAP_USER_FILTER=(uid=%s)
Webhook-Integration:
SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
Verwendung
Stack starten
# Services im Hintergrund starten
docker compose up -d
# Logs anzeigen
docker compose logs -f
# Nur Semaphore-Logs
docker compose logs -f semaphore
# Nur MySQL-Logs
docker compose logs -f mysql
Stack stoppen
docker compose down
Stack neu starten
docker compose restart
Status prüfen
# Container-Status anzeigen
docker compose ps
# Health-Check-Status
docker compose ps --format "table {{.Name}}\t{{.Status}}"
# Semaphore-Health-Check manuell
docker compose exec semaphore wget --no-verbose --spider http://localhost:3000/api/health
Datenbank-Backup
# MySQL-Dump erstellen
docker compose exec mysql mysqldump -u semaphore -psemaphore semaphore > semaphore-backup-$(date +%Y%m%d).sql
# Backup wiederherstellen
docker compose exec -T mysql mysql -u semaphore -psemaphore semaphore < semaphore-backup-YYYYMMDD.sql
Daten löschen und neu starten
# ⚠️ WARNUNG: Löscht alle Daten!
docker compose down -v
docker compose up -d
Erste Schritte mit Semaphore
1. Projekt erstellen
- Öffne http://localhost:3001 im Browser
- Melde dich mit Admin-Credentials an
- Klicke auf "New Project"
- Gib einen Projektnamen ein (z.B. "My Project")
- Klicke auf "Create"
2. Inventory anlegen
Ein Inventory definiert die Hosts, auf denen Playbooks ausgeführt werden sollen.
Option A: Lokaler Host
- Gehe zu Projekt → Inventories → New Inventory
- Name: "Local Hosts"
- Hinzufügen von Host:
- Name:
localhost - Address:
127.0.0.1 - SSH Username:
your-username - SSH Key: Füge deinen privaten SSH-Key hinzu
- Name:
Option B: Docker-Container
- Erstelle ein Inventory mit Docker-Hosts
- Für Docker-in-Docker Support benötigst du zusätzliche Konfiguration
3. Template erstellen
Templates definieren welche Playbooks ausgeführt werden sollen.
- Gehe zu Projekt → Templates → New Template
- Template-Name: "Hello World"
- Inventory: Wähle dein Inventory
- Playbook: Erstelle ein einfaches Playbook:
---
- hosts: all
gather_facts: no
tasks:
- name: Print hello world
debug:
msg: "Hello from Semaphore CI!"
- Speichere das Template
4. Task ausführen
- Gehe zu Templates
- Klicke auf dein Template
- Klicke auf "Run"
- Beobachte die Ausführung in Echtzeit
Integration mit bestehenden Stacks
Verwendung mit lokaler Docker-Registry
Semaphore kann Docker-Images aus der lokalen Registry verwenden:
In Ansible-Playbooks:
- name: Pull image from local registry
docker_image:
name: registry.michaelschiemer.de/framework:latest
source: pull
register: image_result
Voraussetzung: Der Semaphore-Container muss Zugriff auf den Docker-Socket oder die Registry haben.
Verwendung mit bestehenden Ansible-Playbooks
-
Mounte deine Playbooks als Volume:
volumes: - /path/to/your/playbooks:/tmp/semaphore/playbooks:ro -
Oder kopiere Playbooks in den Container:
docker compose exec semaphore mkdir -p /tmp/semaphore/my-playbook docker cp my-playbook.yml semaphore:/tmp/semaphore/my-playbook/playbook.yml -
Verweise im Template auf den Playbook-Pfad
Troubleshooting
Port-Konflikt (Port 3000 vs 3001)
Problem: Port 3000 ist standardmäßig von Gitea belegt, daher verwendet Semaphore Port 3001.
Lösung: Wenn du einen anderen Port verwenden möchtest, setze SEMAPHORE_PORT in der .env Datei:
SEMAPHORE_PORT=8080 # Oder ein anderer freier Port
Wichtig: Der interne Container-Port bleibt immer 3000 - nur der externe Host-Port ändert sich.
Semaphore startet nicht
Prüfe Logs:
docker compose logs semaphore
Häufige Ursachen:
- MySQL ist noch nicht bereit (warte auf Health-Check)
- Port 3001 ist bereits belegt:
netstat -tuln | grep 3001(oder auf Windows:netstat -ano | findstr :3001) - Falsche Datenbank-Credentials
Lösung:
# Prüfe MySQL-Status
docker compose ps mysql
# Prüfe Semaphore-Logs für DB-Verbindungsfehler
docker compose logs semaphore | grep -i database
# Restart wenn nötig
docker compose restart semaphore
MySQL startet nicht
Prüfe MySQL-Logs:
docker compose logs mysql
Häufige Ursachen:
- Volume-Permissions-Probleme
- Port-Konflikte (unwahrscheinlich, da kein Port-Mapping)
Lösung:
# Prüfe Volume
docker volume inspect semaphore-mysql-data
# Cleanup und Neu-Start (⚠️ Datenverlust!)
docker compose down -v
docker compose up -d
Login funktioniert nicht
Standard-Credentials:
- Username:
admin(oderSEMAPHORE_ADMINWert) - Password:
admin(oderSEMAPHORE_ADMIN_PASSWORDWert)
Admin-Passwort zurücksetzen:
- Stoppe Semaphore:
docker compose stop semaphore - Setze
SEMAPHORE_ADMIN_PASSWORDin.envauf neues Passwort - Starte Semaphore:
docker compose up -d
Playbooks werden nicht gefunden
Prüfe Playbook-Pfad:
docker compose exec semaphore ls -la /tmp/semaphore
Lösung:
- Stelle sicher, dass
SEMAPHORE_PLAYBOOK_PATHkorrekt gesetzt ist - Prüfe, ob Playbooks im richtigen Pfad liegen
- Stelle sicher, dass Datei-Berechtigungen korrekt sind
Health-Check schlägt fehl
Prüfe Health-Check:
docker compose exec semaphore wget --no-verbose --spider http://localhost:3000/api/health
Lösung:
- Warte auf vollständigen Start (kann 1-2 Minuten dauern)
- Prüfe Logs:
docker compose logs semaphore - Restart wenn nötig:
docker compose restart semaphore
Sicherheit
Lokale Entwicklung (Aktuell)
- ✅ Nur localhost-Zugriff (127.0.0.1:3000)
- ✅ Isoliertes Netzwerk (kein externer Zugriff)
- ✅ Keine Traefik-Integration
- ⚠️ Standard-Passwörter (nur für lokale Entwicklung)
Für Produktion
Wenn du Semaphore später für Produktion nutzen willst:
- Starke Passwörter: Ändere alle Passwörter in
.env - Encryption Key: Generiere einen sicheren Key:
head -c32 /dev/urandom | base64 - Traefik-Integration: Füge Traefik-Labels für HTTPS hinzu
- LDAP/SSO: Konfiguriere externe Authentifizierung
- Backup-Strategie: Regelmäßige MySQL-Backups einrichten
- Resource Limits: Füge Memory/CPU-Limits hinzu
Wartung
Regelmäßige Aufgaben
Wöchentlich:
- Logs auf Fehler prüfen:
docker compose logs --tail=100 - Disk-Space prüfen:
docker system df - Backup erstellen (wenn wichtige Daten vorhanden)
Monatlich:
- Images aktualisieren:
docker compose pull && docker compose up -d - Alte Tasks in Semaphore aufräumen (über Web-UI)
Updates
# Aktuelle Images herunterladen
docker compose pull
# Mit neuen Images neu starten
docker compose up -d
# Logs prüfen
docker compose logs -f
Daten bereinigen
# Alte Docker-Images löschen
docker image prune -a
# Alte Volumes prüfen
docker volume ls
# ⚠️ Vorsicht: Löscht alle Semaphore-Daten!
docker compose down -v
Backup und Wiederherstellung
Backup erstellen
# MySQL-Dump
docker compose exec mysql mysqldump \
-u semaphore -psemaphore semaphore \
> semaphore-backup-$(date +%Y%m%d-%H%M%S).sql
# Volume-Backup (komplett)
docker run --rm \
-v semaphore-mysql-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/semaphore-mysql-backup-$(date +%Y%m%d).tar.gz /data
Wiederherstellung
# MySQL-Dump wiederherstellen
docker compose exec -T mysql mysql \
-u semaphore -psemaphore semaphore \
< semaphore-backup-YYYYMMDD.sql
# Volume wiederherstellen (⚠️ stoppt Container)
docker compose down
docker run --rm \
-v semaphore-mysql-data:/data \
-v $(pwd):/backup \
alpine sh -c "cd /data && tar xzf /backup/semaphore-mysql-backup-YYYYMMDD.tar.gz"
docker compose up -d
Performance-Optimierung
MySQL-Optimierung
Für bessere Performance kannst du MySQL-Konfiguration anpassen:
- Erstelle
mysql/conf.d/my.cnf:
[mysqld]
innodb_buffer_pool_size = 256M
max_connections = 100
- Mounte in
docker-compose.yml:
volumes:
- ./mysql/conf.d:/etc/mysql/conf.d:ro
Resource Limits
Füge Limits in docker-compose.yml hinzu:
deploy:
resources:
limits:
memory: 1G
cpus: '0.5'
Unterstützung
Dokumentation
- Semaphore CI Docs: https://docs.semaphoreui.com/
- Semaphore GitHub: https://github.com/semaphoreui/semaphore
Logs
# Alle Logs
docker compose logs -f
# Semaphore-Logs
docker compose logs -f semaphore
# MySQL-Logs
docker compose logs -f mysql
# Letzte 100 Zeilen
docker compose logs --tail=100
Health-Checks
# Container-Status
docker compose ps
# Semaphore-Health
curl http://localhost:3001/api/health
# MySQL-Health
docker compose exec mysql mysqladmin ping -h localhost -u root -psemaphore_root
Setup-Status: ✅ Bereit für lokale Entwicklung
Nächste Schritte:
cp env.example .envausführendocker compose up -dstarten- http://localhost:3001 öffnen
- Mit Admin-Credentials anmelden
- Erstes Projekt und Template erstellen