Рубріки: HighloadТеория

Правильная конфигурация Nginx

Ігор Грегорченко

Наткнуться на подводные камни в конфигурации и работе веб-сервера очень легко. Но трудно понять причину некорректной или не всегда корректной/ошибочной работы, если все правила соблюдаются.

Root внутри секции location

Нет ничего плохого в размещении root-директории внутри location. Но если location не соответствует, то у нее не будет доступа к корневому каталогу. Правильнее делать так:

server {
    server_name www.somesite.com;
    root /var/www/nginx-default/;
    location / {
        # [...]
    }
    location /foo {
        # [...]
    }
    location /bar {
        # [...]
    }
}

# Указание root внутри секции server

Несколько директив index

Не нужно плодить большое количество директив index. Пропишите ее один раз в блоке http:

http {
    index index.php index.htm index.html;
    server {
        server_name www.somesite.com;
        location / {
            # [...]
        }
    }
    server {
        server_name somesite.com;
        location / {
            # [...]
        }
        location /foo {
            # [...]
        }
    }
}

#Index будет автоматически наследоваться в всех секциях

Использование if

Вы же в курсе, что if = зло? При использовании директивы нужно быть осторожным, ошибиться несложно. Так что по возможности избегайте использования if.

Имя сервера

Предположим, ваш сайт лежит на домене somesite.com и вы перенаправляете на него пользователей, которые идут на www.somesite.com:

server {
    server_name somesite.com *.somesite.com;
        if ($host ~* ^www\.(.+)) {
            set $raw_domain $1;
            rewrite ^/(.*)$ $raw_domain/$1 permanent;
        }
        # [...]
    }
}

# Проверяет и перенаправляет хост

Здесь несколько проблем. Главная – if. Вне зависимости от запроса хоста (с www или без), Nginx все равно проверяет if. Для каждого запроса. Взамен можно сделать так:

server {
    server_name www.somesite.com;
    return 301 $scheme://somesite.com$request_uri;
}
server {
    server_name somesite.com;
    # [...]
}

# Используется $scheme, которая подходит для http и https

Проверка наличия файла

Не используйте if для проверки наличия файла:

server {
    root /var/www/somesite.com;
    location / {
        if (!-f $request_filename) {
            break;
        }
    }
}

# Подход как минимум не эффективен

Взамен у Nginx есть директива try_files:

server {
    root /var/www/somesite.com;
    location / {
        try_files $uri $uri/ /index.html;
    }
}

# Проверка последовательности на наличие файла, если не существует, то отправляет на index.html

Примечательно, что директиву также можно использовать для защиты веб-сервера от несанкционированного доступа.

Передача запросов на PHP

Если Nginx перенаправляет все запросы, заканчивающиеся на .php, напрямую на интерпретатор PHP, то для злоумышленников открываются возможности для выполнения стороннего кода. PHP по умолчанию пытается догадаться, куда должен вести неправильный запрос. Так что в первую очередь необходимо подправить php.ini, указав:

cgi.fix_pathinfo=0

#Интерпретатор будет обрабатывать только корректные запросы

Обратите внимание на правильную конфигурацию Nginx:

# Перенаправляет запросы только для указанных файлов
location ~* (file_a|file_b|file_c)\.php$ {
    fastcgi_pass backend;
    # [...]
}

 # Отключить выполнение скриптов в пользовательских загрузках
location /uploaddir {
    location ~ \.php$ {return 403;}
    # [...]
}

 # Фильтрация при помощи try_files
location ~* \.php$ {
    try_files $uri =404;
    fastcgi_pass backend;
    # [...]
}

 # Использует вложенное расположение для фильтрации
location ~* \.php$ {
    location ~ \..*/.*\.php$ {return 404;}
    fastcgi_pass backend;
    # [...]
}

# Параметры можно комбинировать

Путь FastCGI

Неправильное указание путей размещения скриптов FastCGI часть приводит к ошибке “Primary script unknown”, которая легко решается.

Перезапись (rewrite)

Используйте переменную $request_uri для изменения URI запроса:

rewrite ^ http://somesite.com$request_uri? permanent;

# Или так
return 301 http://somesite.com$request_uri;

# Перенаправляет на страницу 301

Отсутствующий http://

Добавить отсутствующий http:// очень просто:

rewrite ^ http://somesite.com permanent;

# Автоматически дополняет запрос

Проксирование

Не перенаправляйте все запросы на PHP в таком виде:

server {
    server_name _;
    root /var/www/site;
    location / {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

# Передает все на phpcgi.socket

Используйте все те же директиву try_files:

server {
    server_name _;
    root /var/www/site;
    location / {
        try_files $uri $uri/ @proxy;
    }
    location @proxy {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

# Передает только нужные запросы на proxy

Или так:

server {
    server_name _;
    root /var/www/site;
    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

# Если Nginx не может обработать запрашиваемый URI самостоятельно, то проверяет директории на наличие, затем передает на proxy

Самое главное

Основная причина ошибочной работы системы (не только Nginx) — бездумный копипаст. Проверяйте конфиги, тестируйте приложение перед выкаткой, читайте документацию.

Останні статті

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

Как создать игру на телефоне: программирование с помощью конструктора

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024