feat: update deployment configuration and encrypted env loader
- Update Ansible playbooks and roles for application deployment - Add new Gitea/Traefik troubleshooting playbooks - Update Docker Compose configurations (base, local, staging, production) - Enhance EncryptedEnvLoader with improved error handling - Add deployment scripts (autossh setup, migration, secret testing) - Update CI/CD workflows and documentation - Add Semaphore stack configuration
This commit is contained in:
48
deployment/stacks/semaphore/.env.example
Normal file
48
deployment/stacks/semaphore/.env.example
Normal file
@@ -0,0 +1,48 @@
|
||||
# Semaphore CI Stack - Environment Configuration
|
||||
# Copy this file to .env and adjust values as needed
|
||||
|
||||
# ============================================
|
||||
# MySQL Database Configuration
|
||||
# ============================================
|
||||
MYSQL_ROOT_PASSWORD=semaphore_root
|
||||
MYSQL_DATABASE=semaphore
|
||||
MYSQL_USER=semaphore
|
||||
MYSQL_PASSWORD=semaphore
|
||||
|
||||
# ============================================
|
||||
# Semaphore Configuration
|
||||
# ============================================
|
||||
|
||||
# Port binding (default: 3000)
|
||||
# Only accessible via localhost (127.0.0.1)
|
||||
SEMAPHORE_PORT=3000
|
||||
|
||||
# Admin User Configuration
|
||||
SEMAPHORE_ADMIN=admin
|
||||
SEMAPHORE_ADMIN_NAME=Administrator
|
||||
SEMAPHORE_ADMIN_EMAIL=admin@localhost
|
||||
SEMAPHORE_ADMIN_PASSWORD=admin
|
||||
|
||||
# Playbook Storage Path (inside container)
|
||||
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
|
||||
|
||||
# Access Key Encryption
|
||||
# Generate with: head -c32 /dev/urandom | base64
|
||||
# IMPORTANT: Change this in production!
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
|
||||
|
||||
# ============================================
|
||||
# Optional: LDAP Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_LDAP_ENABLED=false
|
||||
# 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)
|
||||
|
||||
# ============================================
|
||||
# Optional: Webhook Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
|
||||
556
deployment/stacks/semaphore/README.md
Normal file
556
deployment/stacks/semaphore/README.md
Normal file
@@ -0,0 +1,556 @@
|
||||
# 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
|
||||
|
||||
```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:3001
|
||||
|
||||
**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: 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):
|
||||
```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:3001 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 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:
|
||||
```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 3001 ist bereits belegt: `netstat -tuln | grep 3001` (oder auf Windows: `netstat -ano | findstr :3001`)
|
||||
- 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
|
||||
|
||||
### 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:
|
||||
|
||||
1. **Starke Passwörter**: Ändere alle Passwörter in `.env`
|
||||
2. **Encryption Key**: Generiere einen sicheren Key:
|
||||
```bash
|
||||
head -c32 /dev/urandom | base64
|
||||
```
|
||||
3. **Traefik-Integration**: Füge Traefik-Labels für HTTPS hinzu
|
||||
4. **LDAP/SSO**: Konfiguriere externe Authentifizierung
|
||||
5. **Backup-Strategie**: Regelmäßige MySQL-Backups einrichten
|
||||
6. **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
|
||||
|
||||
```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: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**:
|
||||
1. `cp env.example .env` ausführen
|
||||
2. `docker compose up -d` starten
|
||||
3. http://localhost:3001 öffnen
|
||||
4. Mit Admin-Credentials anmelden
|
||||
5. Erstes Projekt und Template erstellen
|
||||
|
||||
87
deployment/stacks/semaphore/docker-compose.yml
Normal file
87
deployment/stacks/semaphore/docker-compose.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
services:
|
||||
# MySQL Database for Semaphore
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: semaphore-mysql
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- semaphore-internal
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-semaphore_root}
|
||||
- MYSQL_DATABASE=${MYSQL_DATABASE:-semaphore}
|
||||
- MYSQL_USER=${MYSQL_USER:-semaphore}
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-semaphore}
|
||||
volumes:
|
||||
- semaphore-mysql-data:/var/lib/mysql
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-semaphore_root}"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
command: >
|
||||
--default-authentication-plugin=mysql_native_password
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_unicode_ci
|
||||
|
||||
# Semaphore CI/CD Platform
|
||||
semaphore:
|
||||
image: semaphoreui/semaphore:latest
|
||||
container_name: semaphore
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- semaphore-internal
|
||||
ports:
|
||||
# Only bind to localhost, not external interfaces
|
||||
# Default port 3001 to avoid conflict with Gitea (port 3000)
|
||||
- "127.0.0.1:${SEMAPHORE_PORT:-3001}:3000"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
# Database Configuration
|
||||
- SEMAPHORE_DB_DIALECT=mysql
|
||||
- SEMAPHORE_DB_HOST=mysql
|
||||
- SEMAPHORE_DB_PORT=3306
|
||||
- SEMAPHORE_DB=${MYSQL_DATABASE:-semaphore}
|
||||
- SEMAPHORE_DB_USER=${MYSQL_USER:-semaphore}
|
||||
- SEMAPHORE_DB_PASS=${MYSQL_PASSWORD:-semaphore}
|
||||
# Admin Configuration
|
||||
- SEMAPHORE_ADMIN=${SEMAPHORE_ADMIN:-admin}
|
||||
- SEMAPHORE_ADMIN_NAME=${SEMAPHORE_ADMIN_NAME:-Administrator}
|
||||
- SEMAPHORE_ADMIN_EMAIL=${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}
|
||||
- SEMAPHORE_ADMIN_PASSWORD=${SEMAPHORE_ADMIN_PASSWORD:-admin}
|
||||
# Playbook Path
|
||||
- SEMAPHORE_PLAYBOOK_PATH=${SEMAPHORE_PLAYBOOK_PATH:-/tmp/semaphore}
|
||||
# Encryption Key (generate with: head -c32 /dev/urandom | base64)
|
||||
- SEMAPHORE_ACCESS_KEY_ENCRYPTION=${SEMAPHORE_ACCESS_KEY_ENCRYPTION:-change-me-in-production}
|
||||
# Optional: LDAP Configuration (disabled by default)
|
||||
- SEMAPHORE_LDAP_ENABLED=${SEMAPHORE_LDAP_ENABLED:-false}
|
||||
# Optional: Webhook Configuration
|
||||
- SEMAPHORE_WEBHOOK_URL=${SEMAPHORE_WEBHOOK_URL:-}
|
||||
volumes:
|
||||
- semaphore-data:/etc/semaphore
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
semaphore-mysql-data:
|
||||
name: semaphore-mysql-data
|
||||
semaphore-data:
|
||||
name: semaphore-data
|
||||
|
||||
networks:
|
||||
semaphore-internal:
|
||||
name: semaphore-internal
|
||||
driver: bridge
|
||||
|
||||
51
deployment/stacks/semaphore/env.example
Normal file
51
deployment/stacks/semaphore/env.example
Normal file
@@ -0,0 +1,51 @@
|
||||
# Semaphore CI Stack - Environment Configuration
|
||||
# Copy this file to .env and adjust values as needed
|
||||
# Note: Rename this file to .env.example if you prefer the standard naming
|
||||
|
||||
# ============================================
|
||||
# MySQL Database Configuration
|
||||
# ============================================
|
||||
MYSQL_ROOT_PASSWORD=semaphore_root
|
||||
MYSQL_DATABASE=semaphore
|
||||
MYSQL_USER=semaphore
|
||||
MYSQL_PASSWORD=semaphore
|
||||
|
||||
# ============================================
|
||||
# Semaphore Configuration
|
||||
# ============================================
|
||||
|
||||
# Port binding (default: 3001)
|
||||
# Only accessible via localhost (127.0.0.1)
|
||||
# Note: Changed from 3000 to avoid conflict with Gitea
|
||||
SEMAPHORE_PORT=3001
|
||||
|
||||
# Admin User Configuration
|
||||
SEMAPHORE_ADMIN=admin
|
||||
SEMAPHORE_ADMIN_NAME=Administrator
|
||||
SEMAPHORE_ADMIN_EMAIL=admin@localhost
|
||||
SEMAPHORE_ADMIN_PASSWORD=admin
|
||||
|
||||
# Playbook Storage Path (inside container)
|
||||
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
|
||||
|
||||
# Access Key Encryption
|
||||
# Generate with: head -c32 /dev/urandom | base64
|
||||
# IMPORTANT: Change this in production!
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
|
||||
|
||||
# ============================================
|
||||
# Optional: LDAP Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_LDAP_ENABLED=false
|
||||
# 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)
|
||||
|
||||
# ============================================
|
||||
# Optional: Webhook Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
|
||||
|
||||
Reference in New Issue
Block a user