Cómo servir todos los archivos estáticos existentes directamente con NGINX, pero enviar el resto a un servidor backend.

87
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    if (-f $request_filename) {
        access_log off;
        expires 30d;
        break;
        }

    if (!-f $request_filename) {
        proxy_pass http://127.0.0.1:8080; # backend server listening
        break;
        }
    }

Arriba servirá todos los archivos existentes directamente usando Nginx (por ejemplo, Nginx solo muestra el código fuente PHP), de lo contrario, reenvíe una solicitud a Apache. Necesito excluir los archivos * .php de la regla para que las solicitudes de * .php también se pasen a Apache y se procesen.

Quiero que Nginx maneje todos los archivos estáticos y que Apache procese todas las cosas dinámicas.

EDITAR: Hay un enfoque de lista blanca, pero no es muy elegante, mira todas esas extensiones, no quiero esto.

location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
    access_log off;
    expires 30d;
    }
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
    }

EDITAR 2: En versiones más nuevas de Nginx, use try_filesen su lugar http://wiki.nginx.org/HttpCoreModule#try_files

fmalina
fuente
Solo para aclarar las cosas: el código anterior servirá un archivo estático si existe en el disco, si el archivo no existe, la solicitud se pasa a Apache. Esto funciona la mayor parte del tiempo ya que todas las URL de mis aplicaciones usan mod_rewrite (o enrutamiento) y realmente no existen en el disco. Solo el acceso directo al nombre de archivo * .php es una excepción y debe ser analizado por Apache.
fmalina

Respuestas:

152

Utilice try_files y el bloque de ubicación con nombre ('@apachesite'). Esto eliminará la coincidencia de expresiones regulares innecesarias y el bloque if. Más eficiente.

location / {
    root /path/to/root/of/static/files;
    try_files $uri $uri/ @apachesite;

    expires max;
    access_log off;
}

location @apachesite {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Actualización: la suposición de esta configuración es que no existe ningún script php debajo /path/to/root/of/static/files. Esto es común en la mayoría de los frameworks php modernos. En caso de que sus proyectos php heredados tengan scripts php y archivos estáticos mezclados en la misma carpeta, es posible que deba incluir en la lista blanca todos los tipos de archivos que desea que sirva nginx.

Chuan Ma
fuente
Estoy usando wordpress, ¿debo poner la carpeta de carga en el servidor nginx?
Chameron
7
Mi problema con esta solución: nginx no usa la otra ubicación (el proxy) e intenta mostrar la lista del directorio. Entonces arroja un 403 porque la lista de directorios no está activada. Editar: Ok, si lo quitas, $uri/entonces funciona.
ChristophLSA
1
Esto sería un proxy / ejemplo para apache pero permitiría descargar /example.php.
Terence Johnson
1
@TerenceJohnson No es seguro colocar sus archivos php en la carpeta de archivos estáticos. Tenga en cuenta que configuré root /path/to/root/of/*static*/files;. Los archivos php deben colocarse en una carpeta diferente, no accesible directamente desde Internet.
Chuan Ma
2
Sé que así deberían ser las cosas, pero si alguien está poniendo Nginx delante de cualquiera de las muchas aplicaciones PHP comunes que tienen todo bajo la raíz web y dependen de archivos .htaccess, no deberían copiar y pegue su configuración.
Terence Johnson
18

Prueba esto:

location / {
    root /path/to/root;
    expires 30d;
    access_log off;
}

location ~* ^.*\.php$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Ojalá funcione. Las expresiones regulares tienen mayor prioridad que las cadenas simples, por lo que todas las solicitudes que terminan en .phpdeben reenviarse a Apache si solo .phpexiste un archivo correspondiente . El resto se manejará como archivos estáticos. El algoritmo real para evaluar la ubicación está aquí .

Jasiu
fuente
6

Si usa mod_rewrite para ocultar la extensión de sus scripts, o si solo le gustan las URL bonitas que terminan en /, entonces es posible que desee abordar esto desde la otra dirección. Dígale a nginx que deje que cualquier cosa con una extensión no estática pase a apache. Por ejemplo:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
{
    root   /path/to/static-content;
}

location ~* ^!.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Encontré la primera parte de este fragmento en: http://code.google.com/p/scalr/wiki/NginxStatic

lo_fye
fuente
Esto funcionó muy bien, aunque todavía obtengo errores para archivos minificados (por ejemplo, site.min.css y main.min.js, etc.). ¿Cómo los atraparía en una expresión regular de ubicación? @lo_fye
Garth