How to use Nginx try_files
In this tutorial, we will quickly discuss how to use the try_files directive and learn when and how to use it:
What is The try_files Directive, and How Does It Work?
We usually use the Nginx try_files directive to recursively check if files exist in a specific order and serve the file located first.
The try_file directive is in the server and location blocks and specifies the files and directories in which Nginx should check for files if the request to the specified location is received. A typical try_files directive syntax is as:
The location/block specifies that this is a match for all locations unless explicitly specified location /<name>
Inside the second block, the try_files means if Nginx receives a request to the URI that matches the block in the location, try the $uri first, and if the file is present, serve the file.
For example, if a request such as https://linuxhint.com/blocks/io.sh is received, Nginx will first look for the file inside the /blocks directory and serve the file if available.
The next part (/default/index.html) specifies a fallback option if the file is not in the first param. For example, if the file is not in the /block directory, Nginx will search for the /default directory and serve the file if it exists.
By default, Nginx forbids directory listing, and you will get 403 Forbidden unless you have auto index set to on.
If Nginx fails to find the file in the specified locations, it displays a 404 not found error to the user.
NOTE: Nginx try_files directive recursively searches for files and directories specified from left to right until it finds ones. Specifying this directive in the location / can cause performance issues, especially on sites with massive traffic. Therefore, you should explicitly specify the location block for try_files.
Conclusion
This quick and simple guide has given you an overview of how Nginx try_block works. We recommend diving deep into the Nginx documentation to understand various blocks and when to use them.
About the author
John Otieno
My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list
Nginx Understanding the intersection of alias and try_files
When working with Nginx it is important to understand the routing and built-in variables. I was working on a clients server configuration recently and we ran into what seemed to be a very annoying bug within Nginx. To frame the issue, they needed to route to different folders based on sub-domains in order serve the clients static files.
The Architecture
This architecture consisted of docker containers with Nginx behind, an Amazon ELB, behind Amazon CloudFront. We needed to handle SSL termination for multiple custom domains however, Amazon only allows you to use one certificate per load balancer. So we were doing SSL termination within Cloudfront for a custom domain like ‘example.com’ which would then need to be converted to ‘example.exampleapp.com’. This allowed us to separate SSL termination out for different parts of the stack.
What We Had to Solve
Nginx needed to then take the sub-domain and route asset requests to different folders within the docker container. Given the example above example.com would need to go to /var/www/sites/example.com/public. This needed to happen in a programmatic way in order to avoid having a different server block per sub-domain. So Alias seems perfect for this right? So we started off with a server block that looks like this.
I kept reading through the docs and thinking it looked exactly like the example in the Nginx docs. I even switched out Alais with root, to test a specific case and everything worked… So what was going on?
The First Solution
After reading the docs over and over, and getting nowhere I turned to stack overflow. I found this post and thought I struck Gold. It;s a long-standing bug, it said. My job is done, it doesn’t work in Nginx move on to the next option. The truth is we are all developers and despite finding that I hammered the app for another couple hours. I logged out the document root and thought it just confirmed my theory since Alias was working correctly.
The Real Solution
I decided to try one more thing, and I removed the try_files line, and everything worked. At this point, I was 100% convinced it was a core bug. I was curious though why this was a bug and decided to log out $uri. The second I did that it all clicked. $url is not affected by Alias, so it was re-adding the entire URI to try files and looking in a directory that didn’t exist. Finally, I went back to that stack overflow post and realized what was actually going on. I needed to use the regex value in try_files and not a core variable. So we ended up with the following solution which works perfectly.
Conclusion
The biggest thing to understand about Nginx is its routing, and how it modifies its variables. What looked like a core bug, was really just the misuse of $uri.
Ошибки конфигурирования nginx (или как правильно писать рерайты)
По долгу службы приходится работать с веб-разработчиками, которые иногда пишут свои скрипты с рерайтами, которые им приходится адаптировать для nginx. Мне же приходится разгребать то, что там написано.
Все желающие получить помощь по рерайтам могут задавать вопросы в комментариях, потом, наверно, из этого будет оформлен еще один пост.
Ошибка номер 1, самая фатальная.
Огромное количество раз упоминалась в рассылке. А именно — использование if на уровне location.
Проблема в том, что if в location устроены не так, как мы представляем. Мы думаем, что приходит запрос, проверяется условие, если оно истинно — делаются поправки к конфигурации. А на деле все совсем иначе. При запуске nginx генерирует отдельные конфигурации location’ов для истинных и ложных условий в if. Несколько жутких примеров:
Segmentation fault в рабочем процессе при попытке найти upstream для proxy_pass’a из первого if’a. А все дело в том, что он не унаследовался в location, где оба условия правильные.
Полное игнорирование try_files. Просто его нет в location, который получился при истинности выражения.
Под «set $expr 123;» можно понимать почти любое выражение в if, не задающее обработчика для запроса — все set, limit_rate и прочее.
Однако, в одном случае использовать if в location все-таки можно — если сразу же после if’a мы уйдем из этого location. Сделать это можно двумя способами:
1) Через rewrite… last;
2) Через return . ;
При этом мы можем через return как окончить обработку запроса, так и перейти в другой location, через error_page.
Кстати, if на уровне server действует именно так, как мы ожидаем. При его использовании глобальных проблем возникать не должно.
Ошибки номер 2, менее фатальные.
Ошибка номер 2.1, об if (-e . )
Специально для того, чтобы красиво записывать такие рерайты придумана специальная директива — try_files. В самом простом варианте ее обычно записывают так:
try_files $uri $uri/ @fallback
что обозначает:
1. Проверить, существует ли запрошенный файл. Если да — отдать его, если нет — идти далее.
2. Проверить, существует ли директория с запрошенным именем. Если да — отдать ее, если нет — идти далее.
3. Передать запрос на обработку в именованный location @fallback.
Внимание! В @fallback при использовании fastcgi не стоит делать rewrite. Достаточно лишь написать fastcgi_parm с требуемым скриптом. Таким образом, конструкция вроде
RewriteCond %
RewriteCond %
RewriteRule ^(.*)$ index.php
Превращается в
В случае использования как бекенда не FastCGI, а HTTP, можно написать это так:
Нужно понимать, что все аргументы try_files, кроме последнего, будут восприниматься как простые файлы для отдачи, а последний аргумент — уже как новая цель (то есть, туда можно написать обрабатывающий uri или именованый location). Поэтому, попытка написать try_files $uri $uri/ /index_new.php /index_old.php не приведет ни к чему хорошему — вместо выполнения index_new.php будет отдано его содержимое.
С помощью try_files можно делать еще одну удивительную вещь — не редактируя конфигов, закрыть весь сайт на техобслуживание. Это делается прописыванием try_files /maintenance.html $uri $uri/ @fallback; и затем простым созданием/перемещением файла /maintenance.html с сообщением о технических работах. Это не даст ожидаемого спада производительности в связи с использованием open_file_cache, который так же кеширует и неудачные попытки открытия файла.
Ошибка номер 2.2, об if ($uri
», то nginx сконфигурирован неправильно. Вся логика проверки uri на что-то должна быть реализована через location, которые теперь поддерживают и выделения.
RewriteCond %
RewriteRule ^(.*)$ rss.php
переходит в
Ошибка номер 2.3, об if ($host
) так же верно для if ($host
). Для использования этих правил просто создайте server с server_name в виде регэкспа!
Не ошибка, но грабли с выделениями
Если Вы отважились переписать конфиг с использованием выделений в server/location то непременно наткнетесь на небольшую проблему. Она заключается в том, что при входе в location с регекспом затираются серверные выделения, при входе в if или при использовании rewrite затираются выделения location.Увы, я не слишком сильно знаком с рерайтами apache чтобы предоставить код, поэтому опишу требуемое словами.
Требуется все запросы вида abc.mysite.com/xyz.php перенаправлять на mysite.com/abc/index.php?p=xyz
Для того, чтобы это работало, приходится писать вот так:
В следующих версиях nginx планируется для выделений на каждом уровне сделать отдельные префиксы (например, вышеописанный рерайт можно будет описать как ), но пока этого нет, так что приходится писать так.
Еще неплохой практикой является давание переменным осмысленных имен :-).
Заключение
Спасибо всем, кто дочитал пост до конца. Он получился достаточно длинным, но я хотел описать все максимально чисто и понятно.
Разумеется, существуют и другие ошибки при конфигурировании — буферы, пути, но это — забота системного администратора, а не вебмастера.
click fraud protection
В этом руководстве мы быстро обсудим, как использовать директиву try_files, и узнаем, когда и как ее использовать:
Что такое директива try_files и как она работает?
Обычно мы используем директиву Nginx try_files, чтобы рекурсивно проверять, существуют ли файлы в определенном порядке, и обслуживать файл, расположенный первым.
Директива try_file находится в блоках server и location и указывает файлы и каталоги, в которых Nginx должен проверять наличие файлов, если получен запрос в указанное место. Типичный синтаксис директивы try_files выглядит так:
расположение / <
try_files $ uri $ uri / / дефолт / index.html;
>
Местоположение / блок указывает, что это соответствие для всех местоположений, если явно не указано местоположение /
Внутри второго блока try_files означает, что если Nginx получает запрос на URI, который соответствует блоку в местоположении, сначала попробуйте $ uri, а если файл присутствует, обслужить файл.
Например, если такой запрос, как https://linuxhint.com/blocks/io.sh получен, Nginx сначала ищет файл в каталоге / blocks и обслуживает файл, если он доступен.
В следующей части (/default/index.html) указывается резервный вариант, если файл не указан в первом параметре. Например, если файла нет в каталоге / block, Nginx будет искать каталог / default и обслуживать файл, если он существует.
По умолчанию Nginx запрещает список каталогов, и вы получите 403 Forbidden, если у вас не включен автоматический индекс.
Если Nginx не может найти файл в указанных местах, он отображает для пользователя ошибку 404: не найден.
ПРИМЕЧАНИЕ: Директива Nginx try_files рекурсивно ищет файлы и каталоги, указанные слева направо, пока не найдет их. Указание этой директивы в местоположении / может вызвать проблемы с производительностью, особенно на сайтах с большим трафиком. Следовательно, вы должны явно указать блок местоположения для try_files.
Вывод
Это быстрое и простое руководство дало вам обзор того, как работает Nginx try_block. Мы рекомендуем углубиться в документацию Nginx, чтобы понять различные блоки и когда их использовать.