7.2.2.1. Principios de configuración

7.2.2.1.1. Instalación

Para versiones recientes de Debian (sobre todo a partir de Bookworm) basta con:

# apt install nginx

pero la regla es, en realidad, una simplificación que merece una explicación:

nginx hasta su versión 1.9.11 tenía un sistema de módulos que obligaba a añadirlos monolíticamente al ejecutable, es decir, que no se podían cargar dinámicamente a través de la configuración, sino que en la compilación se añadían al núcleo del programa. Por esa razón, los empaquetadores de Debian crearon tres sabores dependiendo de cuáles fueran los módulos que se habían incluido en la compilación:

nginx-light,

que incluía el menor número de módulos.

nginx-full,

que incluía un mayor número de módulos, además de algunos módulos de terceros. nginx a secas, era simplemente un metapaquete que forzaba la instalación de esta versión completa.

nginx-extras,

que incluía más módulos aún, tanto propios como de terceros.

De este modo, dependiendo de si necesitábamos más o menos módulos para la configuración del servidor, instalábamos uno u otro. Desgraciadamente, si requeríamos un módulo no incluído en estos tres sabores, debíamos compilar toda la aplicación[1].

Al añadir nginx la posibilidad de cargar módulos de forma dinámica, Stretch (que incluyó la versión 1.10.3), produjo ejecutables con la posibilidad de cargar dinámicamente módulos. Sin embargo, se mantuvieron los tres sabores enumerados, cada uno de cuyos ejecutables contenía un número distinto de módulos compilados estáticamente[2]. La única diferencia respecto a la versiones anteriores es que Debian incluyó paquetes con módulos adicionales que podían instalarse y cargarse dinámicamente con cualquiera de los tres sabores[3]. Además, cada sabor podía añadir dependencias a paquetes de módulos dinámicos.

Bullseye mantuvo esta situación con dos diferencias:

  • La primera fue añadir un nuevo sabor:

    nginx-core

    que era un sabor casi equivalente a nginx-full, pero sin incluir estáticamente ningún módulo de terceros.

  • La segunda, que nginx dejó de ser un metapaquete que instalaba forzosamente nginx-full y pasó a ser uno que instalaba cualquiera de los cuatro.

Y, finalmente, apareció Bookworm, que unificó los ejecutables en uno solo. A partir de esta versión, el paquete nginx es el que contiene el ejecutable del servidor (esto es, /usr/sbin/nginx) con un número mínimo de módulos compilados estáticamente, y los cuatro sabores ya mencionados son metapaquetes que instalan éste y añaden dependencias a paquetes de módulos dinámicos, por lo que la única diferencia entre ellos es la cantidad de paquetes de módulos instalados automáticamente.

Advertencia

Si trabaja con una versión anterior a Bookworm es posible que le salga más a cuenta instalar nginx-light, porque apenas hay aspectos recogidos en esta guía que no se puedan resolver con esta versión. Para Bookworm y posteriores instale nginx por la misma razón y añada módulos dinámicos según convenga.

7.2.2.1.2. Ficheros de configuración

La configuración de nginx está incluida toda dentro de /etc/nginx. Los ficheros y directorios relevantes son los siguientes:

/etc/nginx
   +--- conf.d/
   +--- modules-available/
   +--- modules-enabled/
   +--- nginx.conf
   +--- sites-available/
           +--- default
   +--- sites-enabled/
           +--- default -> ../sites-available/default
   +--- snippets/
           +--- fastcgi-php.conf
           +--- snakeoil.conf

cuyo significado podemos desglosar así:

nginx.conf

Es, en sí, el fichero de configuración. el resto de configuración existente en este directorio se aplica, bien porque este fichero la carga directamente, bien porque un fichero cargado por él, la carga a su vez.

conf.d

Contiene ficheros con trozos de configuración que nginx.conf siempre carga si su extensión es *.conf.

snippets

Es un directorio destinado a contener también ficheros con trozos de configuración, pero a diferencia de los contenidos en el directorio anterior, sólo se aplicarán si son expresamente citados dentro de otros ficheros de configuración. Debian trae dos configuraciones ya definidas que podemos aprovechar:

  • fastcgi-php.conf para la configuración de PHP.

  • snakeoil.conf que incluye las líneas necesarias para usar el certificado autofirmado del servidor.

Para aplicar una configuración incluida en este directorio debe utilizar en la línea en que queramos que se aplique la directiva include:

include snippets/snakeoil.conf;
sites-available

Un mismo servidor web puede alojar distintos sitios web mediante el mecanismo de dominios virtuales. Este directorio está destinado a albergar la definición de todos los dominios virtuales. Ya se verá más adelante esto con mayor profundidad.

sites-enabled

Contiene los dominios virtuales habilitados. Los que no se encuentren aquí, no forman parte de la configuración y por tanto es como si no se hubieran definido. Para habilitar dominios basta, simplemente, con hacer enlaces simbólicos que apuntes a las definiciones incluidas en sites-available.

modules-available

Para cargar dinámicante un módulo la documentación de nginx indica que debe incluirse en la configuración una línea así:

load_module modules/nonbre_del_modulo.so

Para simplificarlo, Debian incluye un fichero de configuración para cada módulo con su línea load_module correspondiente, con lo que cargar el fichero de configuración, implica cargar el módulo. Como Debian prefiere alojar para sus paquetes estos ficheros en /usr/share/nginx/modules-available/, en este directorio sólo cabría crear ficheros de configuración para módulos que hubiéramos compilado nosotros mismos.

modules-enabled

Son enlaces simbólicos a los módulos que realmente se cargan al arrancar nginx. Cada vez que se instala en el sistema un paquete correspondiente a un módulo, Debian crea el enlace simbólico que apunta al fichero de configuración correspondiente en /usr/share/nginx/modules-available. Por supuesto, si algún módulo no lo usamos, podemos aligerar nginx eliminando el enlace (y reiniciando el servidor, claro).

En la práctica:

  • nginx.conf se modifica si se desea alterar alguna directiva citada en él.

  • Se escribe algún fichero conf.d, si se desea añadir configuración predeterminada a la labor HTTP de nginx[4].

  • Nuestra tarea se basa fundamentalmente en crear sitios cuya configuración se creará en un fichero dentro de sites-available que luego se enlazará desde sites-enabled.

  • Si algún trozo de configuración es recurrente en varios sitios, o bien deseamos apartarla para tenerla mejor controlada y organizada, podemos crear un snippet para ella e incluir tal snippet con la directiva include en el fichero de configuración del sitio correspondiente.

7.2.2.1.3. Módulos adicionales

Como hemos instalado nginx-light puede ocurrir que en algún momento necesitemos un módulo empaquetado que no instala automáticamente este sabor. Supongamos que tal módulo es libnginx-mod-http-auth-pam. En ese caso:

# apt-get install libnginx-mod-http-auth-pam

El script de postinstalación se encarga de todo, así que nos podemos limitar a comprobar que en /etc/nginx/modules-enabled se ha creado el enlace adecuado:

# ls -F /etc/nginx/modules-enabled/*pam*
50-mod-http-auth-pam.conf@

Nota

Por supuesto podemos deshabilitar módulos innecesarios eliminado los enlaces simbólicos correspondientes en ese directorio.

7.2.2.1.4. Configuración básica

Para ilustrar la configuración, tomemos una muy básica que sirve contenido estático y analicémosla. En principio, editemos /etc/nginx/sites-available/default y dejémoslo con este contenido:

server {
   listen  80;
   server_name _;

   root /srv/www;
   try_files $uri $uri/ =404;
}

Cada directiva server nos permite configurar un dominio virtual y es lo que hemos hecho. Por ahora:

  • sólo nos preocuparemos de definir una que escucha por el puerto 80 (listen)

  • en el que no preocupa cuál sea el nombre (la cabecera Host, de ahí el valor de server_name)

  • en que todos los ficheros compartidos a través del servidor se sitúan bajo /srv/www[5], merced a la directiva root

  • la directiva try_files le indica al servidor qué recursos debe intentar devolver al realizarse una petición. En la configuración propuesta, primero se intenta devolver el propio recurso; si éste no es un fichero, debe comprobarse si es un directorio y en tal caso tratarlo como tal; y, si tampoco es un directorio, devolver un error 404. Una alternativa podría haber sido:

    try_files $uri $uri/ /
    

    en este caso, cuando el recurso no se encontró como fichero ni como directorio, no se genera un error, sino que se devuelve la página principal. Por tanto en esta configuración, jamás se devolverá al cliente un error de recurso inexistente.

Nota

Si miramos dónde se inserta este fichero dentro de nginx.conf, comprobaremos que lo hace en un bloque http. O sea que un bloque server se inserta dentro de un bloque http. Esto es importante tenerlo en cuenta porque la configuración de nginx se estructura en contextos: el global, el http, el server, etc.` que se anidan unos dentro de otros. Cuando consultemos la documentación oficial, podremos comprobar que para cada directiva se define en qué contextos es válida.

Para rematar la configuración, debemos probarla. Para ello, podemos escribir una página principal simple en /srv/www/index.html:

<!DOCTYPE html>
<html lang="es">
   <title>Página principal</title>
   <meta charset="utf-8">
   <h1>Página principal</h1>
</html>

Y, por último, usar un navegador para acceder a la página usando, por ejemplo, la propia IP de la máquina en la que hayamos instalado el servidor.

Sobre esta configuración básica podemos añadir algunas modificaciones:

  • La directiva listen puede incluir explicitamente la interfaz en la que queremos que escuche. Por ejemplo:

    listen localhost:80;
    

    ya que cuando se indica únicamente el puerto se sobreentiende que escuchará en todas las disponibles.

  • Esta misma directiva puede usarse repetidamente para escuchar en múltiples puertos o múltiples interfaces, de modo que:

    listen  80;
    listen  8080;
    

    hará que el servidor escuche tanto en el puerto 80 como en el 8080[6].

  • Si en el navegador hemos usado esta dirección (cambiése la ip por la que toque):

    http://192.168.1.11
    

    para pedir la página, deberíamos ser conscientes de lo que ha ocurrido. No hemos incluido ruta alguna para especificar el recurso, así que nginx no encuentra el «no recurso» (por llamarlo de alguna forma). Siguiendo la directiva try_files añade una barra y entonces prueba a pedir el directorio raíz e, inexplicablemente, se devuelve el recurso /index.html. Obviamente el suceso tiene explicación. Cuando nginx se encuentra con que se le pide un directorio, revisa una directiva llamada index para saber cuáles son los fichero que se consideran de índice y que se mostrarán. El valor predeterminado de esta directiva es:

    index index.html;
    

    así que esa es la razón por la que se sirve la página simple que preparamos. La directiva, por supuesto, admite que le cambiemos el valor o incluso que pongamos varios para que nginx pruebe su existencia ordenadamente. Por ejemplo:

    index index.html index.htm;
    

    probaría si existen index.html y, si no es así, prueba index.htm. Ahora bien, ¿qué ocurre si no existen tales ficheros de índice? En ese caso, nginx mostrará el contenido del directorio, pero sólo si se añade la directiva autoindex:

    autoindex on;
    autoindex_exact_size off;  # Muestra unidades k, m, M, etc. y no bytes siempre
    

    que por defecto tiene valor off.

La configuración, además, admite algunos añadidos interesantes:

  • nginx registra los accesos y los accesos fallidos dentro de los ficheros access.log y error.log del directorio /var/log/nginx, ya que así de define dentro nginx.conf mediante las directivas access_log y error_log. A este respecto es importante tener claras dos cosas:

    • Es común definir distintos ficheros de registro para distintos dominios virtuales, así que podríamos incluir dentro del bloque server estas dos directivas con ficheros alternativos.

    • Si en un mismo contexto se definen varios access_log (o error_log), se escribirán registros en los ficheros que definen todas las directivas. Sin embargo, cuando en un contexto inferior se define la directiva, ésta sobreescribe las definiciones que pudieran haberse hecho en un contexto superior.

    • Estos ficheros se escriben directamente y no pasan por el gestor de registros (systemd o rsyslog, según el caso). Para propiciar que nginx use el gestor, vea más adelante cómo.

  • nginx tiene unas páginas predefinidas para informar al cliente de los errores (403, 404, 502, etc.). Podemos, no obtante, crear páginas personalizadas y hacer que nginx las envíe al cliente en vez de las predefinidas:

    error_page 404                      /errors/404.html;
    error_page 500 502 503 504          /errors/50X.html;
    

Notas al pie