LNMP веб-сервер - nginx & mysql & phpПодписка на Комментарии к "LNMP веб-сервер - nginx & mysql & php"

Аватар zenon

Решил обновить свой веб-сервер - давно уже вышел Nginx 1.0.0 - пора бы уже... но после обновления нарвался на полную неработоспособность его, поэтому пришлось изрядно помучаться дабы нормально его запустить, вся установка проделывалась на чистом установленном netinstall Debian Squeeze 6.01, плюс использую репозиторий для LAMP / LNMP серверов www.dotdeb.org, где есть самые свежие версии Apache, Nginx, Mysql и Php для стабильной ветки Debian.
Если у вас был установлен LAMP или LLMP, то Apache или Lighttpd необходимо удалить. Также предупреждаю не проделывайте данные операции на продакшн сервере, предварительно не создав резервной копии, дабы всегда можно было откатиться назад. Прежде чем запустить всё делал на Kvm.

  • Напомню основное про Nginx:
    Основная функциональность HTTP-сервера:
    - обслуживание статических запросов, индексных файлов, автоматическое создание списка файлов, кэш дескрипторов открытых файлов;
    - акселерированное проксирование с кэшированием, простое распределение нагрузки и отказоустойчивость;
    - акселерированная поддержка удалённых FastCGI серверов с кэшированием, простое распределение нагрузки и отказоустойчивость;
    - модульность, фильтры, в том числе сжатие (gzip), byte-ranges (докачка), chunked ответы, XSLT-фильтр, SSI-фильтр, преобразование изображений; несколько подзапросов на одной странице, обрабатываемые в SSI-фильтре через прокси или FastCGI, выполняются параллельно.
    - поддержка SSL и расширения TLS SNI;
    Функциональность почтового прокси-сервера:
    - MAP и POP3: перенаправление пользователя на IMAP или POP3-бэкенд с использованием внешнего HTTP-сервера аутентификации;
    - SMTP: проверка пользователя с помощью внешнего HTTP-сервера аутентификации и перенаправление соединения на внутренний SMTP-сервер;
    методы аутентификации:
    - POP3: USER/PASS, APOP, AUTH LOGIN/PLAIN/CRAM-MD5;
    - IMAP: LOGIN, AUTH LOGIN/PLAIN/CRAM-MD5;
    - SMTP: AUTH LOGI/ PLAIN/CRAM-MD5;
    - поддержка SSL;
    - поддержка STARTTLS и STLS;
    Официальный сайт Nginx http://sysoev.ru/
    Основное отличие от многих мануалов в сети, то что тут у нас обмен данными между Nginx и Php происходит через unix socket (unix:/tmp/php-fpm.sock), а не через порт tcp (upstream 127.0.0.1:9000).


  • Итак приступим.

  • Шаг 1: редактируем sources.list:
    $ nano /etc/apt/sources.list
    # Официальный репозиторий Debian
    deb ftp://ftp.ru.debian.org/debian/ stable main contrib non-free
    # Debian Squeeze - обновления
    deb ftp://ftp.ru.debian.org/debian squeeze-updates main
    # Debian Squeeze - обновления безопасности
    deb ftp://ftp.ru.debian.org/debian-security squeeze/updates main non-free contrib
    # Debian Squeeze - backports
    deb ftp://ftp.ru.debian.org/debian-backports squeeze-backports main contrib
    # Debian Squeeze - proprsed - updates
    deb ftp://ftp.ru.debian.org/debian squeeze-proposed-updates main contrib non-free
    # Dotdeb - The repository for Debian-based LAMP servers
    deb http://packages.dotdeb.org stable all

    Далее стандартно выполняем следующие:
    Устанавливаем ключ для Dotdeb:
    $ wget http://www.dotdeb.org/dotdeb.gpg
    $ cat dotdeb.gpg | apt-key add -
    $ rm -v dotdeb.gpg

    Обновляемся:
    $ aptitude update
    $ aptitude full-upgrade

    Теперь можно начать установку LNMP сервера:
    Сам nginx:
    $ aptitude install nginx
    Или nginx-common nginx-extras:
    $ aptitude install nginx-common nginx-extras
    Php5 и модули:
    $ aptitude install php5 php5-cli php5-common php5-fpm php5-cgi php5-curl php5-gd php5-apc
    Mysql и php-mysql:
    $ aptitude install mysql-server mysql-client php5-mysql
    Также если это "свежая" установка я обычно сразу ставлю необходимые мелочи:
    $ aptitude install vim vsftpd grc zsh most mc firmware-linux-free zip unzip p7zip-full hwinfo unrar rar rsync
  • Шаг 2: Подготовка каталога для нашего сервера. Создадим /var/www, если его нет, назначим владельца и выставим права на него:
    $ mkdir /var/www
    $ chmod 755 /var/www
    $ chown www-data:www-data /var/www

    Создадим от имени пользователя www-data тестовый файл php, для проверки работоспособности:
    $ su www-data -c "echo '< ?php phpinfo(); ?> ' > /var/www/index.php &"
  • ВАЖНО. выставление правильных прав на директории/файлы (755/644) - Измените /var/www в соответствии с вашими установками.
    Для всех директорий в /var/www выставить права 755.
    Для всех обычных файлов в /var/www назначить владельцем www-data, группа www-data.
    Для всех обычных файлов в /var/www выставить права 644.

    $ find /var/www -type d -exec chmod 755 {} +
    $ find /var/www -type f -exec chown www-data:www-data {} +
    $ find /var/www -type f -exec chmod 644 {} +
  • Шаг 3: Настраиваем php.
    Сам по себе nginx понимает только html, для того чтобы он начал понимать php существует модуль php-fpm (который мы уже установили), теперь необходимо его настроить. Есть два способа которыми этот обмен может происходить: через tcp порт (по умолчанию) или через юникс сокет.
    Настраивается это в файле /etc/php5/fpm/pool.d/www.conf:
    $ nano /etc/php5/fpm/pool.d/www.conf

    Если мы хотим чтобы обмен происходил через порт - просто убеждаемся что строчка listen = 127.0.0.1:9000 присутствует и не закоментирована.
    Но я всё же рекомендую настроить через сокет, для этого поставим знак комментария (для php конф. файла это";") перед listen = 127.0.0.1:9000 и добавим listen = /tmp/php-fpm.sock
    ; listen = 127.0.0.1:9000
    listen = /tmp/php-fpm.sock
  • Шаг 4: Конфигурация сервера /etc/nginx/sites-available/default:
    Соответсвенно с предидущими настройками редактируем строку fastcgi_pass unix:/tmp/php-fpm.sock; - для сокета или fastcgi_pass 127.0.0.1:9000; - для порта.
    На выбор - две конфигурации, минимальная, и той которой пользуюсь сам:
    $ nano /etc/nginx/sites-available/default

    Минимальная:
    server {
        listen   80;
        server_name localhost;
        charset utf-8;
        access_log  /var/www/access.log;
        error_log /var/www/error_log;
        location = / {
            root   /var/www;
            index  index.php index.html;
        }
        # mod_rewrite - чтобы работали ЧПУ (постоянные ссылки) в различных CMS
        rewrite_log off;
        if (!-e $request_filename) {
           rewrite (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ /index.php last;
        }
        #  Images and static content is treated different
        location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|swf|flv)$ {
            access_log off;
            expires 30d;
            root /var/www;
            break;
        }
        location ~ \.php$ {
            fastcgi_pass   unix:/tmp/php-fpm.sock;
            # fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
            include fastcgi_params;
        }
        # Запрещаем просмотр .htaccess & .htpassword
        location ~ /\.ht {
            deny  all;
        }
    }

    Мой конфиг:
    # -------------------------------------------------------------------------------- #
    #                         Последние изменение 17.05.2011                           #
    # -------------------------------------------------------------------------------- #
    server {
        listen   80;                          ## listen for ipv4
        listen   [::]:80 default ipv6only=on; ## listen for ipv6
        server_name localhost;
        server_name_in_redirect off;
        root /var/www;
        index index.php;
        charset utf-8;
    # -------------------------------------------------------------------------------- #
        # Логи доступа:
        # access_log /var/www/access_log;
        access_log /dev/null;
        # Error log's
        # error_log /var/www/error_log;
        error_log /dev/null;
    # -------------------------------------------------------------------------------- #
        # страницы с ошибками, вместо стандартных, путь указывается от root (выше)
        # error_page      404     /error/404.html;
        # error_page      403     /error/403.html;
        # error_page      500     /error/500.html;
    # -------------------------------------------------------------------------------- #
        # mod_rewrite - чтобы работали ЧПУ (постоянные ссылки) в различных CMS
        rewrite_log off;
        if (!-e $request_filename) {
           rewrite (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ /index.php last;
        }
    # -------------------------------------------------------------------------------- #
        gzip_static on;
    # -------------------------------------------------------------------------------- #
        #  Images and static content is treated different
        location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|swf|flv)$ {
            access_log off;
            expires 30d;
            root /var/www;
            break;
        }
    # -------------------------------------------------------------------------------- #
        # Parse all .php file in the /var/www directory
        location ~* ^.+.(php|cgi)$ {
        # location ~ .php$ {
            include fastcgi_params;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_index  index.php;
            fastcgi_pass   unix:/tmp/php-fpm.sock;
            # fastcgi_pass   127.0.0.1:9000;
            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;

            fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            fastcgi_param  DOCUMENT_URI       $document_uri;
            fastcgi_param  DOCUMENT_ROOT      /var/www/$host;
            fastcgi_param  SERVER_PROTOCOL    $server_protocol;

            fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

            fastcgi_param  REMOTE_ADDR        $remote_addr;
            fastcgi_param  REMOTE_PORT        $remote_port;
            fastcgi_param  SERVER_ADDR        $server_addr;
            fastcgi_param  SERVER_PORT        $server_port;
            fastcgi_param  SERVER_NAME        $server_name;
            fastcgi_intercept_errors         off;
            fastcgi_ignore_client_abort      off;
            fastcgi_connect_timeout           60;
            fastcgi_send_timeout             180;
            fastcgi_read_timeout             180;
            fastcgi_buffer_size             128k;
            fastcgi_buffers               4 256k;
            fastcgi_busy_buffers_size       256k;
            fastcgi_temp_file_write_size    256k;
            # uwsgi_pass      127.0.0.1:3031;
            # include         uwsgi_params;
        }
    # -------------------------------------------------------------------------------- #
        # Запрещаем просмотр .htaccess & .htpassword
        location ~ /\.ht {
            deny  all;
        }
    }
    # -------------------------------------------------------------------------------- #
    # Дальше установки по-умолчанию, (стандартная установка nginx),
    # вдруг понадобяться.
    # -------------------------------------------------------------------------------- #
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #       listen 8000;
    #       listen somename:8080;
    #       server_name somename alias another.alias;
    #       root html;
    #       index index.html index.htm;
    #
    #       location / {
    #               try_files $uri $uri/ /index.html;
    #       }
    #}

    # HTTPS server
    #
    #server {
    #       listen 443;
    #       server_name localhost;
    #
    #       root html;
    #       index index.html index.htm;
    #
    #       ssl on;
    #       ssl_certificate cert.pem;
    #       ssl_certificate_key cert.key;
    #
    #       ssl_session_timeout 5m;
    #
    #       ssl_protocols SSLv3 TLSv1;
    #       ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
    #       ssl_prefer_server_ciphers on;
    #
    #       location / {
    #               try_files $uri $uri/ /index.html;
    #       }
    #}
    # -------------------------------------------------------------------------------- #
  • Шаг 5: Рестарт для php5-fpm и nginx:
    $ /etc/init.d/php5-fpm restart

    $ /etc/init.d/nginx restart
  • Теперь надо зайти на свой сайт, где должны лицизреть сгенерированную страницу с php- информацией:

    если нет то что-то пошло не так, ошибки смотрим так:

    $ tail /var/log/nginx/error.log
    $ tail /var/www/error_log

    Например ошибки mysql 'Access denied' смотрим тут: Access_denied

    На этом всё наш сервер готов.

  • Теперь немного тестов: (тестировал утилитой siege - установил на виртуалку (испоользую kvm) - wordpress и накидал примерно 20 постов, создал текстовый файл со списком ссылок на эти посты и скормил его siege:
    Как использовать siege.
  • $ siege -v -i -c 20 -t 1m -f sitemap
    ** SIEGE 2.70
    ** Preparing 20 concurrent users for battle.
    ....
    ....
    ....
    Lifting the server siege...  done.
    Transactions:                349 hits
    Availability:                100.00 %
    Elapsed time:                59.97 secs
    Data transferred:            3.99 MB
    Response time:               2.81 secs
    Transaction rate:            5.82 trans/sec
    Throughput:                  0.07 MB/sec
    Concurrency:                 16.37
    Successful transactions:     349
    Failed transactions:         0
    Longest transaction:         5.50
    Shortest transaction:        2.09

    Тест сервера на kvm (1Gb RAM) – движок wordpress, постов около 30, ссылки на посты в файле sitemap, нагрузка в 100 пользователей, в течении часа:

    $ siege -v -i -c 100 -t 60m -f sitemap
    ** SIEGE 2.70
    ** Preparing 25 concurrent users for battle.
    The server is now under siege...
    ....
    ....
    ....
    Lifting the server siege...  done.
    Transactions:                18038 hits
    Availability:                100.00 %
    Elapsed time:                3599.17 secs
    Data transferred:            210.67 MB
    Response time:               19.39 secs
    Transaction rate:            5.01 trans/sec
    Throughput:                  0.06 MB/sec
    Concurrency:                 97.20
    Successful transactions:     18038
    Failed transactions:         0
    Longest transaction:         27.96
    Shortest transaction:        7.48

    Кросс ссылка.
    Обсуждали, тестировали тут.

    Похожие материалы:
    Аватар user

    Добрый день, сделал всё как в статье (конфиг /etc/nginx/sites-available/default взял Ваш) на домашнем сервере, в итоге просто пустая страница открывается, перезагрузка сервисов и компьютера не помогает. В чём может быть проблема?

    Аватар user

    В минимальном конфиге, отображается белая страница с надписью , видимо php не работает.

    Аватар zenon

    Для проверки тестовую страницу надо сделать, и минимальную конфигурацию бери.
    В корень хоста например так
    echo '< ?php phpinfo(); ?> ' > /var/www/myserver/test.php
    Если не заработает попробуй простой html, чтобы убедиться в чем проблема, точно ли с php?

    Вот примерно мой конфиг для Drupal:
    /etc/nginx/nginx.conf

    # .................................................................... #
    # Имя пользователя от которого запускается nginx (в debian - www-data)
    user                             nginx nginx;
    # Количество запускаемых процессов (обычно = кол-ву ядер в процессоре)
    worker_processes                 4;
    # [ debug | info | notice | warn | error | crit ]
    error_log                        /var/log/nginx/error_log info;
    worker_rlimit_nofile             8192;
    pid                              /var/run/nginx.pid;
    # .................................................................... #
    events {
        worker_connections           4096;
        # use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ;
        use                          epoll;
    }
    # .................................................................... #
    http {
       log_format                   main
       '$remote_addr - $remote_user [$time_local] '
       '"$request" $status $bytes_sent '
       '"$http_referer" "$http_user_agent" '
       '"$gzip_ratio"';
       default_type                 application/octet-stream;

       client_header_timeout        10m;
       client_body_timeout          10m;
       send_timeout                 10m;

       connection_pool_size         256;
       client_header_buffer_size    1k;
       large_client_header_buffers  4 4k;
       request_pool_size            4k;

       gzip                         on;
       gzip_min_length              1024;
       gzip_buffers                 16 8k;
       gzip_proxied                 expired no-cache no-store private auth;
       gzip_comp_level              5;
       gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # do not compress for IE1-6
       gzip_types text/plain text/css application/json application/x-javascript
                  text/xml application/xml application/xml+rss text/javascript;
       output_buffers               1 32k;
       postpone_output              1460;
       sendfile                     on;
       tcp_nopush                   on;
       tcp_nodelay                  on;
       keepalive_timeout            75 20;
       ignore_invalid_headers       on;
       include                      /etc/nginx/mime.types;
       include                      /etc/nginx/fastcgi.conf;
       include                      /etc/nginx/fastcgi_params;
       # If we set index here, we won't have to anywhere else
       index index.php index.html index.htm;

       # We don't want someone to visit a default site via IP
       # So we catch all non-defined Hosts or blank hosts here
       # the default listen will cause this server block to be used
       # when no matching hostname can be found in other server blocks
       server {
          # use default instead for nginx 0.7.x, default_server for 0.8.x+
          listen 80 default_server;
     
          # if no listen is specified, all IPv4 interfaces on port 80 are
          # listened to listen on both IPv4 and IPv6 as well, listen [::]
          # and 0.0.0.0 must be specified.
          server_name _;
          return 444;
       }

       # Virtual HOSTS ............ Сюда добавляем наши виртуальные хосты #
       # include /etc/nginx/conf.d/*.conf;
       # include /etc/nginx/vhosts/*.conf;
       include                      /etc/nginx/drupal-v-host.conf;
       # ................................................................ #

       # SSL example
       # server {
       # listen 127.0.0.1:443;
       # server_name localhost;
       # ssl on;
       # ssl_certificate /etc/ssl/nginx/nginx.pem;
       # ssl_certificate_key /etc/ssl/nginx/nginx.key;
       # access_log /var/log/nginx/localhost.ssl_access_log main;
       # error_log /var/log/nginx/localhost.ssl_error_log info;
       # root /var/www/localhost/htdocs;
       # }
    }
    # .................................................................... #

    /etc/nginx/drupal-v-host.conf

    # main production site
    server {
      charset utf-8;
      server_name example.drupal.com;
      access_log /var/www/example.drupal.com/access.log main;
      error_log  /var/www/example.drupal.com/error.log warn;
      root /var/www/example.drupal.com;
      # search for already compressed files
      # gzip_static on;
      gzip on;
      # some images have no mime type
      default_type image/jpeg;
      # Buffers definition. allows of up to 260k to be passed in memory.
      client_body_buffer_size 1m;
      proxy_buffering         on;
      proxy_buffer_size       4k;
      proxy_buffers           8 32k;
      # 404 generated from php can be rather slow. Uncomment with care
      # error_page  404              /index.php;
      # disallow access to version control directory, but return 404, not to disclose$
      location /.git { return 404; }
      # robots.txt is important for search engines
      location /robots.txt { access_log off; }
      # This is mostly based on Drupal's stock .htaccess
      location ~* ^.+(\.(txt|engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template)$ {
        return 404;
      }
      # serve imagecache files directly or redirect to drupal if they do not exist
      location ~* imagecache {
        access_log off;
        expires 30d;
        try_files $uri @drupal;
      }
      # Drupal 7 image stylef
      location ~* image/generate {
        access_log off;
        expires 30d;
        try_files $uri @drupal;
      }
      # serve static files directly
      location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|swf|flv)$ {
        access_log        off;
        expires           30d;
      }
      # This rewrites pages to be sent to PHP processing
      location @drupal {
        index index.php;
        if (!-e $request_filename) {
          rewrite ^/(.*)$ /index.php?q=$1 last;
        }
      }
      location / {
        try_files $uri @cache;
      }
      # This will try to see if we have a boost file in place. no harm done if this is not used
      location @cache {
        # queries, drupal cookies, or not GET methods, all require PHP processing.
        if ($query_string ~ ".+") {
          return 405;
        }
        if ($http_cookie ~ "DRUPAL_UID" ) {
          return 405;
        }
        if ($request_method !~ ^(GET|HEAD)$ ) {
          return 405;
        }
        error_page 405 = @drupal;
        # Drupal uses 1978 - I am 4 years older than Dries :)
        add_header Expires "Tue, 22 Sep 1974 08:00:00 GMT";
        add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
        try_files /cache/normal/$host/${uri}_.html /cache/perm/$host/${uri}_.css /cache/perm/$host/${uri}_.js /cache/$host/0$uri.html /cache/$host/0${uri}/index.html @drupal;
      }
      # only a few php files are allowed, this increases the overall server security
      location ~* ^/(index|boost_stats|cron|xmlrpc).php$ {
          # Use your own port of fastcgi here
          fastcgi_pass   unix:/tmp/php-fpm.sock;
          fastcgi_index  index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      }
      # internal pages are protected with a simple htpasswd
      #
      location ~* ^/(install|update|memcached|apc|info).php$ {
        auth_basic "Restricted Area";
        auth_basic_user_file htpasswd;
          # Use your own port of fastcgi here
          fastcgi_pass   unix:/tmp/php-fpm.sock;
          fastcgi_index  index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      }
      location ~* ^.+\.php$ {
        return 404;
      }
      location /nginx_status {
       auth_basic "Restricted Area";
       auth_basic_user_file htpasswd;

       stub_status on;
       access_log  off;
       allow 127.0.0.1;
       # Add IP adresses you want to allow
       # allow n.n.n.n;
       deny all;
      }
    }

    Вот еще места где информацию искать:
    ссылка два
    ссылка раз
    ссылка три
    Вообще у nginx конфиги своеобразные, искать ошибки, тщательно все проверять,...

    Добавить комментарий