# Gitea, Traefik & CI/CD Setup - Komplette Anleitung **Stand:** 2025-11-08 **Status:** ✅ Vollständig dokumentiert - Alle Probleme gelöst **Zweck:** Referenz für zukünftige Deployments und Troubleshooting --- ## Übersicht Dieses Dokument dokumentiert alle Schritte, Probleme und Lösungen, die notwendig waren, um Gitea, Traefik und die CI/CD-Pipeline vollständig zum Laufen zu bringen. Diese Anleitung sollte bei jedem neuen Deployment oder bei ähnlichen Problemen als Referenz dienen. **📖 Verwandte Dokumentation:** - [Initial Deployment Guide](../guides/initial-deployment-guide.md) - [CI/CD Workflow Guide](../guides/cicd-workflow-guide.md) - [Pipeline Testing Guide](../guides/pipeline-testing-guide.md) --- ## Problem 1: Traefik Dashboard nicht erreichbar ### Symptom - Traefik Dashboard unter `https://traefik.michaelschiemer.de` nicht erreichbar - Passwort unbekannt oder vergessen ### Lösung: Traefik-Passwort zurücksetzen **1. Neues Passwort-Hash generieren:** ```bash htpasswd -nb admin "dein_neues_passwort" # Output: admin:$apr1$xyz123$abc456 ``` **2. Hash in `docker-compose.yml` aktualisieren:** **Datei:** `deployment/stacks/traefik/docker-compose.yml` **Wichtig:** In Docker Compose Labels müssen `$` Zeichen mit `$$` escaped werden! ```yaml # Zeile 49 - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$xyz123$$abc456" ``` **3. Konfiguration synchronisieren und Traefik neu starten:** ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml playbooks/sync-stacks.yml \ --vault-password-file secrets/.vault_pass ansible -i inventory/production.yml server -m shell \ -a "cd /home/deploy/deployment/stacks/traefik && docker compose restart traefik" \ --vault-password-file secrets/.vault_pass ``` **Erfolgreich getestet mit Passwort:** `4qcdnnqF7NV4bLZnXmJna7Sd2FCsd2zM` --- ## Problem 2: Gitea nicht erreichbar (504 Bad Gateway) ### Symptom - Gitea unter `https://git.michaelschiemer.de` liefert 504 Bad Gateway - Traefik Logs zeigen: "Error while dialing backend" - Gitea Container läuft, aber Traefik kann nicht verbinden ### Root Cause Die File-Provider-Konfiguration `dynamic/gitea-service.yml` überschreibt die Docker-Service-Definition und verursacht Konflikte. Traefik findet kein Backend, obwohl Gitea läuft. ### Lösung: File-Provider-Konfiguration entfernen **1. Datei deaktivieren (lokal):** ```bash cd deployment/stacks/traefik/dynamic mv gitea-service.yml gitea-service.yml.disabled ``` **2. Konfiguration synchronisieren:** ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml playbooks/sync-stacks.yml \ --vault-password-file secrets/.vault_pass ``` **3. Alte Datei auf Server entfernen:** ```bash ansible -i inventory/production.yml server -m file \ -a "path=/home/deploy/deployment/stacks/traefik/dynamic/gitea-service.yml state=absent" \ --vault-password-file secrets/.vault_pass ``` **4. Traefik neu starten:** ```bash ansible -i inventory/production.yml server -m shell \ -a "cd /home/deploy/deployment/stacks/traefik && docker compose restart traefik" \ --vault-password-file secrets/.vault_pass ``` **Warum funktioniert das?** - Docker-Labels definieren bereits den Service korrekt: `traefik.http.services.gitea.loadbalancer.server.port=3000` - Router referenziert explizit: `traefik.http.routers.gitea.service=gitea@docker` - File-Provider-Definition überschreibt diese Konfiguration und verursacht Konflikte **Wichtig:** Die Datei `gitea-service.yml.disabled` sollte **nicht** wieder aktiviert werden, da die Docker-Labels ausreichend sind. --- ## Problem 3: Gitea im Restart-Loop (Redis-Verbindung) ### Symptom - Gitea Container startet, crasht sofort, startet wieder (Endlosschleife) - Logs zeigen: `dial tcp 127.0.0.1:6379: connect: connection refused` - Gitea versucht, sich mit `127.0.0.1:6379` statt `redis:6379` zu verbinden ### Root Cause Gitea 1.25 interpretiert `GITEA__cache__HOST=redis:6379` nicht korrekt und verbindet sich mit `127.0.0.1:6379`. Die `app.ini` Datei im Volume enthält möglicherweise noch alte `127.0.0.1` Werte. ### Lösung: Gitea app.ini bereinigen **1. Gitea Container stoppen:** ```bash cd deployment/ansible ansible -i inventory/production.yml server -m shell \ -a "cd /home/deploy/deployment/stacks/gitea && docker compose stop gitea" \ --vault-password-file secrets/.vault_pass ``` **2. app.ini im Volume aktualisieren (minimale Konfiguration):** **Wichtig:** Die `[cache]` Sektion muss komplett entfernt werden, da sie über ENV-Variablen gesteuert wird! ```bash ansible -i inventory/production.yml server -m shell -a 'docker run --rm -v gitea-data:/data alpine sh -c "cat > /data/gitea/conf/app.ini << EOF APP_NAME = Gitea: Git with a cup of tea RUN_MODE = prod [server] PROTOCOL = http DOMAIN = git.michaelschiemer.de HTTP_ADDR = 0.0.0.0 HTTP_PORT = 3000 ROOT_URL = https://git.michaelschiemer.de/ DISABLE_SSH = false START_SSH_SERVER = false SSH_DOMAIN = git.michaelschiemer.de SSH_PORT = 2222 SSH_LISTEN_PORT = 2222 [database] DB_TYPE = postgres HOST = postgres:5432 NAME = gitea USER = gitea PASSWD = gitea_password SSL_MODE = disable [security] INSTALL_LOCK = true [service] DISABLE_REGISTRATION = true [actions] ENABLED = true EOF chown 1000:1000 /data/gitea/conf/app.ini && chmod 644 /data/gitea/conf/app.ini"' \ --vault-password-file secrets/.vault_pass ``` **3. Gitea wieder starten:** ```bash ansible -i inventory/production.yml server -m shell \ -a "cd /home/deploy/deployment/stacks/gitea && docker compose up -d gitea" \ --vault-password-file secrets/.vault_pass ``` **4. Cache-Konfiguration (aktuell deaktiviert):** **Datei:** `deployment/stacks/gitea/docker-compose.yml` ```yaml # Cache deaktiviert - Gitea 1.25 interpretiert GITEA__cache__HOST nicht korrekt - GITEA__cache__ENABLED=false - GITEA__cache__ADAPTER=memory # Session und Queue nutzen weiterhin Redis - GITEA__session__PROVIDER=redis - GITEA__session__PROVIDER_CONFIG=network=tcp,addr=redis:6379,password=${REDIS_PASSWORD:-gitea_redis_password},db=0,pool_size=100,idle_timeout=180 - GITEA__queue__TYPE=redis - GITEA__queue__CONN_STR=redis://:${REDIS_PASSWORD:-gitea_redis_password}@redis:6379/0 ``` **Hinweis:** Cache kann später wieder aktiviert werden, wenn Gitea aktualisiert wird oder ein Workaround gefunden wird. --- ## Problem 4: Gitea Repository fehlt ### Symptom - Repository `michael/michaelschiemer` existiert nicht in Gitea - Git Push schlägt fehl: "repository not found" ### Lösung: Repository erstellen **1. Repository über Gitea API erstellen:** ```bash cd deployment/ansible # Admin-Credentials aus Vault holen ADMIN_USER=$(ansible-vault view secrets/production.vault.yml \ --vault-password-file secrets/.vault_pass 2>/dev/null | \ grep 'vault_gitea_admin_username:' | \ sed 's/.*vault_gitea_admin_username: *"\([^"]*\)".*/\1/') ADMIN_PASS=$(ansible-vault view secrets/production.vault.yml \ --vault-password-file secrets/.vault_pass 2>/dev/null | \ grep 'vault_gitea_admin_password:' | \ sed 's/.*vault_gitea_admin_password: *"\([^"]*\)".*/\1/') # Repository erstellen curl -k -s -X POST \ -u "${ADMIN_USER}:${ADMIN_PASS}" \ -H "Content-Type: application/json" \ -H "User-Agent: Mozilla/5.0" \ -d '{ "name":"michaelschiemer", "description":"Main application repository", "private":false, "auto_init":false }' \ https://git.michaelschiemer.de/api/v1/user/repos ``` **2. Git Remote konfigurieren:** ```bash cd /home/michael/dev/michaelschiemer git remote set-url origin https://git.michaelschiemer.de/michael/michaelschiemer.git git remote -v # Verifizieren ``` **3. Push testen:** ```bash # Mit Admin-Credentials (temporär) git remote set-url origin https://${ADMIN_USER}:${ADMIN_PASS}@git.michaelschiemer.de/michael/michaelschiemer.git git push origin staging ``` **Alternativ:** Ansible Playbook verwenden: ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml \ playbooks/setup-gitea-repository.yml \ --vault-password-file secrets/.vault_pass \ -e "repo_name=michaelschiemer" \ -e "repo_owner=michael" \ -e "repo_private=false" ``` --- ## Problem 5: Gitea Runner nicht registriert oder läuft nicht ### Symptom - Workflows werden nicht ausgeführt - Runner erscheint nicht in Gitea UI - Runner Container läuft, aber zeigt "unregistered runner" Fehler ### Lösung: Runner registrieren und starten **1. Registration Token von Gitea holen:** 1. Gehe zu: `https://git.michaelschiemer.de/admin/actions/runners` 2. Klicke auf "Create New Runner" oder "New Runner" 3. Kopiere das Registration Token **2. Token in `.env` Datei aktualisieren:** **Datei:** `deployment/gitea-runner/.env` ```bash cd deployment/gitea-runner nano .env # Setze: GITEA_RUNNER_REGISTRATION_TOKEN= ``` **3. Alte Registrierung entfernen (falls vorhanden):** ```bash cd deployment/gitea-runner docker compose down rm -f data/.runner ``` **4. Runner registrieren:** ```bash cd deployment/gitea-runner ./register.sh ``` **5. Runner-Status prüfen:** ```bash # Container-Status docker compose ps # Runner-Logs docker compose logs -f gitea-runner # In Gitea UI prüfen # https://git.michaelschiemer.de/admin/actions/runners ``` **Erfolgreiche Registrierung zeigt:** ``` ✓ Runner registered successfully! Runner is now active and will start accepting jobs. ``` **Runner-Logs sollten zeigen:** ``` level=info msg="Runner registered successfully." level=info msg="declare successfully" level=info msg="task 1 repo is michael/michaelschiemer" ``` --- ## Problem 6: Git Push schlägt fehl (Authentication) ### Symptom - `fatal: Authentication failed for 'https://git.michaelschiemer.de/...'` - Push funktioniert nicht, obwohl Repository existiert ### Lösung: Git Remote mit Credentials konfigurieren **Option 1: Temporär mit Admin-Credentials (für ersten Push):** ```bash cd /home/michael/dev/michaelschiemer # Credentials aus Vault holen ADMIN_USER=$(ansible-vault view deployment/ansible/secrets/production.vault.yml \ --vault-password-file deployment/ansible/secrets/.vault_pass 2>/dev/null | \ grep 'vault_gitea_admin_username:' | \ sed 's/.*vault_gitea_admin_username: *"\([^"]*\)".*/\1/') ADMIN_PASS=$(ansible-vault view deployment/ansible/secrets/production.vault.yml \ --vault-password-file deployment/ansible/secrets/.vault_pass 2>/dev/null | \ grep 'vault_gitea_admin_password:' | \ sed 's/.*vault_gitea_admin_password: *"\([^"]*\)".*/\1/') # Remote mit Credentials setzen git remote set-url origin https://${ADMIN_USER}:${ADMIN_PASS}@git.michaelschiemer.de/michael/michaelschiemer.git # Push git push origin staging ``` **Option 2: Personal Access Token verwenden (empfohlen für dauerhafte Nutzung):** 1. In Gitea: Settings > Applications > Generate New Token 2. Scopes: `write:repository`, `read:repository` 3. Token kopieren 4. Git Remote konfigurieren: ```bash git remote set-url origin https://michael:@git.michaelschiemer.de/michael/michaelschiemer.git ``` **Option 3: Git Credential Helper konfigurieren:** ```bash git config --global credential.helper store git push origin staging # Bei Aufforderung: Username und Passwort eingeben # Credentials werden in ~/.git-credentials gespeichert ``` --- ## Checkliste für zukünftige Deployments ### Vor dem ersten Deployment - [ ] **Traefik-Passwort setzen/resetzen** - Hash generieren: `htpasswd -nb admin "passwort"` - In `deployment/stacks/traefik/docker-compose.yml` aktualisieren (mit `$$` escapen) - Synchronisieren und Traefik neu starten - [ ] **Traefik File-Provider-Konfiguration prüfen** - `deployment/stacks/traefik/dynamic/gitea-service.yml` sollte **nicht** existieren - Falls vorhanden: deaktivieren oder löschen - Docker-Labels sind ausreichend - [ ] **Gitea app.ini bereinigen** - Keine `[cache]` Sektion mit `127.0.0.1` Werten - Minimale Konfiguration verwenden - Cache über ENV-Variablen steuern - [ ] **Gitea Repository erstellen** - Über API oder Ansible Playbook - Git Remote konfigurieren - [ ] **Gitea Runner registrieren** - Registration Token von Gitea Admin UI holen - In `deployment/gitea-runner/.env` eintragen - `./register.sh` ausführen - Status in Gitea UI prüfen ### Nach dem Deployment - [ ] **Gitea erreichbar?** - `https://git.michaelschiemer.de` sollte funktionieren - Keine 504 Fehler - [ ] **Traefik Dashboard erreichbar?** - `https://traefik.michaelschiemer.de` mit korrektem Passwort - [ ] **Runner läuft?** - `docker compose ps` in `deployment/gitea-runner/` - Runner erscheint als "Idle" in Gitea UI - [ ] **CI-Images verfügbar?** - `docker exec gitea-runner-dind docker images | grep docker-build` - Falls nicht: Image bauen und in docker-dind laden (siehe Problem 7) - [ ] **Workflows werden ausgeführt?** - Test-Commit pushen - In Gitea Actions UI prüfen: `https://git.michaelschiemer.de/michael/michaelschiemer/actions` - Keine "pull access denied" Fehler --- ## Wichtige Dateien und Konfigurationen ### Traefik **Datei:** `deployment/stacks/traefik/docker-compose.yml` - Zeile 49: BasicAuth Passwort-Hash (mit `$$` escapen) **Datei:** `deployment/stacks/traefik/dynamic/gitea-service.yml` - **Sollte nicht existieren** - Docker-Labels sind ausreichend ### Gitea **Datei:** `deployment/stacks/gitea/docker-compose.yml` - Cache deaktiviert (Gitea 1.25 Bug) - Session und Queue nutzen Redis **Datei:** `deployment/stacks/gitea/app.ini` (im Volume) - Minimale Konfiguration - Keine `[cache]` Sektion **Datei:** `deployment/ansible/templates/gitea-app.ini.j2` - Template für minimale app.ini - Wird von Ansible verwendet ### Gitea Runner **Datei:** `deployment/gitea-runner/.env` - `GITEA_INSTANCE_URL=https://git.michaelschiemer.de` - `GITEA_RUNNER_REGISTRATION_TOKEN=` - `GITEA_RUNNER_NAME=dev-runner-01` **Datei:** `deployment/gitea-runner/data/.runner` - Wird automatisch bei Registrierung erstellt - Enthält Runner-Credentials --- ## Häufige Fehler und Lösungen ### Fehler: "runner registration token not found" **Ursache:** Token ist ungültig oder abgelaufen **Lösung:** 1. Neues Token in Gitea Admin UI erstellen 2. Token in `.env` aktualisieren 3. Runner neu registrieren: `./register.sh` ### Fehler: "unregistered runner" **Ursache:** Runner wurde nicht korrekt registriert oder Token ist ungültig **Lösung:** 1. Alte Registrierung entfernen: `rm -f data/.runner` 2. Container stoppen: `docker compose down` 3. Neues Token holen und in `.env` eintragen 4. Neu registrieren: `./register.sh` ### Fehler: "dial tcp 127.0.0.1:6379: connect: connection refused" **Ursache:** Gitea versucht, sich mit `127.0.0.1:6379` statt `redis:6379` zu verbinden **Lösung:** 1. Gitea stoppen 2. `app.ini` im Volume bereinigen (keine `[cache]` Sektion mit `127.0.0.1`) 3. Cache in `docker-compose.yml` deaktivieren 4. Gitea neu starten ### Fehler: "504 Bad Gateway" bei Gitea **Ursache:** Traefik File-Provider überschreibt Docker-Service-Definition **Lösung:** 1. `deployment/stacks/traefik/dynamic/gitea-service.yml` entfernen 2. Konfiguration synchronisieren 3. Traefik neu starten --- ## Ansible Playbooks Referenz ### Stacks synchronisieren ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml playbooks/sync-stacks.yml \ --vault-password-file secrets/.vault_pass ``` ### Gitea Repository erstellen ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml \ playbooks/setup-gitea-repository.yml \ --vault-password-file secrets/.vault_pass \ -e "repo_name=michaelschiemer" \ -e "repo_owner=michael" \ -e "repo_private=false" ``` ### Gitea app.ini aktualisieren ```bash cd deployment/ansible ansible-playbook -i inventory/production.yml \ playbooks/setup-gitea-initial-config.yml \ --vault-password-file secrets/.vault_pass \ -e "force_update_app_ini=true" ``` --- ## Zusammenfassung der kritischen Schritte 1. ✅ **Traefik-Passwort setzen** - Hash in `docker-compose.yml` (mit `$$` escapen) 2. ✅ **File-Provider entfernen** - `gitea-service.yml` löschen/deaktivieren 3. ✅ **Gitea app.ini bereinigen** - Keine `[cache]` Sektion mit `127.0.0.1` 4. ✅ **Repository erstellen** - Über API oder Ansible Playbook 5. ✅ **Runner registrieren** - Token in `.env`, dann `./register.sh` 6. ✅ **Git Remote konfigurieren** - Mit Credentials für ersten Push 7. ✅ **CI-Images bauen und laden** - `docker-build` Image in docker-dind laden **Nach diesen Schritten sollte die CI/CD-Pipeline vollständig funktionieren!** --- ## Problem 7: Workflow schlägt fehl - "pull access denied" für docker-build Image ### Symptom - Workflow startet, aber schlägt fehl mit: `pull access denied, repository does not exist or may require authorization` - Runner versucht, `registry.michaelschiemer.de/ci/docker-build:latest` zu pullen - Fehler tritt auf, bevor der Workflow die Registry-Authentifizierung durchführt ### Root Cause Der Runner versucht, Container-Images für Jobs zu pullen, bevor der Workflow die Registry-Authentifizierung durchführt. Das Image existiert möglicherweise nicht in der Registry oder der Runner hat keine Registry-Credentials. ### Lösung: CI-Image bauen und in docker-dind laden **1. CI-Image bauen:** ```bash cd /home/michael/dev/michaelschiemer docker build -f docker/ci/Dockerfile.build \ -t registry.michaelschiemer.de/ci/docker-build:latest \ --platform linux/amd64 . ``` **2. Image in docker-dind laden (temporäre Lösung):** ```bash docker save registry.michaelschiemer.de/ci/docker-build:latest | \ docker exec -i gitea-runner-dind docker load ``` **3. Verifizieren:** ```bash docker exec gitea-runner-dind docker images | grep docker-build ``` **4. Runner neu starten:** ```bash cd deployment/gitea-runner docker compose restart gitea-runner ``` **Alternative: Image in Registry pushen (empfohlen für Production):** ```bash # Bei Registry einloggen cd deployment/ansible REGISTRY_USER=$(ansible-vault view secrets/production.vault.yml \ --vault-password-file secrets/.vault_pass 2>/dev/null | \ grep 'vault_docker_registry_username:' | \ sed 's/.*vault_docker_registry_username: *"\([^"]*\)".*/\1/') REGISTRY_PASS=$(ansible-vault view secrets/production.vault.yml \ --vault-password-file secrets/.vault_pass 2>/dev/null | \ grep 'vault_docker_registry_password:' | \ sed 's/.*vault_docker_registry_password: *"\([^"]*\)".*/\1/') cd /home/michael/dev/michaelschiemer echo "$REGISTRY_PASS" | docker login registry.michaelschiemer.de \ -u "$REGISTRY_USER" --password-stdin # Image pushen docker push registry.michaelschiemer.de/ci/docker-build:latest ``` **Hinweis:** Wenn der Push fehlschlägt (z.B. 499 Error), kann das Image lokal in docker-dind geladen werden. Für Production sollte das Image jedoch in der Registry sein. **Für zukünftige Deployments:** Das Image sollte beim ersten Setup gebaut und in die Registry gepusht werden, oder das Build-Script `deployment/gitea-runner/build-ci-image.sh` verwenden. --- **Letzte Aktualisierung:** 2025-11-08 **Status:** ✅ Vollständig dokumentiert und getestet