Nginx es un servidor web que también puede funcionar como proxy inverso, balanceador, etc. Es una alternativa al clásico servidor Apache, al que parece estar superando en cuota de mercado, 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 o Podman, 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:
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:
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:
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:
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
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.
logs
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.
ssl
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.
server_name
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.
En el primer bloque de servidor anteriormente mostrado, se observa que se define el nombre del servidor como una cadena vacía. Esto permite interceptar las peticiones que se hagan al servidor utilizando su IP en lugar de un dominio válido.
return
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.
Directiva location
Con la directiva 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
limit_except GET { deny all; }
Con 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
root <root directory>;
Establece el directorio base para las peticiones, y será donde el servidor intente localizar los ficheros y carpetas que se puedan solicitar.
error_page
error_page 404 /<404 error page>;
Si se quiere personalizar las páginas de error, se pueden crear páginas concretas y asociarlas al tipo de error en cuestión.
index
index index.html;
Con esta directiva 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
try_files $uri $uri/ =404;
Finalmente se intenta localizar 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.