Nach einem Update auf Coolify v4.0.0-beta kann es passieren, dass alle Projekte plötzlich nicht mehr über ihre Domains erreichbar sind. Im Browser erscheint nur noch „404 Not Found“, obwohl alle Container laufen. In dieser Anleitung zeige ich Schritt für Schritt, wie du das Problem erkennst, verstehst und mit einem eigenen Traefik-Workaround sauber reparierst – inklusive eines Bash-Skripts, das die Konfiguration automatisch für alle Projekte erzeugt.

Ausgangslage und Symptome

Typische Anzeichen für das Problem:

  • Coolify selbst (z. B. cool.deinedomain.tld) funktioniert.
  • Alle oder mehrere WordPress-Domains (z. B. test.mkdev.de) liefern nur noch einen 404-Fehler.
  • docker ps zeigt, dass alle WordPress-Container laufen.

Du kannst von deinem Server aus testen, ob Traefik deine Domain kennt:

curl -I -H "Host: test.mkdev.de" http://127.0.0.1 

Wenn hier nur Folgendes zurückkommt:

HTTP/1.1 404 Not Found Content-Type: text/plain; charset=utf-8 

dann bedeutet das: Der Request landet beim Traefik-Proxy, aber Traefik hat keine Router-Regel für diese Domain. WordPress wird gar nicht erst erreicht.

Prüfen, ob WordPress im Container korrekt läuft

Bevor wir an Traefik drehen, sollten wir sicherstellen, dass WordPress selbst funktioniert.

  1. Öffne in Coolify das entsprechende Projekt.
  2. Gehe zum WordPress-Service (z. B. wordpress-…).
  3. Öffne dort das Terminal (Shell im Container).

Im Container:

curl -I http://localhost/ 

Wenn WordPress korrekt läuft, bekommst du typischerweise so etwas:

HTTP/1.1 301 Moved Permanently Server: Apache/2.4.65 (Debian) X-Powered-By: PHP/8.2.x X-Redirect-By: WordPress Location: http://test.mkdev.de.de/ 

Das heißt: PHP, Apache und WordPress funktionieren. Das Problem liegt eindeutig davor, im Routing (Coolify/Traefik).

Manuelle Lösung für eine einzelne Domain (Beispiel mk26.mkdai.de)

Coolify startet Traefik so, dass es zusätzliche Konfigurationsdateien aus einem Ordner einliest. Diese können wir nutzen, um das Routing zu reparieren, ohne in Coolify selbst herumzupfuschen.

Traefik lädt dynamische Konfiguration aus:

/data/coolify/proxy/dynamic/ 

Dort legen wir für jede Domain eine eigene YAML-Datei an, die Traefik erklärt: „Wenn Host = test.mkdev.de, leite auf diesen WordPress-Container weiter“.

Schritt 1: WordPress-Container und Domain ermitteln

Auf deinem Server:

docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Labels}}" | grep wordpress 

Du siehst dann z. B.:

wordpress:php8.2-apache wordpress-t8sc0owwwgg48cg810wkc4ck ... coolify.resourceName=test ... 

Wichtige Informationen:

  • Container-Name: wordpress-t8sc0owwwgg48cg810wkc4ck
  • Domain: test.mkdev.de

Schritt 2: YAML-Datei für Traefik anlegen

Erstelle den Dynamic-Ordner (falls nicht vorhanden) und eine Datei für deine Domain:

sudo mkdir -p /data/coolify/proxy/dynamic sudo nano /data/coolify/proxy/dynamic/test.yml 

Inhalt (Domain und Container-Name anpassen):

http: routers: test-router: rule: Host(`test.mkdev.de`) entryPoints: - http - https service: test-service tls: certResolver: letsencrypt services: test-service: loadBalancer: servers: - url: "http://wordpress-t8sc0owwwgg48cg810wkc4ck:80" 

Erklärung:

  • test-router ist ein beliebiger Name für diese Route.
  • Host(`test.mkdev.de`) sagt Traefik: diese Route gilt für diese Domain.
  • entryPoints: http, https entspricht den EntryPoints, die Coolify für Traefik konfiguriert.
  • test-service ist der Name des internen Services.
  • url: "http://wordpress-t8sc0owwwgg48cg810wkc4ck:80" zeigt auf den WordPress-Container im Docker-Netzwerk.

Schritt 3: Traefik neu starten und testen

Traefik neu starten, damit die neue Konfiguration sicher eingelesen wird:

docker restart coolify-proxy 

Dann wieder vom Server testen:

curl -I -H "Host: test.mkdev.de" http://127.0.0.1 

Jetzt solltest du keinen 404 mehr sehen, sondern z. B.:

HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Server: Apache/2.4.65 (Debian) X-Powered-By: PHP/8.2.29 

Damit ist die Domain wieder korrekt auf deinen WordPress-Container geroutet.

Automatischer Workaround für alle Coolify-Services

Wenn du viele Projekte hast, ist es mühsam, für jede Domain eine YAML-Datei per Hand anzulegen. Genau dafür ist das folgende Bash-Script gedacht. Es sucht alle von Coolify verwalteten Container, liest deren SERVICE_URL_*-Variable aus, extrahiert die Domain und erzeugt automatisch passende Traefik-Dynamic-Files.

Wichtig:

  • Es ändert nichts an WordPress, Datenbanken oder Volumes.
  • Es erzeugt nur zusätzliche YAML-Dateien unter /data/coolify/proxy/dynamic/.
  • Wenn Coolify den Bug später fixt, kannst du diese Dateien einfach löschen.

Script: coolify-traefik-fix.sh

Lege das Script unter /usr/local/bin an:

sudo nano /usr/local/bin/coolify-traefik-fix.sh 

Inhalt des Scripts:

#!/usr/bin/env bash
#
# coolify-traefik-fix.sh
# Erzeugt Traefik-Dynamic-Files für von Coolify verwaltete Services,
# basierend auf SERVICE_URL_* und Container-Infos.
#
# Voraussetzungen:
#   - docker
#   - jq (sudo apt install jq)
#
# Traefik liest die Dateien aus /data/coolify/proxy/dynamic/*.yml
# und routet Domains direkt auf die jeweiligen Container.

set -euo pipefail

DYNAMIC_DIR="/data/coolify/proxy/dynamic"

echo ">>> Erzeuge Traefik-Dynamic-Files in: $DYNAMIC_DIR"
sudo mkdir -p "$DYNAMIC_DIR"

# Hilfsfunktion: Domain aus einem SERVICE_URL_*-Wert extrahieren
extract_domain() {
  local value="$1"
  # Alles vor dem ersten '://' weg
  value="${value#*://}"
  # Falls das Muster wie 'foo://bar' ist, nochmal
  value="${value#*://}"
  # Alles nach dem ersten '/' weg
  value="${value%%/*}"
  echo "$value"
}

# Hilfsfunktion: ersten exponierten Port ermitteln (oder 80)
extract_port() {
  local cid="$1"
  local port
  port=$(docker inspect "$cid" \
    | jq -r '.[0].Config.ExposedPorts
             | keys[]? 
             | split("/")[0]' \
    | head -n1)

  if [[ -z "$port" || "$port" == "null" ]]; then
    port="80"
  fi
  echo "$port"
}

# Alle von Coolify verwalteten Container durchgehen
container_ids=$(docker ps --filter "label=coolify.managed=true" --format '{{.ID}}')

if [[ -z "$container_ids" ]]; then
  echo ">>> Keine von Coolify verwalteten Container gefunden."
  exit 0
fi

for cid in $container_ids; do
  name=$(docker inspect -f '{{.Name}}' "$cid" | sed 's#^/##')
  echo ">>> Prüfe Container: $name ($cid)"

  # SERVICE_URL_* aus den Env-Variablen holen
  env_line=$(docker inspect "$cid" \
    | jq -r '.[0].Config.Env[]
             | select(startswith("SERVICE_URL_"))' \
    | head -n1 || true)

  if [[ -z "$env_line" ]]; then
    echo "    -> Keine SERVICE_URL_* Variable gefunden, überspringe."
    continue
  fi

  value="${env_line#*=}"
  domain="$(extract_domain "$value")"

  if [[ -z "$domain" ]]; then
    echo "    -> Konnte aus SERVICE_URL_* keine Domain extrahieren, überspringe."
    continue
  fi

  port="$(extract_port "$cid")"

  # Router/Service-Namen aus Domain ableiten
  router_name="${domain//./-}-router"
  service_name="${domain//./-}-service"
  file_path="$DYNAMIC_DIR/${domain}.yml"

  echo "    -> SERVICE_URL_*: $value"
  echo "    -> Domain:        $domain"
  echo "    -> Port:          $port"
  echo "    -> Datei:         $file_path"

  # YAML-Datei schreiben
  sudo bash -c "cat > '$file_path' <<EOF
http:
  routers:
    $router_name:
      rule: Host(\`$domain\`)
      entryPoints:
        - http
        - https
      service: $service_name
  services:
    $service_name:
      loadBalancer:
        servers:
          - url: \"http://$name:$port\"
EOF
"
done

echo ">>> Fertig. Starte Traefik neu, damit die Config sicher geladen wird:"
echo "    docker restart coolify-proxy"

Voraussetzungen für das Script

Stelle sicher, dass jq installiert ist, da das Script JSON-Ausgaben von Docker auswertet:

sudo apt update sudo apt install -y jq 

Script ausführbar machen:

sudo chmod +x /usr/local/bin/coolify-traefik-fix.sh 

Script ausführen und Routing reparieren

Führe das Script aus:

sudo /usr/local/bin/coolify-traefik-fix.sh 

Anschließend Traefik neu starten, damit die neuen Dateien eingelesen werden:

docker restart coolify-proxy 

Jetzt kannst du für eine Domain testen:

curl -I -H "Host: test.mkdev.de" http://127.0.0.1 

Wenn du hier eine Antwort von Apache/WordPress (200 oder 301) siehst, ist das Routing für diese Domain wiederhergestellt. Das gilt dann für alle Domains, die das Script aus SERVICE_URL_* ableiten konnte.

Aufräumen nach einem offiziellen Coolify-Fix

Wenn Coolify in einer späteren Version den Domain-/Routing-Bug behebt, kannst du den Workaround sauber wieder entfernen:

  1. Update auf die korrigierte Coolify-Version durchführen.
  2. Testen, ob neue Deploys und Domain-Zuweisungen in der Coolify-Oberfläche wieder von alleine funktionieren.
  3. Falls ja: die erzeugten Dateien entfernen:
sudo rm /data/coolify/proxy/dynamic/*.yml docker restart coolify-proxy 

Damit übernimmt Coolify wieder vollständig das Traefik-Routing, ohne dass deine WordPress-Container oder Datenbanken angefasst werden müssen.