nginx try_files, proxy_pass y upstream

6 minutos de lectura

Estoy construyendo una ‘plataforma’ de prueba dockerizada para aplicaciones PHP, específicamente (por el momento) para WordPress. Estoy usando PHPFarm para servir diferentes versiones de PHP en diferentes puertos. Usando nginx en el frente, tengo mucho de eso funcionando. ( https://github.com/richardtape/testit es el repositorio principal)

El gran problema al que me enfrento ahora es hacer que los “bonitos enlaces permanentes” de WordPress funcionen. En una configuración estándar de nginx, es solo un caso de algo como

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

Pero para poder tener buenas direcciones URL de la máquina host, y para tener una base de código, estoy usando algo como lo siguiente:

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;
}

Esto, tal como está, funciona. (Hay 5 reglas más similares para PHP 5.3, 5.4, 5.5, 5.6 y 7) La página de inicio se carga en cada uno de los diferentes nombres_de_servidor de la máquina host (y si genera la versión de PHP en cada uno de ellos, puede vea que está obteniendo una versión de PHP diferente).

Sin embargo, el segundo cambio a una URL ‘interna’ (o cualquier no raíz, es decir, http://52.spaces.dev/about/), obtengo un 404. He intentado algo similar a

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;
}

Obtengo un ciclo de redireccionamiento, dependiendo de algunas formas diferentes en que lo intenté, solo ha sido una serie de redireccionamientos 301 y la página nunca se carga o un error como

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/"

Estoy atascado. También soy bastante nuevo en la configuración de nginx (que puede ser obvio), por lo que podría estar haciendo algo completamente incorrecto y/o tonto. ¿Alguna sugerencia?

  • ¿Qué sucede cuando curvas phpfarm:8052/about desde dentro de la instancia? (Básicamente, eso es lo que hace su proxy_pass inicial). Si también obtiene 404, ¿qué llamada al upstream esperaría en su lugar?

    – cuento de hadas

    11 de abril de 2016 a las 11:47


  • Eso en sí debería ser un 404, pero hasta donde yo lo entiendo, el try_files $uri $uri/ /index.php?$args significa que eventualmente debería volver a index.php (con los argumentos apropiados) que no sería un 404 (como lo demuestra el hecho de que la página de inicio funciona). Si dejo los enlaces permanentes ‘bonitos’ deshabilitados (es decir, todo se ejecuta a través de index.php), entonces funciona como se esperaba.

    – RichardTape

    11 de abril de 2016 a las 15:56

avatar de usuario
cuento de hadas

El problema que está experimentando con el ciclo de redireccionamiento en su pregunta es que básicamente cada solicitud, incluso para archivos estáticos, intenta enrutar a través de su bloque index.php?$args.

Veo 2 posibles soluciones aquí. Primero, si está dispuesto a implementar la configuración de nginx con una sola instancia de nginx, consulte este hilo: NGINX try_files con varias ubicaciones con nombre y esta publicación de blog http://linuxplayer.org/2013/06/nginx-try-files-on-multiple-named-ubication-or-server

Lo que debe suceder es que primero debe probar si el recurso está presente en el flujo ascendente tal como está (es decir, no devuelve 404). Si lo hace, entonces lo sirves como está. Si no es así, estaría llamando al bloque de reescritura que intenta ponerlo como parámetro en index.php. Entonces terminarías con algo como esto (lo siento, realmente no tengo la oportunidad de probar esto, pero espero que te dé una idea):

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;
}

La segunda solución (que personalmente preferiría) es hacer frente a cada upstream con su propio nginx. Luego, el nginx superior que está al frente de todos los demás tendrá una estructura mucho más limpia con proxy_pass simples (+ tal vez algo de contenido estático) y eso es todo. También reducirá el viaje de ida y vuelta de la solicitud, ya que no necesitaría resolver los 404 provenientes de la parte superior.

  • Primero, Pavel, muchas gracias por tomarte el tiempo. En segundo lugar, entiendo lo que dices (eso hace un cambio, jaja). Intenté lo que tienes arriba (falta un ; en la línea 2), pero ahora cualquier página (incluida la página de inicio) descarga el archivo index.php en lugar de ejecutarlo. Sospecho que ya casi llegamos a esto.

    – RichardTape

    11 de abril de 2016 a las 22:08

  • Se arregló el punto y coma 😉 Si descarga el archivo, significa que el tipo de contenido no se pasó correctamente, o estropeé algo con la línea de reescritura (no estoy seguro de cómo se supone que debe ser para wordpress en estos días), o ambas cosas. Pero jugar con esos debería resolverlo. Espero eso ayude.

    – cuento de hadas

    11/04/2016 a las 22:50

  • Nuevamente, muchas gracias por su ayuda hasta ahora. He intentado agregar default_type (y proxy_set_header content-type) para ser application/octet-stream pero no dice, allí. yo pensar podría deberse a que el contenedor en el que está instalado nginx, PHP no lo está, por lo que el try_files La línea para el bloque de ubicación raíz está viendo el archivo index.php y simplemente descargándolo. ¿Haría eso una diferencia? Intenté agregar un bloque de ubicación .php, pero seguí recibiendo bucles de redirección. El estado actual del archivo conf es: gist.github.com/richardtape/9a84e5de6f09d14a1ff8b92449ba96b0

    – RichardTape

    13 de abril de 2016 a las 18:26

  • Entonces, el código anterior es correcto (puede necesitar algunos ajustes para el manejo de reescritura, etc.), pero el problema está en el final de PHPFarm/Apache y el manejo de las reescrituras.

    – sMyles

    13 de abril de 2016 a las 22:12

  • Hola Richard, eché otro vistazo a tu configuración y aparentemente tus nodos de phpfarm tienen Apache delante de ellos. ¿Intentó resolver los enlaces permanentes usando Apache, lo que sería equivalente a mi segunda solución donde nginx se convertiría en un proxy inverso limpio? codex.wordpress.org/Using_Permalinks

    – cuento de hadas

    15/04/2016 a las 19:59

¿Ha sido útil esta solución?