nginx try_files, proxy_pass und Upstream

Lesezeit: 5 Minuten

Ich baue eine dockerisierte Testplattform für PHP-Apps – speziell (im Moment) für WordPress. Ich verwende PHPFarm, um verschiedene Versionen von PHP auf verschiedenen Ports bereitzustellen. Mit nginx vorne habe ich viel davon funktioniert. ( https://github.com/richardtape/testit ist das Hauptrepo)

Das große Problem, mit dem ich jetzt konfrontiert bin, ist, die „hübschen Permalinks“ von WordPress zum Laufen zu bringen. In einem Standard-Nginx-Setup handelt es sich nur um etwas wie

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}

Aber um schöne URLs vom Host-Computer haben zu können und um eine Codebasis zu haben, verwende ich etwas in der folgenden Richtung:

server {
    listen 80;
    index index.php index.html index.htm;
    server_name 52.spaces.dev;

    location / {

        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    root /var/www;
}

upstream phpfarm_52{
    server phpfarm:8052;
}

Das funktioniert so wie es aussieht. (Es gibt 5 weitere ähnliche Regeln für PHP 5.3, 5.4, 5.5, 5.6 und 7) Die Homepage wird auf jedem der verschiedenen server_names von der Hostmaschine geladen (und wenn Sie die PHP-Version auf jedem von ihnen ausgeben, können Sie sehen Sie, dass Sie eine andere PHP-Version erhalten).

Beim zweiten Mal wechsle ich jedoch zu einer „internen“ URL (oder einer beliebigen Nicht-Root-URL, dh http://52.spaces.dev/about/), erhalte ich eine 404. Ich habe etwas Ähnliches versucht

location / {
    try_files $uri $uri/ /index.php?$args
}

location ~ \.php$ {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

Ich erhalte eine Umleitungsschleife, abhängig von ein paar verschiedenen Möglichkeiten, die ich ausprobiert habe, war es entweder nur eine Reihe von 301-Umleitungen und die Seite wird nie geladen oder ein Fehler wie z

nginx_1      | 2016/04/08 20:31:29 [error] 5#5: *4 rewrite or internal redirection cycle while processing "/index.php", client: 192.168.99.1, server: 52.spaces.dev, request: "GET /favicon.ico HTTP/1.1", host: "52.spaces.dev", referrer: "http://52.spaces.dev/"

Ich stecke fest. Ich bin auch ziemlich neu in der nginx-Konfiguration (was offensichtlich sein mag), also mache ich vielleicht etwas völlig falsch und/oder dumm. Irgendwelche Vorschläge?

  • Was passiert, wenn Sie phpfarm:8052/about innerhalb der Instanz curlen? (Im Grunde macht das Ihr anfänglicher Proxy_pass). Wenn Sie auch 404 erhalten, welchen Aufruf an den Upstream würden Sie stattdessen erwarten?

    – Geschichtenerzähler

    11. April 2016 um 11:47 Uhr


  • Das selbst sollte ein 404 sein, aber soweit ich es verstehe, ist das try_files $uri $uri/ /index.php?$args bedeutet, dass es schließlich auf die index.php (mit entsprechenden Argumenten) zurückgreifen sollte, was kein 404 wäre (wie die Tatsache zeigt, dass die Homepage funktioniert). Wenn ich die ‘hübschen’ Permalinks deaktiviert lasse, (dh alles läuft über die index.php) dann funktioniert es wie erwartet.

    – RichardTape

    11. April 2016 um 15:56 Uhr

Benutzeravatar von taleodor
taleodor

Das Problem, das Sie mit der Umleitungsschleife in Ihrer Frage haben, ist, dass im Grunde jede Anfrage, auch für statische Dateien, versucht, über Ihren index.php?$args-Block zu leiten.

Ich sehe hier 2 mögliche Lösungen. Wenn Sie bereit sind, das nginx-Setup mit einer einzelnen nginx-Instanz zu implementieren, sehen Sie sich zunächst diesen Thread an: NGINX try_files mit mehreren benannten Speicherorten und diesen Blogbeitrag http://linuxplayer.org/2013/06/nginx-try-files-on-multiple-named-location-or-server

Was passieren muss, ist, dass Sie zuerst testen müssen, ob die Ressource im Upstream vorhanden ist, wie sie ist (dh nicht 404 zurückgibt). Wenn dies der Fall ist, servieren Sie es so, wie es ist. Wenn dies nicht der Fall ist, rufen Sie den Rewrite-Block auf, der versucht, ihn als Parameter in index.php einzufügen. Sie würden also so etwas bekommen (sorry, ich habe nicht wirklich die Möglichkeit, das zu testen, aber hoffentlich gibt es eine Idee):

location / {
    try_files $uri $uri/ @phpproxy;
}

location @phpproxy {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @rewrite_proxy;
}

location @rewrite_proxy {
    rewrite ^/(.*)$ /index.php?$1 break;
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

Die zweite Lösung (die ich persönlich bevorzugen würde) besteht darin, jedem Upstream ein eigenes Nginx voranzustellen. Dann wird die oberste Nginx, die allen anderen vorangeht, eine viel sauberere Struktur mit einfachen Proxy_Passs (+ vielleicht etwas statischem Inhalt) haben und das war’s. Es wird auch den Request-Roundtrip reduzieren, da Sie 404-Fehler, die von den Upstreams kommen, nicht auflösen müssten.

  • Zunächst, Pavel, vielen Dank, dass Sie sich die Zeit genommen haben. Zweitens verstehe ich tatsächlich, was du sagst (das ändert sich, haha). Ich habe versucht, was Sie oben haben (es fehlt eine ; in Zeile 2), aber jetzt lädt jede Seite (einschließlich der Homepage), die bedient wird, die Datei index.php herunter, anstatt sie auszuführen. Ich vermute, dass wir damit fast am Ziel sind.

    – RichardTape

    11. April 2016 um 22:08 Uhr

  • Semikolon korrigiert 😉 Wenn es die Datei herunterlädt, bedeutet das, dass entweder der Inhaltstyp nicht richtig übergeben wird, oder ich etwas mit der Rewrite-Zeile durcheinander gebracht habe (ich bin mir nicht sicher, wie es heutzutage für WordPress sein soll), oder beide. Aber das Spielen mit diesen sollte es lösen. Ich hoffe es hilft.

    – Geschichtenerzähler

    11. April 2016 um 22:50 Uhr

  • Nochmals vielen Dank für Ihre bisherige Hilfe. Ich habe versucht hinzuzufügen default_type (und proxy_set_header content-type) Anwendung/Oktett-Stream sein, aber keine Würfel, da. ich denken Es könnte daran liegen, dass der Container, auf dem nginx installiert ist, PHP nicht ist, also das try_files Zeile für den Root-Location-Block sieht die Datei index.php und lädt sie einfach herunter. Würde das einen Unterschied machen? Ich habe versucht, einen .php-Standortblock hinzuzufügen, bekomme aber immer wieder Umleitungsschleifen. Der aktuelle Stand der conf-Datei ist: gist.github.com/richardtape/9a84e5de6f09d14a1ff8b92449ba96b0

    – RichardTape

    13. April 2016 um 18:26 Uhr

  • Der obige Code ist also korrekt (kann einige Optimierungen für die Behandlung von Umschreibungen usw. erfordern), aber das Problem liegt am Ende von PHPFarm/Apache und der Behandlung der Umschreibungen

    – Lächeln

    13. April 2016 um 22:12 Uhr

  • Hi Richard, habe noch einmal einen Blick auf deine Konfiguration geworfen, und anscheinend haben deine phpfarm-Knoten Apache vor sich. Haben Sie stattdessen versucht, Permalinks mit Apache aufzulösen, was meiner zweiten Lösung entsprechen würde, bei der nginx zu einem sauberen Reverse-Proxy würde? codex.wordpress.org/Using_Permalinks

    – Geschichtenerzähler

    15. April 2016 um 19:59 Uhr

1402930cookie-checknginx try_files, proxy_pass und Upstream

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy