Files
michaelschiemer/deployment/docs/troubleshooting/gitea-traefik-cicd-setup.md
Michael Schiemer 1b9cda6dd3
Some checks failed
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Failing after 40s
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
🚀 Build & Deploy Image / Determine Build Necessity (push) Successful in 46s
Security Vulnerability Scan / Check for Dependency Changes (push) Successful in 1m0s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Successful in 11s
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
Security Vulnerability Scan / Composer Security Audit (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Successful in 12s
docs: Add CI image setup documentation
2025-11-08 13:38:46 +01:00

19 KiB

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:


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:

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!

# Zeile 49
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$xyz123$$abc456"

3. Konfiguration synchronisieren und Traefik neu starten:

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):

cd deployment/stacks/traefik/dynamic
mv gitea-service.yml gitea-service.yml.disabled

2. Konfiguration synchronisieren:

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:

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:

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:

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!

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:

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

# 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:

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:

cd /home/michael/dev/michaelschiemer
git remote set-url origin https://git.michaelschiemer.de/michael/michaelschiemer.git
git remote -v  # Verifizieren

3. Push testen:

# 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:

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

cd deployment/gitea-runner
nano .env
# Setze: GITEA_RUNNER_REGISTRATION_TOKEN=<neues-token>

3. Alte Registrierung entfernen (falls vorhanden):

cd deployment/gitea-runner
docker compose down
rm -f data/.runner

4. Runner registrieren:

cd deployment/gitea-runner
./register.sh

5. Runner-Status prüfen:

# 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):

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:
git remote set-url origin https://michael:<token>@git.michaelschiemer.de/michael/michaelschiemer.git

Option 3: Git Credential Helper konfigurieren:

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=<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

cd deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/sync-stacks.yml \
  --vault-password-file secrets/.vault_pass

Gitea Repository erstellen

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

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:

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):

docker save registry.michaelschiemer.de/ci/docker-build:latest | \
  docker exec -i gitea-runner-dind docker load

3. Verifizieren:

docker exec gitea-runner-dind docker images | grep docker-build

4. Runner neu starten:

cd deployment/gitea-runner
docker compose restart gitea-runner

Alternative: Image in Registry pushen (empfohlen für Production):

# 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