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

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

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

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

Несколько директив 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 {
                   }
    }
}

Использование 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;
   }

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

Не используйте 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;
    }
}

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

Передача запросов на 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;}
   }

location ~* \.php$ {
    try_files $uri =404;
    fastcgi_pass backend;
   }

location ~* \.php$ {
    location ~ \..*/.*\.php$ {return 404;}
    fastcgi_pass backend;
   }

Путь FastCGI

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

Дополнительно:  Не работает принтскрин “PrtScn” – решение проблемы | Все о наушниках: обзоры, тестирование и отзывы

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

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

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

Отсутствующий 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;
    }
}

Используйте все те же директиву 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;
    }
}
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) — бездумный копипаст. Проверяйте конфиги, тестируйте приложение перед выкаткой, читайте документацию.