Установка и настройка web-сервера nginx

В этом документе описывается рассматривается процесс установки и настройки web-сервера nginx на ОС NetBSD 2.0.2.

[Сгибнев Михаил (www.dreamcatcher.ru)]

Изменения и дополнения приветствуются. Установка производится на ОС NetBSD 2.0.2

Установка

Скачиваем архив nginx-0.1.41.tar.gz (последняя версия на момент написания статьи) с основного сайта проекта http://sysoev.ru/nginx/download.html. Так же нам понадобятся библиотеки ZLIB и PCRE, которые можно взять с сайта производителя (http://www.gzip.org/zlib/ и http://www.pcre.org/). Распакуем библиотеки:
    
    #tar -xvzf zlib-1.2.3.tar.gz
    #tar -xvzf pcre-6.2.tar.gz
    
Для установки nginx нам потребуется выполнить следующий порядок действий (учитывая, что архивы библиотек и сервера находятся в одном каталоге):
    
    #tar -xvzf nginx-0.1.41.tar.gz
    #cd nginx-0.1.41
    #configure --prefix=/usr/pkg --sbin-path=/usr/pkg/nginx
    --conf-path=/usr/pkg/nginx/nginx.conf
    --pid-path=/usr/pkg/nginx/nginx.pid --with-http_ssl_module
    --with-pcre=../pcre-6.2 --with-zlib=../zlib-1.2.3
    
Мы должны получить примерно такой вывод:
    
    Configuration summary
    + threads are not used
    + using PCRE library: ../pcre-6.2
    + using system OpenSSL library
    + md5 library is not used
    + using zlib library: ../zlib-1.2.3
    
    nginx path prefix: "/usr/pkg/nginx"
    nginx binary file: "/usr/pkg/nginx"
    nginx configuration file: "/usr/pkg/nginx/nginx.conf"
    nginx pid file: "/usr/pkg/nginx/nginx.pid"
    nginx error log file: "/usr/pkg/nginx/logs/error.log"
    nginx http access log file: "/usr/pkg/nginx/logs/access.log"
    nginx http client request body temporary files:
    "/usr/pkg/nginx/client_body_temp"
    nginx http proxy temporary files: "/usr/pkg/nginx/proxy_temp"
    nginx http fastcgi temporary files: "/usr/pkg/nginx/fastcgi_temp"
    
Если библиотеки ZLIB и PCRE были установлены из системы портов, то необходимости скачивать архивы этих библиотек нет, достаточно указать следующие параметры утилиты ./configure:
    
    --with-ld-opt="-L /usr/pkg/lib"
    --with-cc-opt="-I /usr/pkg/include"
    
Тогда вывод будет следующим:
    
    Configuration summary
    + threads are not used
    + using system PCRE library
    + using system OpenSSL library
    + md5 library is not used
    + using system zlib library
    
    nginx path prefix: "/usr/pkg/nginx"
    nginx binary file: "/usr/pkg/nginx"
    nginx configuration file: "/usr/pkg/nginx/nginx.conf"
    nginx pid file: "/usr/pkg/nginx/nginx.pid"
    nginx error log file: "/usr/pkg/nginx/logs/error.log"
    nginx http access log file: "/usr/pkg/nginx/logs/access.log"
    nginx http client request body temporary files:
    "/usr/pkg/nginx/client_body_temp"
    nginx http proxy temporary files: "/usr/pkg/nginx/proxy_temp"
    nginx http fastcgi temporary files: "/usr/pkg/nginx/fastcgi_temp"
    
Компилируем и устанавливаем nginx:
    
    #make
    #sudo make install
    
Если планируется редактирование файлов конфигурации или загрузка файлов в каталоги от имени непривилегированного пользователя, то можно воспользоваться такой командой:
    
    #sudo chown -R mixa /usr/pkg/nginx
    
Для получения более подробной информации о параметрах configure, используйте команду:
    
    #./configure --help
    
    
Одной из полезных опций является --with-cpu-opt, которая позволяет произвести оптимизацию по типу процессора. Доступными параметрами являются: pentium, pentiumpro, pentium4, sparc64.

Настройка

Приступим к настройке сервера.

Как таковых, вариантов развития событий у нас три:
  • Использование в качестве веб-сервера
  • Использование в качестве прокси-сервера
  • Использование в качестве почтового прокси
Разберем сперва, как самый экзотический, третий вариант. Задействовать этот режим можно включив опцию --with-imap при запуске ./configure Смысл заключается в следующем:

Предположим, что у нас есть несколько серверов imap/pop3. Перед ними ставится nginx, который по получении имени и пароля ходит по HTTP к специальному авторизационному серверу.

Если серверу нравится имя и пароль, то он говорит, к какому imap/pop3 серверу нужно присоединиться и продолжить imap/pop3 сессию, после чего nginx просто проксирует данные в обе стороны.

Если же не нравится, то nginx передает клиенту то, что именно не нравится.

Конфигурация, в этом случае, будет выглядеть следующим образом:
    
    events {
       ...
    }
    
    imap {
        #auth_http  unix:/path/socket:/cgi-bin/auth;
        auth_http  localhost:9000/cgi-bin/auth;
    
        pop3_capabilities  "TOP"  "USER";
        imap_capabilities  "IMAP4rev1"  "UIDPLUS";
    
        server {
            listen     110;
            protocol   pop3;
            proxy      on;
        }
    
        server {
            listen     143;
            protocol   imap;
            proxy      on;
        }
    }
    
Структура запроса к серверу авторизации: Запрос:
    
    
    GET /auth HTTP/1.0
    Host: localhost
    Auth-Method: plain
    Auth-Login: user
    Auth-Pass: password
    Auth-Protocol: imap
    Auth-Login-Attempt: 1
    Client-IP: 192.168.1.1
    
Хороший ответ:
    
    HTTP/1.0 200 OK   # this line ignore
    Auth-Status: OK
    Auth-Server: 192.168.2.10
    Auth-Port: 143
    
Плохой ответ:
    
    HTTP/1.0 200 OK   # this line ignore
    Auth-Status: Invalid login or password
    Auth-Wait: 3
    
Во втором случае nginx отдаёт клиенту строку "Invalid login or password", ждёт 3 секунды и снова готов принимать login/password. Рассмотрим теперь первый вариант - использование в качестве полноценного web-сервера. В самой простой конфигурации предполагается отдача статического контента. Рассмотрим такой файл конфигурации:
    
    user testuser;
    worker_processes 5;
    
Указываем имя пользователя и количество одновременно запущенных процессов.
    
    error_log logs/error.log;
    pid logs/nginx.pid;
    
Задаем размещение журнальных файлов и идентификатора процесса.
    
    events {
    connections 1024;
    use kqueue;
    }
    
Как известно, NetBSD 2.0 поддерфивает методы kqueue, select и poll. Два последних являются стандартными для UNIX-систем, но не обеспечивают оптимального быстродействия. Мы будем использовать метод kqueue.
    
    http {
    include conf/mime.types;
    default_type application/octet-stream;
    
    sendfile on;
    tcp_nodelay on;
    keepalive_timeout 0;
    
    gzip on;
    gzip_min_length 1100;
    gzip_comp_level 9
    gzip_types text/plain;
    
В блоке, приведенном выше, мы включили сжатие, установили минимальную длинну ответа, при которой будет использоваться сжатие, указали коэффициент сжатия (9) и тип сжимаемого контента (учтите, что text/html сжимается всегда). Более подробную информацию можно посмотреть по адресу: http://sysoev.ru/nginx/docs/http/ngx_http_gzip_module.html
    
    server {
    listen 80;
    server_name hpux.dreamcatcher.ru  dreamcatcher.ru  www.dreamcatcher.ru;
    charset on;
    source_charset windows-1251;
    
Кодировка документов сайта - windows-1251.
    
    access_log logs/dreamcatcher.log;
    location / {
    root html/dream;
    index index.html index.htm;
    }
    error_page 404 /error/404.html;
    location /dream/error/404.html
    {
    root html;
    charset on;
    source_charset windows-1251;
    }
    }
    }
    
Рано или поздно встанет вопрос выполнения динамических страниц. Оговоримся сразу, что поддержка выполнения сценариев cgi вряд либудет когда-либо реализована в силу трудоемкости. В настоящее время есть возможность выполнения php с помощью fastcgi сервера. Для реализации данной идеи следует выполнить следующий нехитрый набор действий:

Конфигурация, используемая далее, взята с сайта www.nginx.info

Чтобы настроить связку nginx+fastcgi+php необходимо : запустить php как fastcgi сервер (порт или unix сокет), указать nginx отправлять файлы с расширением *.php на fastcgi сервер (пример фалйа конфигурации ниже). php можно запустить, как fastcgi сервер, двумя способами: (в обоих случаях надо сначала собрать php с опцией --enable-fastcgi)
  • непосредсвенно запуская php с опцией -b IP:PORT ( Bind Path for external FASTCGI Server mode). В таком случае php можно заставить соединения только по tcp.
  • используя spawn-fcgi+spawn-php.sh из дистрибутива lighttpd
Пример конфигурации для nginx (начиная с 0.1.29): (это все прописывается в секцию требуемого server {...}) В данном случае, fastcgi принимает запросы через сокет UNIX и все файлы php отправляются к fastcgi серверу
    
    location ~* ^.+\.(php)$ {
    root /var/www/domain/root;
    #fastcgi_pass 127.0.0.1:9000;
    fastcgi_pass unix:/usr/local/fastcgi/fcgi; # сокет
    fastcgi_index index.php;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_header_buffer_size 32k;
    fastcgi_buffers 4 32k;
    fastcgi_busy_buffers_size 32k;
    fastcgi_temp_file_write_size 32k;
    #fastcgi_temp_path /var/tmp;
    #fastcgi_next_upstream error timeout invalid_header http_500 http_404;
    #fastcgi_next_upstream error timeout;
    fastcgi_x_powered_by off; # default on
    fastcgi_redirect_errors on; # для отображения своих страниц об ошибках
    fastcgi_x_powered_by off; # убираем отображение версии php, X-Powered..
    fastcgi_param   DOCUMENT_ROOT   /path/to/host_root;
    fastcgi_param   SCRIPT_FILENAME /path/to/host_root$fastcgi_script_name;
    fastcgi_param   PATH_TRANSLATED /path/to/host_root$fastcgi_script_name;
    fastcgi_param   SCRIPT_NAME  $fastcgi_script_name;
    fastcgi_param   QUERY_STRING    $query_string;
    fastcgi_param   CONTENT_TYPE    $content_type;
    fastcgi_param   CONTENT_LENGTH  $content_length;
    fastcgi_param   REDIRECT_STATUS 200; # if php build with option --enable-forece-cgi-redirect
    #additional system call is made, without need it is better to not use
    fastcgi_param   SERVER_ADDR     $server_addr; 
    fastcgi_param   SERVER_PORT     $server_port;
    fastcgi_param   SERVER_PROTOCOL $server_protocol;
    fastcgi_param   SERVER_SOFTWARE "nginx/0.1.30";
    fastcgi_param   GATEWAY_INTERFACE       "CGI/1.1";
    fastcgi_param   SERVER_NAME     $server_name;
    fastcgi_param   REQUEST_URI     $request_uri;
    fastcgi_param   REQUEST_METHOD  $request_method;
    fastcgi_param   REMOTE_USER     $remote_user;
    fastcgi_param   REMOTE_ADDR     $remote_addr;
    fastcgi_param   REMOTE_PORT     $remote_port;
    }
    
Возможен мониторинг состояния nginx с помощью Munin. Вот пример конфигурационных файлов nginx_request.txt
    
    #!/usr/bin/perl -w
    #
    # Magic markers:
    #%# family=auto
    #%# capabilities=autoconf
    
    my $ret = undef;
    
    if (! eval "require LWP::UserAgent;"){
    	$ret = "LWP::UserAgent not found";
    }
    
    chomp(my $fqdn=`hostname -f`);
    
    my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://$fqdn/nginx_status";
    
    if ( exists $ARGV[0] and $ARGV[0] eq "autoconf" )
    {
    	if ($ret){
    		print "no ($ret)\n";
    		exit 1;
    	}
    	
    	my $ua = LWP::UserAgent->new(timeout => 30);
        my $response = $ua->request(HTTP::Request->new('GET',$URL));
    
    	unless ($response->is_success and $response->content =~ /server/im)
    	{
    		print "no (no nginx status on $URL)\n";
    		exit 1;
    	}
    	else
    	{
    		print "yes\n";
    		exit 0;
    	}
    }
    
    if ( exists $ARGV[0] and $ARGV[0] eq "config" )
    {
    	print "graph_title NGINX requests\n";
        print "graph_args --base 1000\n";
    	print "graph_category nginx\n";
        print "graph_vlabel Request per second\n";
    
        print "request.label req/sec\n";
        print "request.type COUNTER\n";
    	print "request.label requests $port\n";
    	print "request.draw LINE2\n";
    	
    	exit 0;
    }
    
    my $ua = LWP::UserAgent->new(timeout => 30);
    
    my $response = $ua->request(HTTP::Request->new('GET',$URL));
    
    if ($response->content =~ /^\s+(\d+)\s+(\d+)\s+(\d+)/m) {
        print "request.value $3\n";
    } else {
        print "request.value U\n";
    }
    
    # vim:syntax=perl
    
и nginx_status.txt
    
    #!/usr/bin/perl -w
    #
    # Magic markers:
    #%# family=auto
    #%# capabilities=autoconf
    
    my $ret = undef;
    
    if (! eval "require LWP::UserAgent;"){
    	$ret = "LWP::UserAgent not found";
    }
    
    chomp(my $fqdn=`hostname -f`);
    
    my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://$fqdn/nginx_status";
    
    if ( exists $ARGV[0] and $ARGV[0] eq "autoconf" )
    {
    	if ($ret){
    		print "no ($ret)\n";
    		exit 1;
    	}
    	
    	my $ua = LWP::UserAgent->new(timeout => 30);
        my $response = $ua->request(HTTP::Request->new('GET',$URL));
    
    	unless ($response->is_success and $response->content =~ /server/im)
    	{
    		print "no (no nginx status on $URL)\n";
    		exit 1;
    	}
    	else
    	{
    		print "yes\n";
    		exit 0;
    	}
    }
    
    if ( exists $ARGV[0] and $ARGV[0] eq "config" )
    {
    	print "graph_title NGINX status\n";
        print "graph_args --base 1000\n";
    	print "graph_category nginx\n";
        print "graph_vlabel Connections\n";
    
        print "total.label Active connections\n";
    	print "total.info  Active connections\n";
    	print "total.draw LINE2\n";
    
        print "reading.label Reading\n";
    	print "reading.info  Reading\n";
    	print "reading.draw LINE2\n";	
    
        print "writing.label Writing\n";
    	print "writing.info  Writing\n";
    	print "writing.draw LINE2\n";	
    
        print "waiting.label Waiting\n";
    	print "waiting.info  Waiting\n";
    	print "waiting.draw LINE2\n";	
    	
    	exit 0;
    }
    
    my $ua = LWP::UserAgent->new(timeout => 30);
    
    my $response = $ua->request(HTTP::Request->new('GET',$URL));
    
    #Active connections: 1845 
    #server accepts handled requests
    # 4566318 4566318 84218236 
    # Reading: 2 Writing: 278 Waiting: 1565 
    if ($response->content =~ /Active connections:\s+(\d+).*Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/s) {
        print "total.value $1\n";
        print "reading.value $2\n";
        print "writing.value $3\n";
        print "waiting.value $4\n";
    } else {
    	foreach (qw(total reading writing waiting)){
    	    print "$_.value U\n";
    	}
    }
    
    # vim:syntax=perl
    
Результат:
pics.rate.ee-nginx_request-day.png
pics.rate.ee-nginx_request-month.png
pics.rate.ee-nginx_request-week.png
pics.rate.ee-nginx_request-year.png
pics.rate.ee-nginx_status-day.png
pics.rate.ee-nginx_status-month.png
pics.rate.ee-nginx_status-week.png
pics.rate.ee-nginx_status-year.png
(совет предоставлен Андреем Ситниковым).

Дополнительную информацию можно получить на сайте, посвященному nginx - http://nginx.info/ Пример, когда nginx выступает в роли прокси-сервера, достаточно подробно рассмотрен на странице http://www.sysoev.ru/nginx/docs/example.html.

[ опубликовано 08/12/2006 ]

Сгибнев Михаил (www.dreamcatcher.ru) - Установка и настройка web-сервера nginx   Версия для печати