Раздача статических файлов: root и alias
Отдать файл с диска — самая базовая задача веб-сервера, и Nginx делает это блестяще. Главное — не перепутать root и alias.
«root приклеивает URI к пути целиком, alias — заменяет совпавшую часть. Перепутаешь — получишь 404 на ровном месте.»
Статика — это файлы, которые не меняются от запроса к запросу: HTML, CSS, JS, картинки, шрифты. Nginx читает их прямо с диска и отдаёт максимально быстро. Управляют этим две директивы: root и alias.
Директива root
root задаёт корневой каталог, к которому целиком приклеивается URI запроса:
location /images/ {
root /var/www/data;
}
# Запрос /images/cat.png -> файл /var/www/data/images/cat.png
Обрати внимание: путь /images/ из URI сохраняется и добавляется к root. Итоговый путь = root + URI.
Директива alias
alias работает иначе: он заменяет совпавшую часть location на указанный путь:
location /images/ {
alias /var/www/data/pics/;
}
# Запрос /images/cat.png -> файл /var/www/data/pics/cat.png
Здесь часть /images/ заменяется на /var/www/data/pics/. Итоговый путь = alias + (URI без префикса location).
Индексные файлы
server {
listen 80;
server_name example.com;
root /var/www/html;
location / {
index index.html index.htm;
try_files $uri $uri/ =404;
}
}
index задаёт файл по умолчанию для каталога (запрос / отдаст /var/www/html/index.html). try_files по очереди пробует варианты: сам файл $uri, затем каталог $uri/, и если ничего нет — отдаёт 404.
Как работает под капотом
Получив запрос, Nginx находит подходящий location, вычисляет путь к файлу (root приклеивает весь URI, alias заменяет префикс), проверяет существование файла и отдаёт его, используя sendfile — копирование из файла прямо в сетевой сокет средствами ядра, без лишнего копирования в память приложения. Это очень дёшево по CPU. Content-Type определяется по расширению через mime.types.
Частые ошибки
- Использовать
rootтам, где нуженalias. Классика:location /static/ { root /var/www/static/; }приведёт к пути/var/www/static/static/...— двойной static и 404. - Забыть слеш в alias. Для location со слешем на конце alias тоже должен оканчиваться слешем.
- Полагаться на
=404в try_files, забыв саму статику. Проверь права доступа: воркер должен иметь право читать файлы.
Best practices
- Для подкаталогов с «перепрыгиванием» в другое место используй
alias; для прямого совпадения структуры —root. try_files $uri $uri/ =404;— безопасный шаблон: отдай файл, иначе явный 404.- Держи статику и аплоады в отдельных каталогах с правильными правами.
SPA, аплоады и защита от обхода путей
На практике раздача статики почти всегда сложнее, чем «отдай файл». Возьмём одностраничное приложение (React, Vue): на сервере лежит один index.html и куча ассетов, но маршрутизация — на клиенте. Если пользователь обновит страницу на /profile/settings, такого файла на диске нет, и обычная отдача вернёт 404. Решение — try_files $uri $uri/ /index.html;: не нашёл файл — отдай index.html, а уж он сам разберётся с маршрутом средствами JavaScript. Это стандартный паттерн для SPA, который стоит знать наизусть.
Второй важный момент — безопасность путей. Когда путь к файлу формируется из URI, возникает риск обхода каталога (path traversal): запрос вида /static/../../etc/passwd теоретически мог бы вылезти за пределы корня. Nginx нормализует путь и не пускает наружу, но коварство alias в том, что при неаккуратной комбинации с регулярными location можно открыть лишнее. Поэтому держи каталог статики изолированным, не клади туда конфиги и ключи, и выдавай воркеру права только на чтение нужных файлов. Аплоады пользователей вообще лучше хранить в отдельном каталоге с запретом на исполнение, чтобы загруженный «аватар» не оказался исполняемым скриптом. Правильная раздача статики — это не только про скорость, но и про то, чтобы случайно не отдать в интернет то, что не предназначено для чужих глаз.
Итоги
Nginx отдаёт статику через root (URI приклеивается к корню целиком) или alias (префикс location заменяется на путь). index задаёт файл по умолчанию, try_files — цепочку проверок. Под капотом работает быстрый sendfile. Дальше — самое важное в маршрутизации: как Nginx выбирает location среди многих.