By

Nginx

Hace bastante tiempo que tengo en mente escribir un post sobre Nginx (pronunciado como “engine x”), aunque ya lo he comentado en algún otro post anterior, y creo que hoy va a ser el día. No por nada en especial, si no porque me apetece compartirlo y además es un servidor web que me gusta mucho y que, en ciertos aspectos, ha ido conquistando terreno de otros servidores web.

¿Qué es Nginx?

Como decía, Nginx es un servidor HTTP libre, de código abierto, de alto rendimiento y que puede ser utilizado para actuar tanto como proxy HTTP reverso, como proxy IMAP/POP3. Nginx es famoso por ser muy ligero, ya que consume muy pocos recursos del sistema; es muy estable, y además su configuración es relativamente sencilla, bastante más simple a la vista que la configuración de Apache2.

Su instalación es bastante sencilla también, independientemente de que lo hagamos mediante herramientas de paquetería o compilando del código fuente directamente.

Como apunte, decir que fue escrito por Igor Sysoev, de origen ruso, escrito para solventar un problema llamado C10K. Resumiendo, ser capaz de manejar 10.000 clientes de forma simultanea.

La primera vez que instalé Nginx, compilando desde las fuentes, fue allá por 2008 simplemente por probarlo. No fue hasta 2009 ó 2010 cuando empecé a usarlo de verdad cuando trabajaba en Yaco Sistemas, para realizar despliegues de aplicaciones web con Django. Y recuerdo que mi primer despliegue utilizando Merengue Project + Nginx + uWSGI, con el fin de ver si mejoraba el rendimiento y la verdad es que quedamos encantados. Así que vamos a instalarlo ya!

Instalando Nginx ¿pero cómo?

Es posible que antes de instalar nos surjan dudas con respecto a la forma de instalar ya sea Nginx u otro software en nuestro sistema. Hay varias formas de instalar Nginx:

  • Descargar el código fuente y seguir el proceso de instalación típico: configurar, compilar e instalar; también conocido como cmmi (configure - make - make install).
  • Utilizando las herramientas de paquetería de nuestra distribución: Aptitude o APT si utilizamos una distribución basada en Debian, yum si utilizamos CentOS, RedHat, Fedora o similar; etc.
  • Añadir el repositorio oficial de Nginx a nuestro sistema de paquetería, si hubiera alguno disponible y compatible; en caso de que no estuviese disponible el paquete en nuestra distribución.
  • Descargar el paquete de instalación compatible con nuestro sistema de paquetería, de otra distribución e instalarlo con las herramientas habituales en nuestro sistema.
  • Descargar un paquete de instalación (.deb.rpm, por ejemplo) y convertirlo con alien si el paquete descargado no es compatible con nuestro sistema de paquetería.

Todas estas formas permitirían instalar Nginx, pero no todas son aconsejables, según qué casos, me explico.

Si se trata de una instalación en producción, y con ello me refiero a la instalación de Nginx en un servidor de un cliente, o en un servidor de producción para nuestra empresa; me decantaría sin dudar por la instalación mediante el sistema de paquetería. De esta forma, contaría con todas las posibles futuras actualizaciones de seguridad y/o correcciones del paquete de forma muy cómoda utilizando las herramientas de paquetería del sistema.

Si la instalación de Nginx se va a realizar en un sistema antiguo, y en ese caso, si es que existe un paquete para Nginx en el sistema de paquetería, es probable que sea más antiguo y desactualizado que la versión actual de Nginx. Con lo que es muy posible que no cuente con mejoras de fallos de seguridad, arreglos de bugs encontrados, etc; en este caso, personalmente, optaría por una instalación desde las fuentes. Es cierto que antes de instalar desde las fuentes sopesaría mis necesidades sobre Nginx, es decir, si es una instalación en producción pero sólo voy a servir HTML estático, es muy posible que aun siendo una versión antigua de Nginx, hubiera optado por la instalación por paquetería. Pero si el fin es servir una web más compleja, optaría por utilizar la versión estable más reciente de Nginx y compilar desde las fuentes.

Con respecto a descargar un paquete de otra distribución o convertir el paquete con alien, no lo recomendaría a menos que fuera una situación extrema, que no haya otro camino, y si la distribución a la que pertenece el paquete es muy similar a la que estamos usando. En cualquier otro caso, no lo usaría nunca, ya que: no contamos con futuras actualizaciones del paquete, al pertenecer a otra distribución es posible que los ficheros se instalen en directorios no habituales en nuestra distribución, es posible que los scripts SysV del servicio no funcionen, etc.

Esto sólo es mi humilde opinión de lo que haría en una situación real. Es imposible describir todas las posibilidades o dar unas directrices de qué hacer en una determinada situación, más que elegir una nosotros mismos basándonos en nuestro conocimiento, experiencia y muchos otros factores. En caso de dudar, si es posible, es aconsejable obtener una segunda opinión de un compañero o consultarlo con alguien con rango superior.

Y bueno, después de esta parrafada (perdón), nos puede quedar claro, qué dos opciones de instalación elegiría yo, IMHO (¿qué pensais vosotros?) Así que veremos la instalación utilizando herramientas de paquetería y compilando desde el código fuente.

Instalación por paquetería

La instalación por paquetería es bastante trivial si ya estamos familiarizados con estas herramientas. Bastaría con buscar el paquete en la base de datos de nuestro sistema de paquetería, ver el nombre e instalarlo.

Debian

En Debian 7 (wheezy) que es la que estoy usando actualmente hay varios paquetes de Nginx en los repositorios oficiales de Debian:

  • nginx-light : una versión “light” que sólo incluye un Nginx precompilado con unos cuantos módulos, pero no todos.
  • nginx-full : incluye Nginx precompilado con todos los módulos estandar incluidos.
  • nginx-extras : se trata de Nginx precompilado con todos los módulos estandar más una serie de módulos extras incluyendo algunos como Perl.

Depende de las necesidades que tengamos instalaremos uno u otro, pero en este caso instalaré nginx-full, y para ello ejecutaremos la siguiente instrucción:

[email protected]:~# apt-get install nginx-full

La instalación no tardará mucho en finalizar y tendremos instalado Nginx en nuestro sistema. Una de las ventajas de utilizar el sistema de paquetería de nuestro sistema frente a compilar nuestra propia versión de Nginx es que el paquete además de instalar Nginx, instala ciertas utilidades adicionales como pueden ser los scripts de inicio SysV y demás scripts que nos permiten arrancar, reiniciar o parar nuestro servidor Nginx. Para arrancar Nginx utilizaremos, como root, el comando service:

[email protected]:~# service nginx start
Starting nginx: nginx.

Si consultamos el estado utilizando el parámetro status podremos ver que Nginx ya se encuentra en funcionamiento:

[email protected]:~# service nginx status
nginx is running.

Para comprobar si realmente el puerto 80 (http/tcp) está escuchando podemos utilizar el comando netstat de la siguiente forma:

[email protected]:~# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 192.168.1.40:80         192.168.1.35:60110      ESTABLISHED 3262/nginx: worker

CentOS

En CentOS al parecer no hay paquete en los repositorios oficiales por defecto, así que hay que añadir primero el repositorio a nuestra lista de repositorios y luego instalarlo. Es muy fácil, sólo hay que hace lo siguiente:

Podemos descargar el paquete RPM que instala la configuración del repositorio y posteriormente instalarlo con la utilida rpm, o instalarlo directamente con la utilidad yum pasando la URL completa hacia el fichero RPM de la siguiente forma:

[[email protected] /]# yum install http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm

Una vez instalado, podemos consultar la configuración del repositorio de Nginx que se ha instalado en el fichero /etc/yum.repos.d/nginx.repo. Tras instalar la configuración del repositorio, ya solo nos queda utilizar yum para instalar Nginx:

[[email protected] /]# yum install nginx

Ya solo nos queda arrancar nuestro Nginx utilizando la utilidad service al igual que hicimos en Debian.

IMPORTANTE: Es posible que en CentOS ya se encuentre ejecutándose una instancia de httpd (Apache2) por defecto. Antes de arrancar Nginx es necesario parar dicha instancia o Nginx informará con un error indicando que el puerto 80 (http/tcp) se encuentra ocupado.

[[email protected] /]# service nginx start
Starting nginx: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

Si accedemos ahora utilizando nuestro navegador a http://localhost:80 veremos un útil, pero poco bonito, mensaje: Welcome to nginx! El fichero de configuración para ambos casos se encuentra en /etc/nginx/nginx.conf.

Instalando desde las fuentes

Antes de comenzar, deberemos disponer en nuestro sistema de ciertas utilidades que serán de vital importancia para poder compilar en nuestro sistema, como gcc, make y otras librerias de desarrollo que se necesitan instaladas para poder compilar Nginx:

[email protected]:~# apt-get install gcc make libpcre3 libpcre3-dev zlib1g zlib1g-dev

Instalados los prerequisitos, procedemos entonces con la descarga de las fuentes de Nginx desde su sitio oficial:

[email protected]:~# wget http://nginx.org/download/nginx-1.2.4.tar.gz

A continuación descomprimimos y procedemos con la configuración, compilación e instalación:

[email protected]:~# tar xzf nginx-1.2.4.tar.gz 
[email protected]:~# cd nginx-1.2.4/
[email protected]:~/nginx-1.2.4# 
[email protected]:~/nginx-1.2.4# ./configure && make && make install

Por defecto, Nginx se instala en /usr/local/ aunque podemos modificar este comportamiento con ./configure --prefix=/path/to/install/. Como comentaba antes, esta vez no contamos con scripts de inicio SysV, así que tendremos que arrancar Nginx de forma manual, ejecutando directamente el binario de nginx:

[email protected]:~# /usr/local/nginx/sbin/nginx

Si todo va bien, deberíamos tener inmediatamente el puerto 80 escuchando peticiones HTTP en nuestro sistema. Para para Nginx, también deberemos hacerlo de forma totalmente manual, utilizando la opción -s y pasándole el argumento stop; aunque también se puede hacer uso de otros argumentos como quit, reopen y reload:

[email protected]:~# /usr/local/nginx/sbin/nginx -s stop

La configuración por defecto

La ubicación del fichero de configuración cambia dependiendo de la forma en que se haya instalado, a menos que cambiemos el comportamiento por defecto con ./configure --conf-path al compilar desde las fuentes. Si Nginx ha sido instalado utilizando el sistema de paquetería se encontrará en /etc/nginx/nginx.conf. Sin embargo, si se ha compilado desde las fuentes y no se ha modificado la ruta del fichero de configuración, entonces lo más probable es que se encuentre en /usr/local/nginx/conf/nginx.conf. El contenido de este fichero es bastante similar en ambos casos, aunque por defecto, hay muchas lineas de ejemplo comentadas. Si eliminamos todos los comentarios, se puede apreciar que la configuración es bastante simple:

[email protected]:~# grep -v "#" /usr/local/nginx/conf/nginx.conf |uniq

worker_processes  1;

events {
    worker_connections  1024;
}

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

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

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

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

Como se puede ver, la configuración se estructura en bloques delimitados por llaves {} (en inglés curly braces) haciéndola mucho más legible que un bloque de configuración de Apache2, por ejemplo. Como parámetros a destacar, me gustaría comentar los siguientes:

  • worker_processess : indica el número de workers/procesos de nginx que se van a arrancar simultaneamente. Si establecemos worker_processes con valor 2, se ejecutarán dos procesos worker de Nginx.
  • worker_connections : hace referencia al número de conexiones por worker. Esto quiere decir que el número de conexiones que será capaz de servir nuestro servidor nginx corresponde a worker_processes x worker_connections. Según la configuración del ejemplo, solo aceptará 1024 conexiones simultaneas (1 (worker_processes) x 1024 (worker_connections)
  • http {} : bloque donde se especifica la configuración de cada servidos. Es posible configurar varios bloques server {} en un mismo bloque http {}, utilizando diferentes puertos lógicamente.
  • server {} : configuración para un servidor concreto, que normalmente se corresponderá con un número de puerto único.
  • listen 80; : puerto de escucha de Nginx. Se corresponde con la directiva Listen de Apache2
  • server_name localhost; : hostname o FQDN del servidor. Se corresponde con la directiva ServerName de Apache2.
  • location : configuración de un location concreto. Se corresponde con la directiva Location en Apache2.
  • root : directorio utilizado para buscar los ficheros estáticos. Se corresponde con la directiva DocumentRoot de Apache2.

Bueno, eso es todo por hoy amigos, espero que os haya sido de utilidad para aquellos que no conocíais Nginx o aquellos que nunca lo habíais instalado. En próximos posts veremos diferentes tipos de configuración que podemos realizar con Nginx. Mientras tanto, podeis encontrar mucha más información en la wiki de Nginx en http://wiki.nginx.org/Main

Un saludo a todos y no dudéis en comentar! ;-)