# Staging 502 Bad Gateway - Nginx PHP-FPM Connection Issue

## Problem

Staging-Server zeigt **502 Bad Gateway** Fehler auf `https://staging.michaelschiemer.de/`.

Nginx-Fehlerlog zeigt:
```
connect() failed (111: Connection refused) while connecting to upstream, 
client: 172.21.0.4, server: _, request: "GET / HTTP/1.1", 
upstream: "fastcgi://127.0.0.1:9000"
```

## Ursache

**Root Cause:** Nginx versucht, sich mit PHP-FPM auf `127.0.0.1:9000` (localhost) zu verbinden, aber PHP-FPM l?uft in einem **separaten Docker-Container** (`staging-app`).

### Technische Details

1. **Nginx-Konfiguration:** Es gibt zwei Nginx-Konfigurationsdateien:
   - `/etc/nginx/conf.d/default.conf` ? Korrekt: verwendet `upstream php-upstream { server staging-app:9000; }`
   - `/etc/nginx/sites-available/default` ? Falsch: verwendet `upstream php-upstream { server 127.0.0.1:9000; }`

2. **Nginx Include-Ordnung:** `nginx.conf` inkludiert:
   ```nginx
   include /etc/nginx/sites-enabled/*;  # Wird ZULETZT geladen
   include /etc/nginx/conf.d/*.conf;     # Wird ZUERST geladen
   ```
   Da `sites-enabled/default` **nach** `conf.d/default.conf` geladen wird, **?berschreibt** sie die korrekte Konfiguration.

3. **Container-Architektur:**
   - `staging-nginx` Container: L?uft Nginx
   - `staging-app` Container: L?uft PHP-FPM auf Port 9000
   - Beide Container sind im `staging-internal` Docker-Netzwerk

## L?sung

### Sofort-Fix (Manuell)

```bash
cd ~/deployment/stacks/staging

# Fix upstream in sites-available/default
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default

# Reload nginx
docker compose restart staging-nginx
```

Oder mit Ansible:
```bash
ansible-playbook -i deployment/ansible/inventory/production.yml deployment/ansible/playbooks/fix-sites-available-default.yml
```

### Permanente L?sung

Das Entrypoint-Script in `deployment/stacks/staging/docker-compose.yml` (Zeilen 181-192) wurde erweitert, um das Problem **automatisch beim Container-Start** zu beheben:

```bash
# Fix nginx upstream configuration - sites-enabled/default overrides conf.d/default.conf
if [ -f "/etc/nginx/sites-available/default" ]; then
  echo "?? [staging-nginx] Fixing PHP-FPM upstream configuration..."
  # Replace in upstream block
  sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
  sed -i '/upstream php-upstream {/,/}/s|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || true
  # Replace any direct fastcgi_pass references too
  sed -i 's|fastcgi_pass 127.0.0.1:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
  sed -i 's|fastcgi_pass localhost:9000;|fastcgi_pass php-upstream;|g' /etc/nginx/sites-available/default || true
  echo "? [staging-nginx] PHP-FPM upstream fixed"
fi
```

## Diagnose-Schritte

Wenn das Problem erneut auftritt:

### 1. Pr?fe Nginx Error Logs

```bash
cd ~/deployment/stacks/staging
docker compose logs --tail=50 staging-nginx | grep -i "502\|error\|upstream"
```

Oder direkt im Container:
```bash
docker compose exec -T staging-nginx tail -100 /var/log/nginx/error.log
```

**Erwartete Fehlermeldung bei diesem Problem:**
```
connect() failed (111: Connection refused) while connecting to upstream, 
upstream: "fastcgi://127.0.0.1:9000"
```

### 2. Pr?fe PHP-FPM Status

```bash
# Container-Status
docker compose ps staging-app staging-nginx

# PHP-FPM l?uft?
docker compose exec -T staging-app netstat -tlnp | grep 9000
# Oder:
docker compose exec -T staging-app ss -tlnp | grep 9000
```

### 3. Pr?fe Upstream-Konfiguration

```bash
# Welche upstream-Definition wird verwendet?
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/sites-available/default
docker compose exec -T staging-nginx grep -A 3 "upstream php-upstream" /etc/nginx/conf.d/default.conf

# Welche fastcgi_pass Direktiven gibt es?
docker compose exec -T staging-nginx grep "fastcgi_pass" /etc/nginx/sites-available/default
docker compose exec -T staging-nginx grep "fastcgi_pass" /etc/nginx/conf.d/default.conf
```

**Erwartetes Ergebnis (korrekt):**
```
upstream php-upstream {
    server staging-app:9000;
}
```

**Fehlerhaft (zeigt Problem):**
```
upstream php-upstream {
    server 127.0.0.1:9000;  # ? FALSCH
}
```

### 4. Teste Verbindung von Nginx zu PHP-FPM

```bash
# Kann nginx sich mit staging-app:9000 verbinden?
docker compose exec -T staging-nginx curl -v http://staging-app:9000 2>&1 | head -20

# Oder teste direkt mit FastCGI (wenn cgi-fcgi installiert ist)
docker compose exec -T staging-nginx sh -c "echo -e 'REQUEST_METHOD=GET\nSCRIPT_FILENAME=/var/www/html/public/index.php\n' | cgi-fcgi -bind -connect staging-app:9000"
```

### 5. Vollst?ndige Diagnose mit Ansible

```bash
ansible-playbook -i deployment/ansible/inventory/production.yml \
  deployment/ansible/playbooks/diagnose-staging-502.yml
```

## Verwandte Dateien

- **Docker Compose Config:** `deployment/stacks/staging/docker-compose.yml`
- **Nginx Config (korrekt):** `deployment/stacks/staging/nginx/conf.d/default.conf`
- **Nginx Config (problem):** `/etc/nginx/sites-available/default` (im Container)
- **Diagnose-Playbooks:**
  - `deployment/ansible/playbooks/diagnose-staging-502.yml`
  - `deployment/ansible/playbooks/fix-sites-available-default.yml`

## Verhindern in Zukunft

### Nach jedem Deployment

**WICHTIG:** Nach jedem Deployment (Push zu staging-Branch) muss dieser Fix ausgef?hrt werden, da die Container neu erstellt werden.

```bash
# Mit Ansible (empfohlen)
ansible-playbook -i deployment/ansible/inventory/production.yml \
  deployment/ansible/playbooks/fix-staging-502-quick.yml

# Oder manuell
cd ~/deployment/stacks/staging
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default
docker compose restart staging-nginx
```

### Langfristige L?sungen

1. **Entrypoint-Script:** Das Entrypoint-Script behebt das Problem automatisch beim Container-Start (implementiert, aber nicht 100% zuverl?ssig)
2. **Deployment-Script:** Erweitere `.gitea/workflows/build-image.yml` um einen Post-Deployment-Fix (siehe TODO unten)
3. **Image-Build:** Idealerweise sollte die `sites-available/default` Datei im Docker-Image bereits korrekt konfiguriert sein
4. **Alternativ:** Entferne `sites-available/default` komplett und verwende nur `conf.d/default.conf`

### TODO: Deployment-Script erweitern

Das Deployment-Script in `.gitea/workflows/build-image.yml` sollte nach Zeile 991 erweitert werden:

```bash
# Fix nginx upstream configuration - critical fix for 502 errors
echo "?? Fixing nginx PHP-FPM upstream configuration (post-deploy fix)..."
sleep 5
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default
docker compose exec -T staging-nginx nginx -t && docker compose restart staging-nginx
```

## Siehe auch

- [Staging Stack README](../../stacks/staging/README.md)
- [Nginx Configuration](../../stacks/staging/nginx/conf.d/default.conf)
- [Troubleshooting Overview](../README.md)
