NGINX to szybki i lekki serwer HTTP, który mimo faktu, że zajmuje jedynie ok. 2 MB dysku, posiada sporo mozliwości konfiguracyjnych, takich jak virtual-hosts, czy url-rewriting. Dzięki FastCGI pozwala na obsługę skryptów PHP, ale i innych języków.
Pod windowsem, w domowej deweloperce króluje zestaw WAMP, w skład którego whodzi Windows, Apache, MySQL i PHP. Postanowiłem wykonać coś, co możnaby określić WNMP, czyli starego, ciężkiego Apacza zamienić na jego nowszy i lżejszy odpowiednik.
Całość jednak ma mi pozwalać kontynuwać prace nad kilkoma projektami, które tworzę z użyciem frameworka Symfony.

Jak uruchomić serwer NGINX ze wsparciem dla projektów Symfony pod Windows?

Ściągamy najnowszą wersję serwera NGINX – od niedawna istnieje wersja natywna, a nie cygwinowa, jakie były niedawno popularne. Natywna wersja powinnna być dużo szybsza od poprzedniczki. Serwer instalujemy w np. c:/dev/tools/nginx.

Zakładam, że system zarządzania bazą danych MySQL, framework Symfony, oraz sam PHP jest już zainstalowany na Twoim komputerze. Zakładam też, że zarówno MySQL, jak i PHP przygotowane są do współpracy z Symfony. Jeśli nie – w sieci jest mnóstwo opisów jak to zrobić.

Aby łatwo było uruchamiać i zatrzymywać serwer NGINX, musimy utworzyć następujące skrypty i zapisać je w katalogu NGINXa:

start-nginx.bat

@echo off
set NGINX_HOME=c:/dev/tools/nginx
set PHP_HOME=c:/dev/tools/php
set FASTCGI_ADDR=127.0.0.1
set FASTCGI_PORT=9000
 
echo "Startujemy nginx"
start %NGINX_HOME%/nginx.exe
echo "Startujemy php-cgi"
start /B %PHP_HOME%/php-cgi.exe -b %FASTCGI_ADDR%:%FASTCGI_PORT% -c %PHP_HOME%/php.ini
exit

stop-nginx.bat

@echo off
taskkill /f /IM nginx.exe
taskkill /f /IM php-cgi.exe
exit

Teraz wystarczy tylko skonfigurować NGINX tak, by

  • pozwalał na wykonywanie skryptów PHP za pomocą fastCGI
  • pozwalał na uruchamianie skryptów napisanych we frameworku Symfony

Edytujemy skrypt konfiguracyjny NGINXa (conf/nginx.conf):

worker_processes  1;
 
events {
    worker_connections  64;
}
 
http {
    include       mime.types;
    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 2k;
    request_pool_size               4k;
 
    gzip on;
    gzip_min_length 1100;
    gzip_buffers    4 8k;
    gzip_types      text/plain;
 
    output_buffers  1 32k;
    postpone_output 1460;
 
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
 
    keepalive_timeout       75 20;
    ignore_invalid_headers  on;
 
server {
    set  $docroot     c:/dev/php/symfony/myproject;
    root $docroot/web;
    index  index.php;
 
    listen       80;
    server_name  localhost;
 
    log_format main
                '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $bytes_sent '
                '"$http_referer" "$http_user_agent" '
                '"$gzip_ratio"'; 
    access_log  $docroot/log/myproject.access.log  main;
 
    charset utf-8;
 
    location / {
        if (-f $request_filename) {
            expires max;
            break;
        }
        rewrite ^(.*)/index.php last;
    }
 
    location /sf/ {
          root c:/dev/tools/php/data/symfony-1.2.7/data/web;
    }            
 
    location ~ \.php($|/) {
        set $the_uri $uri;
        if ($the_uri ~ "^(.+)/$") {
            set $the_uri    $1;
        }
 
        set  $script     $the_uri;
        set  $path_info  "";
 
        if ($uri ~ "^(.+\.php)(/.+)") {
            set  $script     $1;
            set  $path_info  $2;
        }
 
        fastcgi_index   index.php;
        fastcgi_pass   127.0.0.1:9000;
        include fastcgi_params;
 
        fastcgi_param  SCRIPT_FILENAME  $docroot/web$script;
        fastcgi_param  SCRIPT_NAME      $script;
        fastcgi_param  PATH_INFO        $path_info; 
        fastcgi_param  SERVER_NAME      $host;
    }
 
    location ~ /\.ht {
        deny  all;
    }
  }    
}

Pliczek konfiguracyjny NGINX’a jest dość czytelny i łatwo go zrozumieć (łatwo go też rozbudować i zoptymalizować jeśli np. używamy virtual-hostów). Na uwagę zasługuje jednak fakt, że przed przekazaniem argumentów do FastCGI musimy nieco „rozpracować” żądanie i wydobyć z niego zmienne $script i $path_info, ewentualnie usuwając zakańczający je znak slash (zmienna $the_uri). Warto też odnotować, że NGINX wspiera znane z Apacza aliasy – widoczna tu sekcja location /sf/.
Zauważ, że port 9000 wspomniany jest także w skrypcie startującym NGINX – możesz wybrać dowolny inny większy niż 1024 (niższe wymagają roli administratora i są zarezerwowane dla tzw. well-known-services).

Gotowe, teraz możemy uruchamiać NGINX poleceniem start-nginx.bat (z katalogu NGINXa) i zatrzymywać poprzez stop-nginx.bat.
Nasz projekt powinien być dostępny pod adresem http://localhost/ – czy to zakończonym slashem, czy tez nie.

Oczywiście nie jest to konfiguracja idealna – wspiera tylko jeden projekt (myproject), ale daje dobre podstawy do zbudowania konfiguracji dla wielu projektów i osobnych virtual-hostów dla każdego z nich. Warto wiedzieć, że konfiguracja NGINXa wspiera dyrektywę include, dzięki której możliwe jest importowanie konfiguracji z zewnętrznych plików konfiguracyjnych (np. po jednym dla każdego virtual-hosta) np. z sekcjami server.