Files
michaelschiemer/deployment/stacks/semaphore/README.md
Michael Schiemer 77c656af62 feat(deployment): update Semaphore stack and Traefik configuration
- Add QUICKSTART.md and SETUP_REPOSITORY.md for Semaphore stack
- Add playbooks directory for Semaphore deployment
- Update Semaphore docker-compose.yml, env.example, and README
- Add Traefik local configuration files
- Disable semaphore.yml in Traefik dynamic config
- Update docker-compose.local.yml and build-image workflow
2025-11-02 22:55:51 +01:00

14 KiB

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
  • Lokal isoliert: NUR über localhost (127.0.0.1) erreichbar - KEIN externer Zugriff aus Sicherheitsgründen!
  • MySQL-Backend: Persistente Datenbank für Projekte, Tasks und Templates
  • Web-UI: Intuitive Benutzeroberfläche für Pipeline-Management (nur lokal)
  • 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 9300 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:9300

⚠️ WICHTIG: Semaphore ist NUR lokal zugänglich (127.0.0.1). Es gibt KEINEN externen Zugriff aus Sicherheitsgründen.

Standard-Login:

  • Username: admin (oder Wert aus SEMAPHORE_ADMIN)
  • Password: admin (oder Wert aus SEMAPHORE_ADMIN_PASSWORD)

5. Erste Schritte in Semaphore

  1. Projekt erstellen: Klicke auf "New Project" und erstelle ein neues Projekt
  2. Inventory anlegen: Erstelle ein Inventory mit lokalen Hosts oder Docker-Containern
  3. Template erstellen: Erstelle ein Template mit einem Ansible-Playbook
  4. 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: 9300)
SEMAPHORE_PORT=9300

# 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

  1. Öffne http://localhost:9300 im Browser
  2. Melde dich mit Admin-Credentials an
  3. Klicke auf "New Project"
  4. Gib einen Projektnamen ein (z.B. "My Project")
  5. Klicke auf "Create"

2. Inventory anlegen

Ein Inventory definiert die Hosts, auf denen Playbooks ausgeführt werden sollen.

Option A: Lokaler Host

  1. Gehe zu Projekt → Inventories → New Inventory
  2. Name: "Local Hosts"
  3. Hinzufügen von Host:
    • Name: localhost
    • Address: 127.0.0.1
    • SSH Username: your-username
    • SSH Key: Füge deinen privaten SSH-Key hinzu

Option B: Docker-Container

  1. Erstelle ein Inventory mit Docker-Hosts
  2. Für Docker-in-Docker Support benötigst du zusätzliche Konfiguration

3. Template erstellen

Templates definieren welche Playbooks ausgeführt werden sollen.

  1. Gehe zu Projekt → Templates → New Template
  2. Template-Name: "Hello World"
  3. Inventory: Wähle dein Inventory
  4. Playbook: Erstelle ein einfaches Playbook:
---
- hosts: all
  gather_facts: no
  tasks:
    - name: Print hello world
      debug:
        msg: "Hello from Semaphore CI!"
  1. Speichere das Template

4. Task ausführen

  1. Gehe zu Templates
  2. Klicke auf dein Template
  3. Klicke auf "Run"
  4. 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

  1. Mounte deine Playbooks als Volume:

    volumes:
      - /path/to/your/playbooks:/tmp/semaphore/playbooks:ro
    
  2. 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
    
  3. Verweise im Template auf den Playbook-Pfad

Troubleshooting

Port-Konflikt (Port 3000 vs 9300)

Problem: Port 3000 ist standardmäßig von Gitea belegt, daher verwendet Semaphore Port 9300.

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 9300 ist bereits belegt: netstat -tuln | grep 9300 (oder auf Windows: netstat -ano | findstr :9300)
  • 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 (oder SEMAPHORE_ADMIN Wert)
  • Password: admin (oder SEMAPHORE_ADMIN_PASSWORD Wert)

Admin-Passwort zurücksetzen:

  1. Stoppe Semaphore: docker compose stop semaphore
  2. Setze SEMAPHORE_ADMIN_PASSWORD in .env auf neues Passwort
  3. 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_PATH korrekt 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

🔒 Lokaler Zugriff (Nur localhost)

Semaphore ist absichtlich NUR lokal zugänglich aus Sicherheitsgründen:

  • Nur localhost-Zugriff: Port 9300 gebunden an 127.0.0.1 (nicht 0.0.0.0)
  • Keine externen Netzwerke: Kein externer Zugriff möglich
  • Keine Traefik-Integration: Keine öffentliche Route konfiguriert
  • Isoliertes Netzwerk: Nur internes Docker-Netzwerk
  • ⚠️ Standard-Passwörter: Nur für lokale Entwicklung - ändern bei Bedarf

⚠️ KEINE Produktions-Nutzung über Internet!

Semaphore sollte NICHT öffentlich zugänglich gemacht werden!

Gründe:

  1. Sicherheitsrisiko: Semaphore hat Zugriff auf SSH-Keys und Deployment-Credentials
  2. Privilegierter Zugriff: Kann auf Produktions-Server zugreifen
  3. Keine Multi-Factor-Authentication: Standardmäßig keine 2FA
  4. Exploits: Selbst-gehostete Software kann Sicherheitslücken haben

Für lokale Entwicklung (Empfohlen)

Wenn du Semaphore lokal nutzen willst:

  1. Starke Passwörter: Ändere alle Passwörter in .env:
    SEMAPHORE_ADMIN_PASSWORD=<starkes-passwort>
    MYSQL_PASSWORD=<starkes-passwort>
    MYSQL_ROOT_PASSWORD=<starkes-passwort>
    
  2. Encryption Key: Generiere einen sicheren Key:
    head -c32 /dev/urandom | base64
    
    Setze in .env: SEMAPHORE_ACCESS_KEY_ENCRYPTION=<generierter-key>
  3. SSH-Keys: Stelle sicher, dass SSH-Keys sicher gespeichert sind
  4. Backup-Strategie: Regelmäßige MySQL-Backups einrichten
  5. Resource Limits: Füge Memory/CPU-Limits hinzu (optional)

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:

  1. Erstelle mysql/conf.d/my.cnf:
[mysqld]
innodb_buffer_pool_size = 256M
max_connections = 100
  1. 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

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:9300/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:

  1. cp env.example .env ausführen
  2. docker compose up -d starten
  3. http://localhost:9300 öffnen
  4. Mit Admin-Credentials anmelden
  5. Erstes Projekt und Template erstellen