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

577 lines
14 KiB
Markdown

# 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
```bash
cd deployment/stacks/semaphore
cp env.example .env
```
### 2. Konfiguration anpassen (Optional)
Bearbeite `.env` und passe die Werte an:
```bash
nano .env
```
**Wichtig**: Generiere einen sicheren Encryption Key:
```bash
# 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
```bash
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
```env
MYSQL_ROOT_PASSWORD=semaphore_root
MYSQL_DATABASE=semaphore
MYSQL_USER=semaphore
MYSQL_PASSWORD=semaphore
```
#### Semaphore-Konfiguration
```env
# 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):
```env
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**:
```env
SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
```
## Verwendung
### Stack starten
```bash
# 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
```bash
docker compose down
```
### Stack neu starten
```bash
docker compose restart
```
### Status prüfen
```bash
# 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
```bash
# 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
```bash
# ⚠️ 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:
```yaml
---
- hosts: all
gather_facts: no
tasks:
- name: Print hello world
debug:
msg: "Hello from Semaphore CI!"
```
5. 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**:
```yaml
- 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:
```yaml
volumes:
- /path/to/your/playbooks:/tmp/semaphore/playbooks:ro
```
2. Oder kopiere Playbooks in den Container:
```bash
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:
```env
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**:
```bash
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**:
```bash
# 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**:
```bash
docker compose logs mysql
```
**Häufige Ursachen**:
- Volume-Permissions-Probleme
- Port-Konflikte (unwahrscheinlich, da kein Port-Mapping)
**Lösung**:
```bash
# 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**:
```bash
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**:
```bash
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`:
```env
SEMAPHORE_ADMIN_PASSWORD=<starkes-passwort>
MYSQL_PASSWORD=<starkes-passwort>
MYSQL_ROOT_PASSWORD=<starkes-passwort>
```
2. **Encryption Key**: Generiere einen sicheren Key:
```bash
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
```bash
# Aktuelle Images herunterladen
docker compose pull
# Mit neuen Images neu starten
docker compose up -d
# Logs prüfen
docker compose logs -f
```
### Daten bereinigen
```bash
# 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
```bash
# 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
```bash
# 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`:
```ini
[mysqld]
innodb_buffer_pool_size = 256M
max_connections = 100
```
2. Mounte in `docker-compose.yml`:
```yaml
volumes:
- ./mysql/conf.d:/etc/mysql/conf.d:ro
```
### Resource Limits
Füge Limits in `docker-compose.yml` hinzu:
```yaml
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
```bash
# 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
```bash
# 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