Настройка nginx для хостинга

// Март 20th, 2011 // Highload, Memcached, PHP, Веб-разработка

В последнее время замечаю большой интерес к nginx, и организации веб-сервера на его основе.
UP 20.11.2011
Если раньше строили двухзвенную систему (фронтэнд — Nginx, бекэнд — Apache), то сейчас постепенно переходят только на Nginx, полностью отказываясь от Apache. Для таких случаев можно использовать следующий конфиг:

# PHP-FPM (backend)
upstream php-fpm {
	server 127.0.0.1:9000;
}

# Сервера кэширования
upstream memcaches {
	server 127.0.0.1:11211;
}

# Конфиг Nginx (frontend)
server {

  # Защита от бага http://forum.nginx.org/read.php?2,154025,154036
   server_name_in_redirect off;

  # Порт, принимаемые HOST и путь к сайту
  listen 80;
  server_name   site1.ru
		*.site1.ru
		site2.ru
		*.site2.ru;

  set $www_folder '/home/webuser';
  set $root_path '$www_folder/$host/html';
  root $root_path;
  index index.htm index.html index.php;

  # Запросы непосредственно .php-файлов, например index.php (не кэшируются)
  location ~ \.php$ {
	include /etc/nginx/fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $root_path/$fastcgi_script_name;
	fastcgi_param DOCUMENT_ROOT $root_path; # этот параметр нужен несмотря на root в секции server
        fastcgi_pass php-fpm;
  }
  # Копия предыдущего для internal переадресации
  location @phpscripts {
	include /etc/nginx/fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $root_path/$fastcgi_script_name;
	fastcgi_param DOCUMENT_ROOT $root_path; # этот параметр нужен несмотря на root в секции server
        fastcgi_pass php-fpm;
  }

 # Запросы отдельных php-файлов (кэшируются)
 location /utils {
 default_type text/html;
 root  $root_path;
 set             $memcached_key   'nginx_$host$uri?$args';
 memcached_pass  memcaches;
 error_page      404 502 504 405 = @phpscripts;
 }

 # Остальные запросы также идут на PHP-FPM, если $uri не существует (через memcache)
  location / {
     default_type text/html;
     root  $root_path;

     if (!-e $request_filename) {
        return 404;
     }

     error_page      404 502 504 403 405 = @php;
  }

  # Веб-приложение
  location @php {
	include /etc/nginx/fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $root_path/index.php;
        fastcgi_pass php-fpm;
  }

  # Переопеределение 502 ошибки
  error_page	502 = /502.htm;
  location = /502.htm {
         root  $www_folder;
  }  

  # Для js, css, swf, ico и т.д.
  location ~* \.(css|js|swf|ico|png|jpg|gif|jpeg)$ {
	root  $root_path;
	access_log   off;
        expires      30d;
  }

  # Защита от просмотра .htaccess и .htpasswd файлов
  location ~ /\.ht {
	deny  all;
  }

  # Защита от просмотра svn-файлов
  location ~ /.svn/ {
 	deny all;
  } 

  # Статус запросы (/status) и пинг(/ping) запросы от системы мониторинга
  location ~ ^/(status|ping)$ {
      include fastcgi_params;
      fastcgi_pass 127.0.0.1:9000;
      fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
      allow 127.0.0.1;
      deny all;
  }
}

Если будут вопросы, пишите в комментах.

Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


16 Responses to “Настройка nginx для хостинга”

  1. Не подскажите как обьяснить nginx-у что .jpeg = .JPEG?
    Меня вот этот кусочек интересует:
    # Для js, css, swf, ico и т.д.
    location ~* \.(css|js|swf|ico|png|jpg|gif|jpeg)$ {
    root $root_path;
    access_log off;
    expires 30d;
    }

  2. dex157:

    Здравствуйте, а зачем писать location @phpscripts, разве где то это используется в коде?

    • google.com Андрей Токарчук:

      Пардоньте, забыл одну секцию. См. /utls в коняиге. Это нужно для запросов вне веб-приложения.

  3. Анон:

    Добрый день. У меня с данным конфигом проблема.

    nginx |nginx: [warn] server name «/var/www» has suspicious symbols in /etc/nginx/vhosts.d/test1:18

    nginx: [emerg] no port in upstream «memcaches» in /etc/nginx/vhosts.d/test1:66

    что мне подправить, что бы довести до работоспособности его?

    • google.com Андрей Токарчук:

      Для этого надо добавить кусок в начало файла (в статье тоже обновил):

      # Сервера кэширования
      upstream memcaches {
      server 127.0.0.1:11211;
      }

      И прописать нормальный server_name, например такой:

      server_name mydomain.ru;

      Хотя вообще странно, что он так ругается. У меня с масками нормально работает.

  4. myopenid.com ErgallM:

    Предлагаю вынести директивы upstream php-fpm и upstream memcaches в /etc/nginx/nginx.conf в директиву html, это даст нам возможность указывать директивы в одном глобальном месте и для всех сайтов + не будет ошибки о дублировании upstream есть вы создаете несколько файлов в /etc/nginx/sites-available.

    • google.com Андрей Токарчук:

      Согласен. У меня обычно один файл в /etc/nginx/sites-available для всех сайтов, поэтому такой ошибки не возникает. Однако если их много, то да — лучше вынести в общий конфиг.

  5. conroe9:

    А вы не подскажите? Есть сайт в локалке недавно перенес на nginx 1.0.5 ,на сайте контент фильмы и т.д отдача по http вот кусок php скрипта :

    if(isset($_SERVER[‘HTTP_USER_AGENT’]) and strpos($_SERVER[‘HTTP_USER_AGENT’],’MSIE’))
    Header(‘Content-Type: application/force-download’);
    else
    */
    Header(‘Content-Type: application/octet-stream’);
    header(‘Accept-ranges: bytes’);
    header(‘Content-Length: ‘.$f_size);
    header(«Content-disposition: attachment; filename=\»$fname\»»);
    $dwnld=$bd->QUERY(«insert cont_stat set stat_obj=?, stat_objtype=?, stat_date=?, stat_act=?, stat_ip=?»,$file[‘owner’],$tp,time(),’download_start’,$_SERVER[‘REMOTE_ADDR’]);
    $handle = @fopen($file[‘link’], «rb»);
    fpassthru($handle);
    fclose($handle);
    $bd->QUERY(«update cont_stat set stat_date=?, stat_act=? where stat_id=?»,time(),’download_complete’,$dwnld);
    switch($type){
    case ‘flm’:
    $bd->QUERY(«update cont_films set film_rait=film_rait+1, film_lastdate=? where film_id=?»,time(),$file[‘owner’]);
    break;
    case ‘prg’:
    $bd->QUERY(«update cont_progs set prog_rait=prog_rait+1, prog_lastdate=? where prog_id=?»,time(),$file[‘owner’]);
    break;
    case ‘mus’:
    $bd->QUERY(«update cont_mus set mus_rait=mus_rait+1, mus_lastdate=? where mus_id=?»,time(),$file[‘owner’]);
    break;
    case ‘gam’:
    $bd->QUERY(«update cont_games set gam_rait=gam_rait+1, gam_lastdate=? where gam_id=?»,time(),$file[‘owner’]);
    break;
    }
    }
    else header(«Location: error-norights»);
    }
    else header(«Location: error-nofile»);
    ****************************************************************************************************************
    возможно ли кэшировать контент на ssd диск ?
    уже бьюсь месяц и не пойму как это реализовать рабочий конфиг сервера получился вот такой:
    ***********************************************************************************************************************
    server {
    listen 80;
    server_name localhost;

    root /home/ariadna/www;
    index index.php;
    client_max_body_size 100M;
    client_body_buffer_size 128k;

    location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
    }
    location /phpmyadmin {
    alias /usr/share/phpmyadmin;
    index index.html index.htm index.php;
    break;
    }
    location /www {
    alias /var/cache/munin/www;
    index index.php index.html index.htm;
    break;
    }

    location /admin {
    rewrite ^/admin~ /index.php?page=admin? last;
    }

    location / {
    rewrite ^/down~(.*)-(.*)$ /download.php?type=$1&id=$2? last;
    rewrite ^/error-(.*)$ /index.php?page=Error&id=$1? last;
    rewrite ^/film-(.*)$ /index.php?page=film&id=$1 last;
    rewrite ^/gallery-(.*)$ /index.php?page=gal&id=$1? last;
    rewrite ^/Kino~j(.*)-(.*)$ /index.php?page=Kino&janr=$1&id=$2? last;
    rewrite ^/Kino~n(.*)-(.*)$ /index.php?page=Kino&name=$1&id=$2? last;
    rewrite ^/prog-(.*)$ /index.php?page=prog&id=$1? last;
    rewrite ^/progs~j(.*)-(.*)$ /index.php?page=progs&janr=$1&id=$2? last;
    rewrite ^/progs~n(.*)-(.*)$ /index.php?page=progs&name=$1&id=$2? last;
    rewrite ^/music-(.*)$ /index.php?page=music&id=$1? last;
    rewrite ^/musics~j(.*)-(.*)$ /index.php?page=musics&janr=$1&id=$2? last;
    rewrite ^/musics~n(.*)-(.*)$ /index.php?page=musics&name=$1&id=$2? last;
    rewrite ^/game-(.*)$ /index.php?page=game&id=$1? last;
    rewrite ^/games~j(.*)-(.*)$ /index.php?page=games&janr=$1&id=$2? last;
    rewrite ^/games~n(.*)-(.*)$ /index.php?page=games&name=$1&id=$2? last;
    rewrite ^/top-(.*)$ /index.php?page=top&type=$1? last;
    rewrite ^/(.*)-(.*)$ /index.php?page=$1&id=$2? last;
    rewrite ^/([A-Za-z0-9\_\-]+)$ /index.php?page=$1? last;
    }
    error_page 404 403 500 /404.php;

    location ~ \.php$ {
    #fastcgi_pass 127.0.0.1:9000;
    fastcgi_pass unix:/tmp/php5-fpm.sock;
    fastcgi_index index.php;
    #fastcgi_cache_path /ssd/data/fastcgi_temp 1 2;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 360;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 32 256k;
    fastcgi_busy_buffers_size 512k;
    fastcgi_temp_file_write_size 512k;
    fastcgi_max_temp_file_size 0;
    }

    location ~ /\.ht {
    deny all;
    }
    }

    ****************************************************************************************************************
    Буду очень благодарен за помощь или хотя бы пример !!

    • google.com Андрей Токарчук:

      Привет!
      Конечно можно это организовать. Для этого надо сделать две вещи.
      Первая, чтобы php создавал кэш. Вторая, чтобы nginx проверял существование кэша и, если он есть — отдавал.
      Это делается вот таким условием: if (!-e $request_filename) {
      SSD подключаете, как обычный локейшен.

  6. conroe9:

    Спасибо за подсказку !!

  7. Vladimir:

    Что у меня ваш пример не запустился.
    Подскажите если nginx дублирует get параметры в урле что может быть?

  8. Joshuan:

    Здравствуйте. Можете помочь с проблемой?
    Подключаю php традиционным скриптом
    location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /private/var/www/$fastcgi_script_name;
    include fastcgi_params;
    }

    И делаю реврайт такой
    location / {
    if (!-e $request_filename){
    rewrite ^(.*)$ /?modRewrite=$1 break;
    }
    }

    То например /catalog работает (перенаправляет на /index.php?modRewrite=catalog), а вот /catalog.php не работает — отдает 404
    Я думал он будет отправлять на /index.php?modRewrite=catalog.php
    В лог пишет такую ошибку
    *14 FastCGI sent in stderr: «Primary script unknown» while reading response header from upstream, client: 127.0.0.1, server: zf.dev, request: «GET /catalog.php HTTP/1.1», upstream: «fastcgi://127.0.0.1:9000», host: «localhost»

    Можете подсказать в чем затык? :(

    • google.com Андрей Токарчук:

      Возможно, у вас затык в том, что файл catalog.php существует, и упавление идёт на вторую ветку (которой у вас нет).

      location / {
      if (!-e $request_filename){
      rewrite ^(.*)$ /?modRewrite=$1 break;
      } else {
      // сюда
      }
      }

  9. […] — Ubuntu 14.04 LTS За основу возьмем мой конфиг из статьи Настройка nginx для хостинга. Там как раз реализована схема «nginx+php_fpm». Итак на […]

Комментировать