Nginx

Nginx (prononcez “Engine X”) est serveur web robuste, léger et très performant sous licence BSD … Igor Sysoev a démarré son développement en 2002, et sa version 1.0 est sorti en 2011. Il a été développé dans la perspective de pouvoir répondre à la problématique des sites web actuels : desservir 10K clients simultanément.
Sa faible empreinte mémoire et CPU en fait le parfait candidat pour de petits serveurs à faibles ressources physiques, où les sites à très fort trafic. Il s’avère 3 à 4 fois plus rapide que Apache en mode prefork + PHP embarqué dans la plupart des cas pour une bande passante moindre. D’après W3Techs, il est utilisé par 34% des serveurs web à travers le monde le mettant ainsi en 1ère position devant Apache. Pour le traitement du contenu dynamique, il s’appuie sur une interface FastCGI mais aussi uWSGI. Il possède nombre de modules lui permettant de rivaliser avec les plus utilisés des serveurs HTTP et permet aussi de faire proxy pour les protocoles IMAP, POP et SMTP.

Sur ces belles paroles, faisons tourner la bête pour voir de quoi il retourne vraiment.

Installation

USE

Concernant sa variable USE voici ce que nous activerons en mettant cette ligne dans le fichier /etc/portage/package.use/nginx.use par exemple :

www-servers/nginx aio http http-cache ipv6 pcre ssl vim-syntax
  • aio : active les entrées sorties asynchrones,
  • http : active le support HTTP (c’est mieux dans la perspective de publier des pages web!)
  • http-cache : active le support du cache,
  • ipv6 : active le support IPv6,
  • pcre : active le support des expressions,
  • rtmp : active le support de serveur de streaming,
  • ssl : active le support OpenSSL,
  • syslog : active le support de syslog,
  • uwsgi : active le support du protocole uWSGI,
  • vim-syntax : active la coloration syntaxique de la configuration sous vim.

NGINX_MODULES_HTTP

Nginx possède un grand nombre de modules activables via la variable NGINX_MODULES_HTTP.

Ajoutez au fichier /etc/portage/make.conf ce qui suit :

NGINX_MODULES_HTTP="access auth_basic autoindex fastcgi browser charset gzip proxy referer rewrite spdy stub_status upstream upstream_check"
  • access : module proposant le contrôle d’accès basé sur l’hôte,
  • auth_basic : module d’authentification HTTP avec utilisateur et mot de passe,
  • autoindex : module permettant de lister les fichiers d’un repertoire,
  • fastcgi : module FastCGI pour la communication avec les langages,
  • browser : module permettant de créer des variables et données basées sur l’entête “User-agent de la requête,
  • charset : module de re-encodage des données,
  • gzip : module de compression des données,
  • proxy : module proxy,
  • referer : module permettant de créer des filtres basés sur l’entête “Referer” de la requête,
  • rewrite : module de ré-écriture des URLs
  • spdy : module implémentant le protocole SDPY (‘Speedy’) créer par Google,
  • stub_status : module permettant la visualisation en temps réel de l’état du service,
  • upstream : module permettant de créer des pools de ressources appelés dans la configuration,
  • upstream_check : module permettant de tester les pools de ressources.

Une fois que vous avez paramétré ses variables, il ne vous reste plus qu’à l’installer :

emerge -av www-servers/nginx

Configuration

Ici nous appliquerons une configuration quelque peu calquée sur Debian pour la gestion de l’activation des vhosts via des liens symboliques.

Créez les répertoires nécéssaires :

mkdir /etc/nginx/{conf.d,sites-available,sites-enabled}

Passons maintenant au coeur du sujet. Si nous autorisons 2048 connexions (worker_processes * worker_connections), nginx aura besoin de 2048 file descriptors (descripteurs de fichiers). Sachant que la limite par défaut sous Linux est de 1024 par utilisateur, il vous faudra faire certains réglages.

Créez un utilisateur :

useradd -d /dev/null -g 33 -u 33 -s /sbin/nologin

Augmentez les limites d’ouvertures de file descriptors en modifiant le fichier /etc/security/limits.conf :

www          soft    nofile           2048
www          hard    nofile           2048

Afin que cela soit appliquer lors de l’utilisation du script d’initialisation ajoutez le fichier /etc/conf.d/nginx :

rc_ulimit="-n 2048"

A noter que dans le cas d’utilisation du module proxy, chaque requête consommera 4 file descriptors, il vous faudra donc adapter ces chiffres à votre utilisation.

nginx.conf

###
user www www;
worker_processes 2;

error_log /var/log/nginx/error_log info;

events {
        worker_connections  1024;
        use epoll;
}

http {
        server_tokens off;

        server_names_hash_max_size 512;
        server_names_hash_bucket_size 128;
        server_name_in_redirect off;

        include         mime.types;
        default_type    application/octet-stream;

        client_header_timeout   10m;
        client_body_timeout     10m;
        send_timeout            10m;
        client_max_body_size    50m;

        connection_pool_size            256;
        client_header_buffer_size       64k;
        client_body_buffer_size         128k;
        large_client_header_buffers     8 16k;
        request_pool_size               4k;

        gzip              on;
        gzip_vary         on;
        gzip_proxied      any;
        gzip_http_version 1.1;
        gzip_comp_level   2;
        gzip_min_length   1100;
        gzip_buffers      16 8k;
        gzip_types        text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_disable      "MSIE [1-6]\.(?!.*SV1)";

        output_buffers  1 32k;
        postpone_output 1460;

        sendfile        on;
        tcp_nopush      on;
        tcp_nodelay     on;

        keepalive_timeout       75 75;

        ignore_invalid_headers  on;

        index index.html;

        include conf.d/*.conf;
        include sites-enabled/*;

        access_log      /var/log/nginx/access_log;
        error_log       /var/log/nginx/error_log;

}

Vhosts

Default

Passons maintenant à la configuration des vhosts et créons celui par défaut, c’est-à-dire écoutant même sur l’adresse seule.

Fichier /etc/nginx/sites-available/default :

server {
                listen 80;
                server_name _;
                server_name_in_redirect off;
                return 444;
}

Dans ce cas, si la requête est faite sur un vhost ne stipulant pas le nom de domaine, la requête retourne un code HTTP 444 (pas de réponse).

www.gentoo-fr.org

Créez votre premier vhost; dans cet exemple l’écoute se fait uniquement le nom de domaine www.gentoo-fr.org, les fichiers commençant par .ht (htaccess, htpasswd…) sont interdits, l’accès au fichier favicon.ico ne sera pas enregistré dans les logs et son expiration est fixé à 1 jour (équivalent du mod_expire sous Apache).

Fichier /etc/nginx/sites-available/gentoo-fr.org :

server {
        listen 80;
        server_name www.gentoo-fr.org;
        root /var/www/gentoo-fr.org/www;

        location ~ /\.ht {
                deny  all;
        }

        location /favicon.ico {
                access_log  off;
                log_not_found  off;
                expires  1d;
        }
}

Faites les liens des sites que vous activez :

cd /etc/nginx/sites-enabled
ln -s ../sites-available/default 00-default
ln -s ../sites-available/gentoo-fr.org 10-gentoo-fr.org

Vérifiez la syntaxe :

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Et démarrez le service :

rc-update add nginx default
/etc/init.t/nginx start

Cela dit, je suis d’accord avec vous, peu de sites sont statiques à notre époque, et donc la configuration d’un interpréteur s’impose.

Modules

Il existe un certain nombre de modules pour Nginx, je ne traiterai que les principaux pour un usage basique. Pour vos besoins spécifiques, je vous invite à vous reporter à la documentation en anglais.

FastCGI PHP

php-fpm

fpm pour “Fork Process Manager” est le gestionnaire de processus PHP intégré à PHP à partir de la version 5.3.

Afin d’exécuter les scripts PHP via l’interface Fastcgi, il faut vous assurer du support cgi et fpm à sa compilation.

Configurez le service php-fpm en modifiant le fichier /etc/php/fpm-php5.3/php-fpm.conf :

[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm.log

[www]
listen = /var/run/php-fpm.sock
listen.owner = www
listen.group = www
listen.mode = 0660
user = www
group = www
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

Démarrez :

rc-update add php-fpm default
/etc/init.d/php-fpm start

Ajoutez le fichier /etc/nginx/conf.d/00-upstream.conf :

upstream php5-backend {
        server unix:/var/run/php-fpm.sock;
}

Ajoutez le fichier /etc/nginx/php_fatcgi_params qui contiendra les options FastCGI PHP génériques :

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;
fastcgi_intercept_errors on;

fastcgi_param  SCRIPT_FILENAME    $request_filename;
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      $document_root;
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;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

Modifiez votre vhost afin qu’il transfère au service php-fpm les requêtes concernant les fichiers avec l’extension .php :

server {
        listen 80;
        server_name www.gentoo-fr.org;
        root /var/www/gentoo-fr.org/www;
        index index.html index.php;

        location ~ /\.ht {
                deny  all;
        }

        location ~ \.php$ {
                include php_fastcgi_params;
                fastcgi_pass php5-backend;
        }

        location /favicon.ico {
                access_log  off;
                log_not_found  off;
                expires  1d;
        }
}

Redémarrez le service nginx :

/etc/init.d/nginx restart

spawn-fcgi

Pour ceux qui utilisent une version inférieure à php-5.3, vous pouvez utiliser spawn-fcgi, initialement développé pour lighttpd, comme gestionnaire de processus php-cgi.

emerge -av spawn-fcgi

Modifiez le fichier /etc/conf.d/spawn-fcgi :

FCGI_SOCKET=/var/run/spawn-fcgi/php-cgi.sock
FCGI_PROGRAM=/usr/bin/php-cgi
FCGI_CHILDREN=1
FCGI_USER=www
FCGI_GROUP=www
PHP_FCGI_CHILDREN=10
PHP_FCGI_MAX_REQUESTS=500
ALLOWED_ENV="PATH PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS"

Démarrez le service spawn-fcgi :

rc-update add spawn-fcgi default
/etc/init.d/spawn-fcgi start

Modifiez votre configuration nginx en conséquence en modifiant le fichier /etc/nginx/conf.d/00-upstream.conf :

upstream php5-backend {
        server unix:/var/run/spawn-fcgi/php-cgi.sock;
}

Redémarrez le service nginx.

Rails & Rack

Il y a une manière relativement simple d’utiliser le framework Rails et Rack sous nginx en utilisant Phusion Passenger aussi appelé mod_rails sous Apache, mais aussi Thin ou encore Unicorn. En paramétrant nginx en mode proxy, tout le contenu dynamique étant demandé à l’application.

Créez le fichier /etc/nginx/proxy_params qui contiendra les informations génériques pour la communication entre nginx et :

proxy_redirect             off;
proxy_set_header           Host            $http_host;
proxy_set_header           X-Real-IP       $remote_addr;
proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout      180;
proxy_send_timeout         180;
proxy_read_timeout         180;
proxy_buffer_size          4k;
proxy_buffers              4   32k;
proxy_busy_buffers_size    64k;
proxy_temp_file_write_size 64k;

Ensuite faites ressembler votre vhost à ce qui suit :

# Upstream Ruby process cluster for load balancing
upstream rails-gentoo-fr {
    server unix:/tmp/rails-gentoo-fr.0.sock;
    server unix:/tmp/rails-gentoo-fr.1.sock;
    server unix:/tmp/rails-gentoo-fr.2.sock;
    server unix:/tmp/rails-gentoo-fr.3.sock;
}

server {
        listen 80;
        server_name  projects.gentoo-fr.org;
        root  /var/www/gentoo-fr.org/projects/public;

        location / {
                try_files $uri/index.html $uri.html $uri @rails-gentoo-fr;
        }

        location @rails-gentoo-fr {
                include proxy_params;
                proxy_pass http://rails-gentoo-fr;
        }

        location ~ /\.ht {
                deny  all;
        }

        location /favicon.ico {
                access_log  off;
                log_not_found  off;
                expires  1d;
        }

        location ~ /(images|javascripts|stylesheets)/ {
                expires   1d;
        }
}

Redémarrez nginx et le tour est joué.

SSL

Passons à la configuration du module SSL.

Global

Pour utiliser le même certificat pour tous les vhosts, créez le fichier /etc/nginx/conf.d/10-ssl.conf :

ssl on;
ssl_certificate /etc/ssl/private/nginx.cert;
ssl_certificate_key /etc/ssl/private/nginx.key;

Ensuite modifiez vos vhosts afin qu’ils écoutent sur le port 443 au lieu de 80.

Vhost

Pour utiliser un certificat spécifique par vhost reportez les lignes ci-dessus dans sa configuration :

server {
        listen 443;
[...]
        ssl on;
        ssl_certificate /etc/ssl/private/nginx.cert;
        ssl_certificate_key /etc/ssl/private/nginx.key;
[...]
}

uWSGI

Le module uWSGI permet d’utiliser le protocole du même nom. Ajoutez l’upstream correspondant à votre fichier /etc/nginx/conf.d/00-upstream.conf :

upstream uwsgi-www-php54 {
        server unix:/run/uwsgi_www-php54/uwsgi.www-php54.sock;
}

Crééz le fichier /etc/nginx/uwsgi_params :

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  REMOTE_USER        $remote_user;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

En enfin le vhost :

[...]
        location ~ \.php$ {
                try_files    $uri =404;
                include uwsgi_params;
                uwsgi_modifier1 14;
                uwsgi_pass uwsgi-www-php54;
        }
[...]

Pour le paramètre uwsgi_modifier1 reportez-vous à la documention du protocole uWSGI.

Access

Le module access va vous permettre d’effectuer un filtrage par adresse IP pour l’accès à certaines ressources :

server {
[...]
        location / {
                allow 127.0.0.1;
                allow 192.168.0.0/24;
                deny all;
        }
[...]
}

Auth

Le module d’authentification vous permet quant à lui de restreindre l’accès par utilisateur :

server {
[...]
        location / {
                auth_basic  "Secure Access";
                auth_basic_user_file  /etc/nginx/.htpasswd;
        }
[...]
}

Auto Index

Ce module permet de lister les fichiers et répertoires contenus dans un emplacement :

server {
[...]
        location /download/ {
                autoindex  on;
        }
[...]
}

Proxy

server {
[...]
        location / {
                include proxy_params;
                proxy_pass http://localhost:8080;
        }
[...]
}

Rewrite

Le module rewrite permet la re-écriture des URLs, très partique afin de convertir les RewriteRules Apache.

Si le site est appelé en http://gentoo-fr.org/ , modifier l’URL en http://www.gentoo-fr.org/ de manière permanente (code HTTP 301) :

server {
        listen 80;
        server_name gentoo-fr.org;
        return 301 http://www.gentoo-fr.org$request_uri;
}

Emuler le comportement Apache pour les applications du type WordPress :

server {
[...]
        try_files $uri $uri/ /index.php?q=$uri&$args;
[...]
}

Liens