# Configuraciones básicas para Nginx

[Nginx](https://nginx.org/) es un servidor web que también puede funcionar como proxy inverso, balanceador, etc. Es una alternativa al clásico servidor [Apache](https://httpd.apache.org/), al que parece estar [superando en cuota de mercado](https://w3techs.com/technologies/overview/web_server), además de tener un mejor rendimiento (según diferentes comparativas en Internet, no he hecho personalmente pruebas para poder asegurarlo).

Cuando quise montar un servidor para mis experimentos, sabiendo que querría tener diferentes servicios montados con [Docker](https://www.docker.com/) o [Podman](https://podman.io/), hice una búsqueda rápida de qué opciones serían las más adecuadas, y Nginx aparecía como una opción bastante sólida, así que fue el elegido.

Lo que sigue son unos apuntes rápidos para un servidor de webs estáticas.

## TL;DR

Configuración por defecto para evitar el acceso usando la IP pública del servidor:

```plaintext
server {
    listen                  443         ssl http2 default_server;
    listen                  [::]:443    ssl http2 default_server;

    access_log              <access log file>;
    error_log               <error log file>;

    ssl_certificate         <certificate file>;
    ssl_certificate_key     <certificate key file>;

    server_name             "";
    return                  444;
}
```

Configuración para dirigir todas las peticiones a la versión WWW del servidor:

```plaintext
server {
    listen                  443         ssl http2;
    listen                  [::]:443    ssl http2;

    access_log              <access log file>;
    error_log               <error log file>;

    ssl_certificate         <certificate key>;
    ssl_certificate_key     <certificate key file>;

    server_name             <domain>;
    return                  301 https://www.<domain>$request_uri;
}
```

Configuración para servir páginas estáticas:

```plaintext
server {
    listen                  443         ssl http2;
    listen                  [::]:443    ssl http2;

    access_log              <access log file>;
    error_log               <error log file>;

    ssl_certificate         <certificate key>;
    ssl_certificate_key     <certificate key file>;

    server_name             <WWW domain>;

    location / {
        limit_except        GET { deny all; }
        root                <root directory>;
        error_page          404 /<404 error page>;

        index               index.html;

        try_files $uri $uri/ =404;
    }
}
```

Configuración para devolver un error 404 en los accesos a subdominios inexistentes:

```plaintext
server {
    listen                  443         ssl http2;
    listen                  [::]:443    ssl http2;

    access_log              <access log file>;
    error_log               <error log file>;

    ssl_certificate         <certificate key>;
    ssl_certificate_key     <certificate key file>;

    server_name             *.<domain>;
    return                  404;
}
```

## Elementos comunes en todos los bloques (o casi)

### listen

```plaintext
    listen                  443         ssl http2;
    listen                  [::]:443    ssl http2;
```

Con esta directiva se establecen la dirección y el puerto de escucha del servidor. En nuestro caso únicamente se indica el puerto, tanto para **IPv4** como para **IPv6**.

El parámetro **default\_server** se usa para definir el servidor por defecto que se utilizará en las conexiones realizadas hacia el puerto indicado. Como es lógico, para un puerto solo se podrá definir un servidor por defecto.

Con el parámetro **ssl** se indica que toda comunicación debe estar cifrada, y con el parámetro **http2** se configura el puerto para aceptar conexiones **HTTP/2**.

Para tener documentación más detallada y lo más actualizada posible debemos acudir a la [documentación oficial](http://nginx.org/en/docs/http/ngx_http_core_module.html#listen).

### logs

```plaintext
    access_log              <access log file>;
    error_log               <error log file>;
```

Las directivas **access\_log** y **error\_log** permiten configurar dónde y cómo registrar los accesos y errores del servidor.

En los ejemplos solo se define el fichero donde guardar estos registros, pero hay [disponibles más opciones](http://nginx.org/en/docs/http/ngx_http_log_module.html).

### ssl

```plaintext
    ssl_certificate         <certificate key>;
    ssl_certificate_key     <certificate key file>;
```

Con las directivas **ssl\_certificate** y **ssl\_certificate\_key** se indica dónde están ubicados los ficheros correspondientes al certificado utilizado en las conexiones cifradas con el servidor y su correspondiente clave privada.

Existen más detalles en la [documentación oficial](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate).

### server\_name

```plaintext
    server_name             <domain>;
```

La directiva **server\_name** permite definir qué bloque de servidor se va a utilizar en cada petición. Dependiendo de lo que se defina en los diferentes bloques, se usará uno u otro en un [orden determinado](http://nginx.org/en/docs/http/server_names.html).

En el primer bloque de servidor anteriormente mostrado, se observa que se define el nombre del servidor como una [cadena vacía](http://nginx.org/en/docs/http/server_names.html#miscellaneous_names). Esto permite interceptar las peticiones que se hagan al servidor utilizando su **IP** en lugar de un dominio válido.

### return

```plaintext
    return                  444;
```

Esta directiva permite parar el procesamiento del bloque actual y devolver al usuario el código **HTTP** indicado. Dependiendo de dicho código, la directiva acepta otros parámetros que pueden verse en la [documentación oficial](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return).

## Directiva location

Con la [directiva location](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) se pueden definir configuraciones concretas para URIs concretas. En el bloque de ejemplo se define la configuración para el dominio raíz.

### limit\_except

```plaintext
    limit_except        GET { deny all; }
```

Con [limit\_except](https://nginx.org/en/docs/http/ngx_http_core_module.html#limit_except) se limitan los tipos de peticiones que procesará el servidor para la URI en cuestión. Como el servidor solo va a servir contenido estático, solo aceptará peticiones **GET**.

### root

```plaintext
    root                <root directory>;
```

Establece el [directorio base](https://nginx.org/en/docs/http/ngx_http_core_module.html#root) para las peticiones, y será donde el servidor intente localizar los ficheros y carpetas que se puedan solicitar.

### error\_page

```plaintext
    error_page          404 /<404 error page>;
```

Si se quiere [personalizar las páginas de error](https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page), se pueden crear páginas concretas y asociarlas al tipo de error en cuestión.

### index

```plaintext
    index               index.html;
```

Con esta [directiva](http://nginx.org/en/docs/http/ngx_http_index_module.html) se define la página por defecto que se va a mostrar cuando no se indique ninguna en la petición. Como puede observarse en la documentación oficial, se pueden definir varias páginas diferentes en orden de prioridad.

### try\_files

```plaintext
    try_files $uri $uri/ =404;
```

Finalmente se [intenta localizar](https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files) en el directorio raíz el fichero o carpeta solicitado en la petición, y en caso de no encontrarse se devuelve un error 404.

## Nota final

En estos apuntes iniciales se muestra cómo configurar un servidor web con Nginx para servir páginas web totalmente estáticas. Este software tiene capacidades para ofrecer muchas más funcionalidades, como por ejemplo servir como proxy inverso, que será mi siguiente paso a medida que instale diferentes servicios en mi servidor personal.

Por ahora quedan aquí estos apuntes para poder copiar y pegar de manera rápida una configuración funcional.
