Instalando Nginx (Engine-X) en Debian

Antes de instalar Nginx debemos de actualizar el repositorio del sistema, agregando los links necesarios para descargar la última versión de Nginx.
Actualización del repositorio en Debian
Actualizamos el repositorio de apt para poder descargar la última versión de Nginx.

vim /etc/apt/sources.list

Y agregamos las siguientes líneas.

deb http://nginx.org/packages/debian/ squeeze nginx
deb-src http://nginx.org/packages/debian/ squeeze nginx

En la siguiente url: http://nginx.org/packages/ están disponibles los paquetes para varias distribuciones de Linux.
Ahora para permitir que apt obtenga la lista de paquetes de las fuentes que especificamos ejecutamos el siguiente comando para actualizar el repositorio de apt.

apt-get update

Después de actualizado el repositorio procedemos a la instalación de Nginx.

apt-get install nginx

Verificamos que hayamos instalado la última versión (Chequear versión contra su página oficial en ingles)

root@server:~# nginx -v
      nginx version: nginx/1.2.3

Configurando Nginx como Proxy Inverso

Primero creamos los directorios donde se alojará las configuraciones para todos los sitios.

mkdir -p /etc/nginx/sites-available
mkdir -p /etc/nginx/sites-enabled

Ahora vamos a crear la configuración de Nginx como proxy inverso.
En /etc/nginx/sites-available/ creamos un archivo con la configuración del sitio al que apuntará el proxy. (Para esta prueba crearemos la configuración para el siguiente dominio (example.com) ).

vim /etc/nginx/sites-available/example.com.conf

Sobre este archivo agregamos la siguiente configuración correspondiente a la configuración de proxy inverso sobre los sitios que indicamos anteriormente.

server {
    listen		80; #Puerto sobre el cual escucha
    server_name	example.com www.example.com;
    access_log	/var/log/nginx/example.com.access.log main;
    access_log 	/var/log/nginx/example.com.cache.log cache;
    error_log   	/var/log/nginx/example.com.error.log error;

    location / {
        proxy_pass   http://192.168.1.200:80; #Host donde apunta
    }
    Include		/etc/nginx/proxy.conf; # Incluimos la configuración del Proxy
}

La directiva proxy_pass establece la dirección del servidor proxy y el URI al que se asignará la ubicación. Dirección se puede dar como nombre o dirección y el puerto, por ejemplo: proxy_pass http://localhost:8000/uri/;.

Procedemos a crear el archivo /etc/nginx/proxy.conf que contendrá la configuración del Proxy.

vim /etc/nginx/proxy.conf

Y le agregamos el siguiente contenido correspondiente a la configuración del Proxy.

proxy_cache             STATIC;
proxy_cache_valid       200  1d;
proxy_cache_use_stale   error timeout invalid_header updating
                        http_500 http_502 http_503 http_504;

proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    16m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

Ahora pasamos a editar el archivo de configuración principal de Nginx /etc/nginx/nginx.conf.

Dentro del contexto http hacemos el include que levantará todos los sitios habilitados, también agregamos la configuración correspondiente al cache del proxy.

Archivo de configuración /etc/nginx/nginx.conf.

user  nginx;
worker_processes  2;

#Cantidad limite de conexiones de red abiertas por cada worker_processes
worker_rlimit_nofile 4096;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  2048;
    use epoll;
};

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;

    include /etc/nginx/conf.d/*.conf;

    #Definimos la configuración de cache para el proxy.
    proxy_cache_path  /var/cache/nginx/proxy_temp   levels=1:2    keys_zone=STATIC:10m
                                                    inactive=24h  max_size=1g;

    #Incluimos los sitios habilitados
    include /etc/nginx/sites-enabled/*.conf;

}

Después de creada la configuración, creamos un link simbólico en la carpeta /etc/nginx/sites-enabled/ que es donde se levantarán todos los sitios habilitados (Se creó esta estructura para que sea mas fácil para los que ya hemos trabajado con Apache)

ln -s /etc/nginx/sites-available/crisishazterico.conf /etc/nginx/sites-enabled/

Después de creado el link simbólico reiniciamos el servidor Nginx para que tome los nuevos cambios.

/etc/init.d/nginx start

Con esto ya deberíamos tener nuestro sitio funcionando a través de un proxy inverso. Para probarlo deberemos mapear el dominio en el host de nuestra maquina a la IP del servidor proxy y probar si accede bien. (Con herramientas como Firebug podemos chequear desde que IP levanta los recursos un sitio)

Configurar Nginx como balanceador de carga (Load Balancing)

Para configurar Nginx como balanceador de carga primero debemos configurar el mismo como servidor de proxy inverso, ver Configurando Nginx como Proxy inverso, la única diferencia es que en este caso la configuración del proxy inverso no vinculara directamente con un host, sino que apuntará a la configuración de un cluster de servers indicados con la directiva upstream sobre el mismo archivo de configuración de Nginx.

Upstream: Esta directiva describe un conjunto de servidores, que pueden ser utilizados con las directivas PROXY_PASS y fastcgi_pass como una sola entidad. Se puede configurar un servidor en puertos diferentes y, además, es posible utilizar simultáneamente un servidor que escuche en TCP y sockets Unix.
Procedemos a detallar la configuración de Neginx como Load Balancing.
Asumimos que Nginx ya está configurado y que están creados los siguientes directorios:

  •  sites-available
  •  sites-enabled

Creamos un archivo de configuración correspondiente al dominio sobre el cual se hará balance de carga.

vim /etc/nginx/sites-available/big.server.com.conf

Y le agregamos el siguiente contenido correspondiente a la configuración.

upstream big_server_com {
	server 192.168.7.20:8801;
	server 192.168.7.20:8802 weight=1;
	server 192.168.7.20:8803 weight=2 max_fails=2;
	server 192.168.7.20:8804 weight=2 max_fails=2 fail_timeout=20;
	server 192.168.7.20:8805 weight=4;
	server 192.168.7.20:8806 weight=4 fail_timeout=4;
	server 192.168.7.20:8807 weight=2 fail_timeout=20;
}

server { # simple load balancing
	listen          	80;
	server_name     	big.server.com;
	access_log      	/var/log/nginx/big.server.access.log main;
	access_log 		/var/log/nginx/big.server.cache.log cache;
	error_log   		/var/log/nginx/big.server.error.log error;

	location / {
				proxy_pass      http://big_server_com;
	}
}

  • Weight=[number]: Especifica una ponderación entre los diferentes servidores configurados, el valor por defecto es 1 y para ponderar un host mas que otro se incrementa su valor. Un servidor con una ponderación de 2 recibirá el doble de tráfico que uno con una ponderación por defecto y así sucesivamente.
  • Max_fails=[number]: Esta variable especifica el número de intentos infructuosos de comunicación con el host antes de ser considerado no operativo. Para evitar que los servidores que alguna fueron marcados como inactivos, aunque se encuentra fuera de cobertura, establecer este valor a 0. El valor predeterminado para max_fails es 1.
  • Fail_timeout=[tiempo en segundos]: Este argumento determina el lapso de tiempo en que el número de intentos fallidos max_fails debe ocurrir con el fin de marcar un componente del servidor fuera de servicio. Tener en cuenta, para los servidores que devuelven un mensaje de error 404, se considera operativo y este valor no afecta a los tiempos de espera para las conexiones del proxy establecido.

En el ejemplo anterior, hay siete componentes de servidor (hosts configurados) que se ejecutan en los puertos únicos en el servidor 192.168.7.20 y comprenden el appcluster upstream. Los componentes que se ejecutan en los puertos 8801 y 8802 son tratados de forma idéntica por Nginx, ya que el valor predeterminado para el weight es de 1. Los componentes que se ejecutan en los puertos 8803, 8804, 8807 recibirán un tráfico de dos veces mayor que los dos primeros. Los componentes, 8805 y 8806 recibirán cuatro veces más tráfico que 8801 y 8802 y el doble que los componentes 8803, 8804 y 8807.

Los componentes en los puertos 8801, 8802, 8805, 8806 y 8807 sólo pueden rechazar una conexión antes de ser marcado como fuera de servicio (no operativos). Para los componentes 8803 y 8804 se les permite fallar dos veces antes de ser marcado como fuera de servicio. Por defecto, todos los componentes tienen su “fail counter” reset cada 10 segundos, que cubre los componentes de 8801, 8802, 8803 y 8805. Los componentes, 8804 y 8807 tienen sus fail counters reset cada 20 segundos, mientras que 8806 tiene su fail counter reset cada 4 segundos. Con estos argumentos, se puede usar nginx para gestionar el comportamiento y distribución de carga a través de un cluster de servidores.

upstream appcluster {
   ip_hash;
   server 192.168.1.80:8801 down;
   server 192.168.1.80:8802;
}

ip_hash se utiliza para tratar de asegurar que los requests procedentes de una única dirección IP permanecerán unidos a un componente específico del clúster. Si un componente de servidor es inaccesible, Nginx dirigirá esas conexiones a un componente alternativo. Si un servidor tiene que estar offline durante un período prolongado de tiempo, debemos añadir el argumento down como en la entrada 192.168.1.80:8801 del ejemplo anterior para evitar la pérdida de conexiones al intentar acceder a un componente del servidor que está offline.

Configurar Nginx como Webserver

Para realizar este paso ya debemos haber instalado Nginx, ver Instalando Nginx (Engine-X) en Debian.
Nginx soporta PHP sólo a través de FastCGI, por eso debemos de instalar y configurar spawn-fcgi he instalar el paquete de PHP php5-cgi.

FastCGI
Es la evolución de CGI (Common Gateway Interface), un protocolo concebido para responder a la demanda de páginas dinámicas. Hoy fast-cgi permite conectar (vía TCP) un servidor web cómo Nginx con otro servidor independiente que ejecuta las aplicaciones. En este caso aplicaciones que están desarrolladas en PHP y el servidor de aplicación es php-cgi.

Instalamos los paquetes requeridos

apt-get update
apt-get install php5-cli php5-cgi spawn-fcgi php5-common
apt-get install php5-curl php5-gd php5-json php5-mcrypt php5-sqlite php5-mysql

Creando directorios
En esta guía, el dominio “example.com” se utiliza como un sitio de ejemplo. Debe sustituir su propio nombre de dominio en los pasos de configuración siguiente. En primer lugar, crearemos los directorios para alojar los sitios y los logs de los mismos.

mkdir -p /var/www/example.com/htdocs
mkdir -p /var/www/example.com/logs
chown -R nginx.nginx /var/www/example.com

Creamos un archivo con la configuración para FastCGI y un script de arranque para el mismo.

vim /usr/bin/php-fastcgi

Le agregamos el siguiente contenido.

#!/bin/bash

FASTCGI_USER=nginx
FASTCGI_GROUP=nginx
ADDRESS=127.0.0.1
PORT=9000
PIDFILE=/var/run/php-fastcgi/php-fastcgi.pid
CHILDREN=6
PHP5=/usr/bin/php5-cgi

/usr/bin/spawn-fcgi -a $ADDRESS -p $PORT -P $PIDFILE -C $CHILDREN -u $FASTCGI_USER -g $FASTCGI_GROUP -f $PHP5

Marcamos el archivo recién creado como ejecutable.

chmod +x /usr/bin/php-fastcgi

Creamos el archivo de arranque para php-fastcgi llamado /etc/init.d/php-fastcgi con el siguiente contenido:

vim /etc/init.d/php-fastcgi
#!/bin/bash

PHP_SCRIPT=/usr/bin/php-fastcgi
FASTCGI_USER=nginx
FASTCGI_GROUP=nginx
PID_DIR=/var/run/php-fastcgi
PID_FILE=/var/run/php-fastcgi/php-fastcgi.pid
RET_VAL=0

case "$1" in
    start)
      if [[ ! -d $PID_DIR ]]
      then
        mkdir $PID_DIR
        chown $FASTCGI_USER:$FASTCGI_GROUP $PID_DIR
        chmod 0770 $PID_DIR
      fi
      if [[ -r $PID_FILE ]]
      then
        echo "php-fastcgi already running with PID `cat $PID_FILE`"
        RET_VAL=1
      else
        $PHP_SCRIPT
        RET_VAL=$?
      fi
  ;;
    stop)
      if [[ -r $PID_FILE ]]
      then
        kill `cat $PID_FILE`
        rm $PID_FILE
        RET_VAL=$?
      else
        echo "Could not find PID file $PID_FILE"
        RET_VAL=1
      fi
  ;;
    restart)
      if [[ -r $PID_FILE ]]
      then
        kill `cat $PID_FILE`
        rm $PID_FILE
        RET_VAL=$?
      else
        echo "Could not find PID file $PID_FILE"
      fi
      $PHP_SCRIPT
      RET_VAL=$?
  ;;
    status)
      if [[ -r $PID_FILE ]]
      then
        echo "php-fastcgi running with PID `cat $PID_FILE`"
        RET_VAL=$?
      else
        echo "Could not find PID file $PID_FILE, php-fastcgi does not appear to be running"
      fi
  ;;
    *)
      echo "Usage: php-fastcgi {start|stop|restart|status}"
      RET_VAL=1
  ;;
esac
exit $RET_VAL

Marcamos el archivo recién creado como ejecutable.

chmod +x /etc/init.d/php-fastcgi

Configuramos para que php-fastcgi arranque junto con el sistema, (arranque automático)

update-rc.d php-fastcgi defaults

Iniciamos el servicio

/etc/init.d/php-fastcgi start

Ahora procedemos a crear la configuración del virtual host para el dominio de prueba example.com.

vim /etc/nginx/sites-available/example.com.conf

Y le agregamos el siguiente contenido.

server {
    server_name www.example.com example.com;
    access_log /var/www/example.com/logs/access.log;
    error_log /var/www/example.com/logs/error.log;
    root /var/www/example.com/htdocs;

    location / {
        index  index.html index.htm index.php;
    }

    location ~ \.php$ {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/htdocs$fastcgi_script_name;
    }
}

Ahora pasamos a editar el archivo de configuración principal de Nginx /etc/nginx/nginx.conf.
Dentro del contexto http hacemos el include que levantará todos los sitios habilitados linkeados en el directorio sites-enabled.

...
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    include /etc/nginx/conf.d/*.conf;
    #Incluimos los sitios habilitados
    include /etc/nginx/sites-enabled/*.conf;
}

Posteriormente creamos un link simbólico en /etc/nginx/sites-enabled para el host configurado previamente.

ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/

Después de creado el link reiniciamos Nginx o simplemente le indicamos que vuelva a leer su configuración.

/etc/init.d/nginx restart OR nginx -s reload

Prueba de PHP con FastCGI
Finalmente para poder probar este proyecto creamos un archivo llamado index.php para realizar la prueba.

vim /var/www/example.com/htdocs/index.php

Y le agregamos el siguiente contenido.

<?php phpinfo(); ?>

Solo resta probarlo con el browser que mas prefieran.