Введение
Немного расскажу своими словами о том, как работает модуль ngx_http_proxy_module. Именно он реализует весь функционал, о котором пойдет речь. Допустим, у вас в локальной или виртуальной сети есть какие-то сервисы, не имеющие прямого доступа из интернета. А вы хотите таковой иметь. Можно пробрасывать нужные порты на шлюзе, можно что-то еще придумывать. А можно сделать проще всего — настроить единую точку входа на все свои сервисы в виде nginx сервера и с него проксировать различные запросы к нужным серверам.
Расскажу на конкретных примерах, где я это использую. Для наглядности и простоты буду прям по порядку перечислять эти варианты:
- Ранее я рассказывал о настройке чат серверов — matrix и mattermost. В этих статьях я как раз рассказывал о том, как проксировать запросы в чат с помощью nginx. Прошелся по теме вскользь, не останавливаясь подробно. Суть в том, что вы настраиваете на любом виртуальном сервере эти чаты, помещаете их в закрытые периметры сети без лишних доступов и просто проксируете запросы на эти сервера. Они идут через nginx, который у вас смотрит во внешний интернет и принимает все входящие соединения.
- Допустим, у вас есть большой сервер с множеством контейнеров, например докера. На нем работает множество различных сервисов. Вы устанавливаете еще один контейнер с чистым nginx, на нем настраиваете проксирование запросов на эти контейнеры. Сами контейнеры мапите только к локальному интерфейсу сервера. Таким образом, они будут полностью закрыты извне, и при этом вы можете гибко управлять доступом.
- Еще один популярный пример. Допустим, у вас есть сервер с гипервизором proxmox или любым другим. Вы настраиваете на одной из виртуальных машин шлюз, создаете локальную сеть только из виртуальных машин без доступа в нее извне. Делаете в этой локальной сети для всех виртуальных машин шлюз по-умолчанию в виде вашей виртуальной машины со шлюзом. На виртуальных серверах в локальной сети размещаете различные сервисы и не заморачиваетесь с настройками фаервола на них. Вся их сеть все равно не доступна из интернета. А доступ к сервисам проксируете с помощью nginx, установленным на шлюз или на отдельной виртуальной машине с проброшенными на нее портами.
- Мой личный пример. У меня дома есть сервер synology. Я хочу организовать к нему простой доступ по https из браузера по доменному имени. Нет ничего проще. Настраиваю на сервере nginx получение бесплатного сертификата , настраиваю проксирование запросов на мой домашний ip, там на шлюзе делаю проброс внутрь локалки на synology сервер. При этом я могу фаерволом ограничить доступ к серверу только одним ip, на котором работает nginx. В итоге на самом synology вообще ничего не надо делать. Он и знать не знает, что к нему заходят по https, по стандартному порту 443.
- Допустим, у вас большой проект, разбитый на составные части, которые живут на разных серверах. К примеру, на отдельном сервере живет форум, по пути /forum от основного домена. Вы просто берете и настраиваете проксирование всех запросов по адресу /forum на отдельный сервер. Точно так же можно без проблем все картинки перенести на другой сервер и проксировать к ним запросы. То есть вы можете создать любой location и переадресовывать запросы к нему на другие сервера.
Надеюсь в общем и целом понятно, о чем идет речь. Вариантов использования много. Я привел самые распространенные, которые пришли в голову и которые использую сам. Из плюсов, которые считаю наиболее полезными именно из своих кейсов, отмечу 2:
- Без проблем можете настроить https доступ к сервисам, при этом совершенно не трогая эти сервисы. Вы получаете и используете сертификаты на nginx сервере, используете https соединение с ним, а сам nginx уже передает информацию на сервера со службами, которые могут работать по обычному http и знать не знают о https.
- Вы очень легко можете менять адреса, куда проксируете запросы. Допустим у вас есть сайт, его запросы проксируются на отдельный сервер. Вы подготовили обновление или переезд сайта. Отладили все на новом сервере. Теперь вам достаточно на сервере nginx изменить адрес старого сервера на новый, куда будут перенаправляться запросы. И все. Если что-то пойдет не так, можете оперативно вернуть все обратно.
С теорией закончил. Перейдем теперь к примерам настройки. В своих примерах я буду использовать следующие обозначения:
blog.zeroxzed.ru | доменное имя тестового сайта |
nginx_srv | имя внешнего сервера с установленным nginx |
blog_srv | локальный сервер с сайтом, куда проксируем соединения |
94.142.141.246 | внешний ip nginx_srv |
192.168.13.31 | ip адрес blog_srv |
77.37.224.139 | ip адрес клиента, с которого я буду заходить на сайт |
Обработка ошибок
Использовать Инструкция, вы можете настроить nginx:
- Вернуть код ошибки и настроенную страницу;
- В ответном сообщении замените другой код ошибки
- Отправить в браузер команду перенаправления, указывающую на другой URI
В следующем примереerror_page В инструкции указывается страница /404.html, которая будет возвращена клиенту, когда он вернет код 404:
Следует отметить, что эта инструкция не сразу возвращает ошибку клиенту (именно это и делает инструкция возврата), она просто определяет, как обработать ошибку. Код ошибки может исходить от внутреннего сервера или появляться, когда nginx выполняет некоторую обработку (например, когда nginx не может найти запрошенный файл, он вернет ошибку 404).
В следующем примере, когда nginx не может найти запрошенную страницу, он заменяет код 404 на код 301 и возвращает клиенту перенаправление:http:/example.com/new/path.html。
Эта конфигурация очень полезна: когда клиент пытается запросить страницу со старым URI, он может вернуть команду перенаправления, чтобы получить доступ к файлу по новому пути.
Код 301 сообщает браузеру, что страница была навсегда перенесена в другое место, и ему необходимо заменить старый адрес новым возвращенным адресом:
В следующем примере, когда при запросе файла по пути / images / возникает ошибка «файл не найден», передайтеВнутреннее перенаправлениеПеренаправить на внутренний сервер. Поскольку в инструкции error_page после = не определен код состояния замены, код состояния, возвращаемый клиенту, указывается внутренним сервером (не обязательно 404):
error_page Инструкция сообщает nginx о необходимости внутреннего перенаправления при возникновении ошибки «файл не найден». Значение переменной $ uri — это URI текущего запроса, который пересылается на внутренний сервер во время перенаправления.
Например, если/images/some/file Не обнаружено, заменено на/fetch/images/some/fileДля этого нового URI nginx найдет соответствующее местоположение, вот местоположение / fetch /, а затем он будет перенаправлен на внутренний сервер. (см.Обратный прокси)
При отправке файла ошибка не найдена, Здесь используются инструкции для предотвращения регистрации ошибок. Поскольку запрос был перенаправлен на серверную часть, журнала ошибок быть не должно.
Информация об авторских правах: * Эта статья составлена изnginx.com
Шаг 3. Контроль ресурсов и ограничения
Чтобы предотвратить потенциальные DoS-атаки на nginx, вы можете установить ограничения на размер буфера для всех клиентов. Вы можете сделать это в файле конфигурации nginx, используя следующие директивы:
- client_body_buffer_size – используйте эту директиву, чтобы указать размер буфера тела запроса клиента. Значение по умолчанию — 8 КБ или 16 КБ, но рекомендуется установить его равным 1 КБ: client_body_buffer_size 1k.
- client_header_buffer_size – используйте эту директиву, чтобы указать размер буфера заголовка для заголовка запроса клиента. Размер буфера 1k подходит для большинства запросов.
- client_max_body_size – используйте эту директиву, чтобы указать максимально допустимый размер тела для клиентского запроса. Директивы 1k должно быть достаточно, но вам нужно увеличить ее, если вы получаете загрузку файлов методом POST.
- large_client_header_buffers – используйте эту директиву, чтобы указать максимальное количество и размер буферов, которые будут использоваться для чтения больших заголовков клиентских запросов. Директива large_client_header_buffers 2 1k устанавливает максимальное количество буферов в 2, каждый с максимальным размером 1k. Эта директива будет принимать URI данных размером 2 КБ.
Примечание. Некоторые источники предполагают, что установка таких ограничений может предотвратить потенциальные атаки переполнения буфера, если такие уязвимости обнаружены в nginx.
Шаг 9 — Настройка сайтов HTTPS с Let’s Encrypt (опционально)
На этом шаге мы настроим сертификаты TLS/SSL для обоих доменов, размещенных в Apache. Мы получим сертификаты посредством Let’s Encrypt. Nginx поддерживает конечные узлы SSL, и поэтому мы можем настроить SSL без изменения файлов конфигурации Apache. Модуль обеспечивает установку в Apache переменных среды, необходимых для бесшовной работы приложений за обратным прокси-сервером SSL.
Вначале мы разделим блоки обоих доменов так, что у каждого из них будет собственный сертификат SSL. Откройте в своем редакторе файл :
Измените файл, чтобы он выглядел следующим образом, сайты и должны находиться в собственных блоках:
/etc/nginx/sites-available/apache
Мы используем Certbot для генерирования сертификатов TLS/SSL. Плагин Nginx изменит конфигурацию Nginx и перезагрузит ее, когда это потребуется.
Прежде всего, добавьте официальное хранилище Certbot:
Нажмите в диалоге, чтобы подтвердить добавление нового хранилища. Обновите список пакетов, чтобы получить данные пакета нового хранилища:
Установите пакет Certbot’s Nginx с :
После установки используйте команду для генерирования сертификатов для и :
Эта команда указывает Certbot, что нужно использовать плагин , а параметр задает имена, для которых должен действовать сертификат.
Если это первый запуск , вам будет предложено указать адрес эл. почты и принять условия обслуживания. После этого свяжется с сервером Let’s Encrypt и отправит запрос с целью подтвердить, что вы контролируете домен, для которого запрашиваете сертификат.
Далее Certbot запросит желаемый вариант настройки HTTPS:
Выберите желаемый вариант и нажмите . Конфигурация будет обновлена, а затем будет выполнена перезагрузка Nginx для активации новых настроек.
Теперь выполните команду для второго домена:
Откройте один из доменов Apache в браузере с помощью префикса ; откройте , и вы увидите следующее:
Посмотрите раздел PHP Variables. Для переменной SERVER_PORT задано значение 443 и протокол HTTPS включен, как если бы осуществлялся прямой доступ к Apache через HTTPS. При такой настройке переменных не нужно специально настраивать приложения PHP для работы за обратным прокси-сервером.
Теперь отключим прямой доступ к Apache.
Tip 4 – Change the size of the Buffers
Nginx buffers are also somewhat important for the optimization of Nginx performance. Because the buffer sizes are too low, then Nginx going to write to a temporary file causing huge disk I/O operations constantly. To prevent it, set the buffer size accordingly.The following are the parameters that need to be adjusted inside the file for optimum performance:
http{ ... client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 4 4k; ... }
- client_body_buffer_size – Sets buffer size for reading client request body. In case the request body is larger than the buffer, the whole body or only its part is written to a temporary file.
- client_header_buffer_size – Refers to the buffer size relative to the client request header.
- client_max_body_size – Sets the maximum allowed size of the client request body, specified in the “Content-Length” request header field. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client.
- large_client_header_buffers – Maximum number and size of buffers for large client headers. A request line cannot exceed the size of one buffer, or the 414 (Request-URI Too Large) error is returned to the client.
With the values above the Nginx will work optimally but for even further optimization, you can tweak the values and test the performance.
Шаг 6. Установка и настройка access и error logs nginx
Журналы access и error logs nginx включены по умолчанию и расположены соответственно в logs/error.log и logs/access.log. Если вы хотите изменить местоположение, вы можете использовать директиву error_log в файле конфигурации nginx. Вы также можете использовать эту директиву, чтобы указать журналы, которые будут записываться в соответствии с их уровнем безопасности. Например, уровень crit заставит nginx регистрировать критические проблемы и все проблемы, которые имеют более высокий уровень, чем уровень crit. Чтобы установить уровень crit, установите директиву error_log следующим образом:
Вы можете найти полный список уровней error_log в официальной .
Вы также можете изменить директиву access_log в файле конфигурации nginx, указав расположение не по умолчанию для журналов доступа. Наконец, вы можете использовать директиву log_format для настройки формата записываемых сообщений, как описано .
Timeouts
Timeouts can also drastically improve performance.
The and directives are responsible for the time a server will wait for a client body or client header to be sent after request. If neither a body or header is sent, the server will issue a 408 error or Request time out.
The assigns the timeout for keep-alive connections with the client. Simply put, Nginx will close connections with the client after this period of time.
Finally, the is established not on the entire transfer of answer, but only between two operations of reading; if after this time client will take nothing, then Nginx is shutting down the connection.
Logging
Nginx logs every request that hits the VPS to a log file. If you use analytics to monitor this, you may want to turn this functionality off. Simply edit the directive:
Save and close the file, then run:
Conclusion
At the end of the day a properly configured server is one that is monitored and tweaked accordingly. None of the variables above are set in stone and will need to be adjusted to each unique case. Even further down the road, you may be looking to further your machine performance with research in load balancing and horizontal scaling. These are just a few of the many enhancements a good sysadmin can make to a server.
<div class=“author”>Submitted by: <a href=“”>Alex Kavon</div>
Переписать HTTP-ответ
Иногда вам нужно переписать или изменить содержимое сообщения HTTP-ответа. вы можете использовать Инструкции по определению операции перезаписи. Эта инструкция поддерживает подстановку переменных и цепочек и может вносить сложные изменения:
Например, вы можете изменить абсолютную ссылку на сервер:
Другой пример, изменитеhttp:// Заhttps:// , И измените адрес localhost на значение поля host в заголовке запроса. Инструкция сообщает nginx, следует ли выполнять операцию замены повторно для всех совпавших строк или выполнять только операцию замены (заменять только один раз), когда совпадающая строка встречается в первый раз. sub_filter_once включен по умолчанию, что означает, что он заменяется только один раз, когда совпадающая строка встречается впервые:
Обратите внимание, что если часть ответного сообщения была изменена инструкцией sub_filter, когда другой sub_filter также соответствует этой части, он не будет изменен
Establishing a Baseline
One of the first steps in performance tuning anything is to establish a unit of measurement. For this article, we will be using the HTTP load testing tool ApacheBench, otherwise known as to generate test traffic to our NGINX system.
This load-testing tool is very simple and useful for web applications. ApacheBench provides quite a few options for different types of load-testing scenarios; however for this article, we’ll keep our testing pretty simple.
We will be executing the command with the (concurrency level) and (number of requests) parameters set.
$ ab -c 40 -n 50000 http://159.203.93.149/
When we execute , we’ll be setting the concurrency level () to , meaning will maintain at least concurrent HTTP sessions to our target NGINX instance. We will also be setting a limit on the number of requests to make with the parameter. Essentially these two options together will cause to open concurrent HTTP sessions and send as many requests as possible until it reaches requests.
Let’s go ahead and execute a test run to establish a baseline and identify which metric we will use for our testing today.
# ab -c 40 -n 50000 http://159.203.93.149/ This is ApacheBench, Version 2.3 <$Revision: 1528965 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 159.203.93.149 (be patient) Completed 5000 requests Completed 10000 requests Completed 15000 requests Completed 20000 requests Completed 25000 requests Completed 30000 requests Completed 35000 requests Completed 40000 requests Completed 45000 requests Completed 50000 requests Finished 50000 requests Server Software: nginx/1.10.0 Server Hostname: 159.203.93.149 Server Port: 80 Document Path: / Document Length: 8089 bytes Concurrency Level: 40 Time taken for tests: 16.904 seconds Complete requests: 50000 Failed requests: 0 Total transferred: 420250000 bytes HTML transferred: 404450000 bytes Requests per second: 2957.93 [#/sec] (mean) Time per request: 13.523 (mean) Time per request: 0.338 (mean, across all concurrent requests) Transfer rate: 24278.70 [Kbytes/sec] received
In the above output, there are several interesting metrics. Today we will be focusing on the metric. This metric shows the average number of requests our NGINX instance can serve in a second. As we adjust parameters, we should see this metric go up or down.
Requests per second: 2957.93 [#/sec] (mean)
From the above, we can see that the mean requests per second was . This might seem like a lot, but we will increase this number by quite a bit as we continue.
When performance tuning, it’s important to remember to make small incremental changes and compare the results with the baseline. For this article, requests per second is our baseline measurement. For a parameter to be successful, it must result in an increase in requests per second.
With our baseline metrics set, let’s go ahead and start tuning NGINX.
Тестовый стенд
Для проведения экспериментов нам понадобится тестовая площадка. Конечно, всегда можно самому установить и настроить нужный дистрибутив, но зачем, когда можно просто взять и сразу перейти непосредственно к опытам? Тем более наши китайские коллеги уже собрали готовую уязвимую среду и выложили ее в виде докер-контейнера. Скачать его можно из репозитория vulapps. На странице полно иероглифов, так что вот тебе команда, которая нужна для запуска сервера:
Вообще, в этом репозитории ютится множество стендов для тестирования разных уязвимостей, советую изучить на досуге.
После успешного выполнения команды на 80-м порте у нас будет висеть подопытный веб-сервер nginx версии 1.13.1.
Если вдруг тебе захочется немного подебажить, то рекомендую приаттачиться к контейнеру и выполнить
Теперь можно присоединяться к процессу (worker process) с помощью gdb.
Сразу предупреждаю, что импакт у уязвимости невесть какой, однако покопаться в ней интересно.
Tip 1 – Adjust Worker Processors & Worker Connections
The architecture of the Nginx has one master processor and several worker processors. The purpose of the master processor is to read and evaluate the configuration as well as manage the worker processors. The worker processor’s job is to handle requests and establish a connection with the client and the server.
By default, the value of this parameter is set to auto (recommended) and it sets the number of worker processes to match the number of available CPU cores in the system. However, in case there is more traffic coming to your Nginx web server and if you require to run more processors, then it’s recommended to upgrade your machine to more cores and re-adjust the worker processes to the new number of CPU cores in your system accordingly.
In order to figure out how many worker processes we required; we first need to know how many CPUs are available in our system. To find how many cores you have on your Nginx server, run the following command.
grep processor /proc/cpuinfo | wc –l
Then we can do changes to the “worker_processes” parameter inside the file.
worker_processes auto;
Worker connections are the maximum number of connections (TCP Sessions) that each worker process can handle simultaneously. By increasing this number, we can increase the capacity of each worker process. When combine worker processors and worker connections together, you get the maximum number of clients can be served per second.
The default is 512, but most systems have enough resources to support a larger number and most web browsers opens at least two connections per server, this number can half.
The following command will tell you how many open files your system allows a process to use.
ulimit -a
Therefore the maximum number for the worker connections setting is 1024 and it’s best to use this to get the full potential from Nginx.
Let’s update the main config
worker_connections 1024;
Сжатие
Это один из самых эффективных методов ускорить ответ от вашего веб-сервера nginx.
Пример настроенного nginx.conf:
http {
…
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/javascript application/javascript application/x-javascript text/xml application/xml application/xml+rss application/json;
gzip_disable «msie6»;
…
gzip включает сжатие.
gzip_min_length устанавливает минимальную длину ответов, для которых будет применяться сжатие. По умолчанию 20, но имеет смысл поставить больше, так как постоянное сжатие приведет к повышению нагрузки на процессоры сервера и клиента.
gzip_proxied перечисляет параметры проксированных запросов, для которых будет разрешено сжатие.
gzip_types по умолчанию включено сжатие для ответов типа текст. В данном параметре можно перечислить все необходимые типы ответов.
gzip_disable запрещает для перечисленных параметров заголовка User-Agent сжатие. В данном примере для Internet Explorer 6 сжатие применяться не будет (данный браузер не умеет принимать сжатые ответы).
Tip 6 – Disabling access logs (If required)
Logging is very important when troubleshooting issues and for auditing. However, by enabling logging, it will consume large amount of disk storage and utilize more CPU/IO cycles hence reducing server performance, because it logs every single Nginx request coming to the server.There are two solutions to go about this.
access_log off;
If it’s required to have access logging, then enable access-log buffering. This enables Nginx to buffer a series of log entries and writes them to the log file together at once instead of performing the different write operations for each request.
access_log /var/log/nginx/access.log main buffer=16k
As an alternative solution you could use open source solutions for like ELK stack and others which will centralize all logs for your system.
Tip 3 – Change static content caching duration on Nginx
Static content is content of a website that remains the same across pages. As an example, that includes files like media files, documents, CSS & JS files. Caching is a mechanism for keeping frequent access files in easily accessible locations. By enabling caching will reduce bandwidth and improve the performance of the website. When a client request arrives at your site the cached version will be served up unless it has changed since the last cache. In the Nginx main configuration file, you can add the following directives to tell your computer to cache the web page’s static files for faster accessibility.Add the following section inside vhost file.
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 365d; }
In this example, all .jpg, .jpeg, .png, .gif, .ico, .css, and .js files get an Expires header with a date 365 days in the future from the browser access time.
Шаг 8. Настройте Nginx для включения заголовков безопасности
Чтобы дополнительно защитить свой веб-сервер nginx, вы можете добавить несколько различных заголовков HTTP. Вот некоторые из вариантов, которые мы рекомендуем.
X-Frame-Options
Заголовок HTTP-ответа X-Frame-Options, используется чтобы указать, разрешено ли браузеру отображать страницу в frame или iframe . Это может предотвратить атаки с помощью clickjacking. Поэтому мы рекомендуем вам включить эту опцию для вашего сервера nginx.
Для этого добавьте следующий параметр в файл конфигурации nginx в разделе server:
Strict-Transport-Security
HTTP Strict Transport Security (HSTS) — это метод, используемый веб-сайтами для объявления того, что доступ к ним должен осуществляться только через безопасное соединение (HTTPS). Если веб-сайт объявляет политику HSTS, браузер должен отклонить все HTTP-соединения и запретить пользователям принимать незащищенные SSL-сертификаты. Чтобы добавить заголовок HSTS на ваш сервер nginx, вы можете добавить следующую директиву в ваш раздел сервера:
CSP and X-XSS-Protection
Политика безопасности контента (CSP) защищает ваш веб-сервер от определенных типов атак, включая атаки с использованием Cross-site Scripting (XSS) и атаки с использованием data injection
Вы можете реализовать CSP, добавив следующий пример заголовка Content-Security-Policy (обратите внимание, что фактический заголовок должен быть настроен в соответствии с вашими уникальными требованиями):. Заголовок HTTP X-XSS-Protection поддерживается IE и Safari и не требуется для современных браузеров, если у вас есть строгая политика безопасности содержимого
Однако, чтобы предотвратить XSS в случае более старых браузеров (которые еще не поддерживают CSP), вы можете добавить заголовок X-XSS Protection в раздел вашего сервера:
Заголовок HTTP X-XSS-Protection поддерживается IE и Safari и не требуется для современных браузеров, если у вас есть строгая политика безопасности содержимого. Однако, чтобы предотвратить XSS в случае более старых браузеров (которые еще не поддерживают CSP), вы можете добавить заголовок X-XSS Protection в раздел вашего сервера:
Установка
Пакет nginx доступен в прекомпилированном виде для любого дистрибутива. Однако собрав сервер самостоятельно, ты сможешь сделать его более компактным и надежным, а также получишь возможность изменить строку приветствия Web-сервера, чтобы отбить несмышленых скрипт-кидди.
Измени строку приветствия Web-сервера
Скачай исходники nginx, открой файл src/http/ngx_http_header_filter_module.c и найди следующие две строки:
Замени их на что-то вроде этого:
Удали все неиспользуемые тобой nginx-модули
Некоторая часть модулей nginx подключается к Web-серверу прямо во время компиляции, и любой из них таит в себе потенциальную опасность. Возможно, в будущем в одном из них будет найдена уязвимость, и твой сервер окажется под угрозой. Отключив ненужные модули, ты сможешь значительно снизить риск возникновения такой ситуации.
Выполни сборку с помощью следующих команд:
Так ты получишь nginx с заранее отключенными (и в большинстве случаев бесполезными) модулями SSI (Server Side Includes) и Autoindex. Чтобы узнать, какие модули можно безболезненно выбросить из Web-сервера, запусти скрипт configure с флагом ‘—help’.
Ошибка 500 Internal Server Error — устранение на популярных платформах
Многие пользователи устанавливают на свой сервер популярные CMS-системы, такие как WordPress, Joomla, Drupal и они не должны вызывать ошибку 500, если всё настроено правильно. Однако она всё равно всплывает – из-за несовместимости версий, некачественных установок или сбоя прав доступа на сервере.
Вот некоторые распространённые проблемы, которые могут вызывать подобную ошибку в часто используемых CMS:
- Если вы только что обновили движок до новой версии, вероятно, обновление прошло с ошибками и необходимо провести его повторно. Скорее всего, на сайте разработчика есть инструкции, как это правильно сделать.
- Если вы только что активировали новый плагин или новую тему, стоит попробовать отменить эти изменения. Даже профессионально написанные плагины могут конфликтовать с другими и вызывать 500 Internal Server Error nginx
- Если вы обновляли CMS, старые плагины и темы могут быть с ней несовместимы. Единственное, что можно сделать в таком случае — отключать их по очереди, пока ошибка 500 не исчезнет.
- Неправильно заданные права доступа на сервере или ошибки в файле .htaccess. Серверу не удаётся получить доступ к скриптам, файлам и другим ресурсам, поэтому он выдаёт ошибку.
Когда причиной, по которой возникает ошибка 500 Internal Server Error являются скрипты и плагины, лучше всего искать ответы на сайтах их разработчиков.
Concluding remarks
Thank you for reading. This series would not have been possible without the great amount of resources found in the depths of the internet. Here are a few great websites we found especially useful when writing this series:
- nginx docs
- nginx blog
- nginx fundamentals on udemy
- Ilya Grigorik blog, and his amazing book:High Performance Browser Networking
- Martin Fjordvald blog
We’ll be more than happy to see some feedback or discussion, so feel free to leave comments or get in touch in any other way! Did you like the tutorial? Do you have some suggestions on what subject we should take up next? Or maybe you spotted a bug? Let us know and see you next time!
Короткая предыстория
Главная проблема веб-сервера Apache, про который мы говорили прошлый раз, — это падение производительности с ростом трафика. Чем больше людей заходят на сайт, тем хуже он справляется. Решения на тот момент были такие:
- устанавливать в серверы более мощное оборудование;
- добавлять новые серверы.
И то и другое — дорого. Чтобы решить эту проблему, в 2002 году системный администратор Игорь Сысоев начал разрабатывать собственный веб-сервер, который сможет решить проблему с проседанием под нагрузкой. Тогда Игорь работал в «Рамблере».
Через два года вышел первый релиз его веб-сервера Nginx. Сейчас это самый популярный веб-сервер в России и в тройке самых известных — в мире.
Структура конфигурационного файла Nginx
Конфигурационный файл Nginx делится на блоки.
Первый блок – events, за ним идёт http и начинается главная иерархия конфигураций.
Детали конфигурации блока http делятся на уровни при помощи закрытых блоков, которые наследуют свойства из блока, в котором они расположены. В блоке http хранится большая часть общих конфигураций Nginx, которые делятся на блоки server, которые, в свою очередь, делятся на блоки location.
Во время настройки Nginx важно помнить следующее правило: чем выше уровень конфигурации, тем больше блоков наследует эту конфигурацию; чем ниже уровень конфигурации, тем она «индивидуальнее». То есть, если параметр Х должен применяться в каждом блоке server, то такой параметр нужно поместить в блок http
Если вы внимательно рассмотрите файл, вы заметите, что он содержит много опций, которые определяют поведение программы как единого целого.
Например, чтобы настроить сжатие файлов, нужно установить такие параметры:
Это включит поддержку gzip для сжатия отправляемых клиенту данных и отключит gzip для Internet Explorer 6 (поскольку этот браузер не поддерживает сжатия данных).
Если какой-либо параметр должен иметь разное значение в нескольких блоках server, то такой параметр можно задать на высшем уровне, а затем переопределить его внутри самих блоков server. В результате Nginx выполнит параметр низшего уровня.
Такое разбиение конфигураций на уровни позволяет избежать необходимости управлять несколькими идентичными файлами. Кроме того, если вы забыли определить параметры на низшем уровне, Nginx просто выполнит параметры по умолчанию.
Блок http в файле nginx.conf заканчивается так:
Это говорит о том, что блоки server и location, которые определяют настройки конкретных сайтов и URL-адресов, будут храниться за пределами этого файла.
Это позволяет поддерживать модульную архитектуру конфигураций, в которой можно создавать новые файлы для обслуживания новых сайтов. Также это позволяет группировать похожие файлы.
Закройте файл nginx.conf. Теперь нужно изучить настройки отдельных сайтов.
Worker Connections
The next parameter we are going to tune is the configuration within NGINX. This value defines the maximum number of TCP sessions per worker. By increasing this value, the hope is that we can increase the capacity of each worker process.
The setting can be found within the block in the configuration file.
events { worker_connections 768; # multi_accept on; }
The default setting for Ubuntu’s installation of NGINX is . For this first test, we will try to change this setting to and measure the impact of that change.
events { worker_connections 1024; # multi_accept on; }
Like the previous configuration change, in order for this adjustment to take effect we must restart the NGINX service.
root@nginx-test:~# service nginx restart
With NGINX restarted, we can run another test with the command.
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second" Requests per second: 6068.41 [#/sec] (mean)
Once again, our parameter change has resulted in a significant increase in performance. With just a small change in , we were able to increase our throughput by requests per second.
Increasing worker threads further
If a small change in can add requests per second, what affect would a much larger change have? The only way to find this out is to make the parameter change and test again.
Let’s go ahead and change the value to .
worker_rlimit_nofile 4096; events { worker_connections 4096; # multi_accept on; }
We can see the value is , but there is also another parameter whose value is . The parameter is used to define the maximum number of open files per worker process. The reason this parameter is now specified is because, when adjusting the number of connections per worker, you must also adjust the open file limitations.
With NGINX, every open connection equates to at least one or sometimes two open files. By setting the maximum number of connections to , we are essentially defining that every worker can open up to files. Without setting the to at least the same value as , we may actually decrease performance, because each worker will try to open new files and would be rejected by the open file limitations or .
With these settings applied, let’s go ahead and rerun our test to see how our changes affect NGINX.
# ab -c 40 -n 50000 http://159.203.93.149/ | grep "per second" Requests per second: 6350.27 [#/sec] (mean)
From the results of the test run, it seems we were able to add about requests per second. While this may not be as significant of a change as our earlier requests per second, this is still an improvement in throughput. As such, we will leave this parameter as is to move on to our next item.