Nginx: ¿raíz versus alias, para servir archivos individuales?

66

Después de muchas horas nginxpara servir archivos individuales como robots.txt(pista: borrar el caché del navegador cada vez), terminé con dos formas diferentes, una usando la directiva de alias y otra usando la directiva raíz , así:

location /robots.txt { alias /home/www/static/robots.txt; }
location /robots.txt { root /home/www/static/;  }

¿Hay alguna diferencia funcional entre los dos? O problemas de seguridad? ¿Algún conflicto con otras directivas? (Ambos parecían estar bien con otro / ubicación estática). ¿O alguna razón para elegir uno sobre el otro?

Nota: no utilicé ambos al mismo tiempo :) En cambio, probé cada uno, uno a la vez, y ambos funcionaron. No estoy preguntando cómo ambos interactúan juntos en el mismo archivo, pero cuál sería mejor usar.

Cíclope
fuente

Respuestas:

71

Bueno, estas dos directivas son ligeramente funcionales diferentes porque no utiliza la coincidencia exacta en el último caso. Por lo tanto, /robots.txt1111coincidirá con su segunda ubicación también.
location =/robots.txt { root /home/www/static/; }es un equivalente funcional exacto de su primera directiva.

Alex
fuente
Buen punto, gracias. Pero puedes usar un =en ambos casos, ¿correcto? ¿O solo se aplica a root? Además, vea mi edición: no quise usar ambos a la vez. :)
Cyclops
@ Cyclops sí, puedes usarlo =en ambos casos.
Alexander Azarov
Entonces serían lo mismo: ¿hay alguna razón para elegir una directiva sobre la otra? Es mi pregunta principal
Cyclops
@ Cyclops Básicamente, no existe tal razón.
Alex
41

Sí, hay una diferencia: con "alias" puedes ... alias a otro nombre de archivo, como

location /robots.txt { alias /home/www/static/any-filename.txt; }

mientras

location /robots.txt { root /home/www/static/; }

te obliga a nombrar tu archivo en el servidor también robots.txt. Utilizo la primera opción ya que me gusta nombrar mis archivos de robots en mi servidor como tld.domain.subdomain-robots.txt; p.ej

location /robots.txt { alias /home/www/static/ch.notex.static-robots.txt; }
Hasan Karahan
fuente
1

Creo que vale la pena exponer explícitamente que nginx funciona con prefijos y no con archivos en sí. En el primer caso,

location /robots.txt { alias /home/www/static/robots.txt; }

nginx reemplaza el prefijo de cadena /robots.txten la ruta URL con /home/www/static/robots.txty luego usa el resultado como una ruta del sistema de archivos. Representado como pseudocódigo, esto sería algo así como:

if urlPath.startsWith("/robots.txt") {
    fsPath := "/home/www/static/robots.txt" + urlPath.stripPrefix("/robots.txt")
    serveFile(fsPath)
}

Por /robots.txtlo tanto, se sirve /home/www/static/robots.txtporque /robots.txtdespojado del /robots.txtprefijo es la cadena vacía, y agregar la cadena vacía para /home/www/static/robots.txtdejarla sin cambios. Pero, /robots.txt1sería servido desde /home/www/static/robots.txt1y /robots.txt/foobarsería servido desde /home/www/static/robots.txt/foobar. Es posible que esos archivos no existan, lo que hace que nginx envíe una respuesta 404, y es probable que robots.txtno sea un directorio de todos modos, pero nginx no lo sabe de antemano, y todo esto se basa en prefijos de cadena y no en lo que parece ser un archivo o directorio por la ausencia o presencia de una barra inclinada final.

Considerando que, en el segundo caso,

location /robots.txt { root /home/www/static/; }

nginx inserta la cadena /home/www/static/al comienzo de la ruta URL y luego usa el resultado como una ruta del sistema de archivos. En pseudocódigo, esto sería algo como:

if urlPath.startsWith("/robots.txt") {
    fsPath := "/home/www/static/" + urlPath
    serveFile(fsPath)
}

Esto tiene exactamente el mismo resultado que el primer caso, pero por una razón diferente. No hay eliminación de prefijos, pero dado que cada ruta URI debe contener el prefijo /robots.txt, las rutas del sistema de archivos siempre comenzarán con lo /home/www/static//robots.txtque es equivalente a /home/www/static/robots.txt .

Por supuesto, el pseudocódigo no cuenta toda la historia, ya que, por ejemplo, nginx no usará ciegamente rutas de URL sin formato como /../../../etc/passwd, la try_filesdirectiva cambia el comportamiento de root/ alias, y existen restricciones sobre dónde aliasse puede usar.

kbolino
fuente
0

Hay una diferencia, cuando el alias es para un directorio completo.

    location ^~ /data/ { alias /home/www/static/data/; }

funcionará, mientras

    location ^~ /data/ { root /home/www/static/data/; }

no lo haré Esto tendría que ser

    location ^~ /data/ { root /home/www/static/; }

(Fácil de confundir)

BurninLeo
fuente