1. Introducción
Esto es un resumen de Saquib Khan
Nginx es:
- Non threaded (en contra de los servidores web tradicionales que son multi-threaded)
- Dirigido por eventos
- Permite manejar más conexiones simultáneas más de 10.000 peticiones concurrentes
- Es apropiado para sitios web de alto tráfico.
- Puede actuar como balaceador de cargas
- Cacheador de request HTTP, reduciendo el tiempo de carga y mejorando la respuesta
- Reverse proxy, pwermitiendo el balanceo de carga delos servidores.
- API gateway, manejando y enrutadno las request por API.
- Servidor de ficheros estáticos (imágenes, vídeos etc)
- Manejo SSL (certificados, conexiones segurasa los usuarios)
2. Forward Proxy y Reverse Proxy
Hemos dicho que Nginx es reverse proxy. Veamos la diferencia respecto a un Forward proxy
Forward Proxy se caracteriza por:
- El proxy está entre el cliente y el servidor. El cliente envia la petición al proxy y este al servidor.
- El servidor se desvincula del cliente, intereactuando solo con el proxy. Esto permite la privacidad y superar las restricciones geográficas. (VPN es un ejemplo)
Reverse Proxy se caracteriza por:
- Se situa entre el cliente y múltiples servidores, decidiendo que server va a recibor el request.
- El cliene desconoce que servidor le contesta.
- Los criterios de selección de servidores pueden ser por la ruta (por ejemplo /admin se entruta al servidor 1 y /settings al servidor 2). Es decir se predefinen reglas para la redirección de servidores.
3. Instalación de nginx
Si lo instalamos en docker
# 1. Instalar Ubuntu en un contenedor docker usando el puerto 8080 de la máquina local y el puerto 80 del contenedor
docker run -it -p 8080:80 ubuntu
# 2. Instalar nginx
apt-get update
apt-get install nginx
# 3. Verificar la instalación
nginx -v
Si lo instalamos en la máquina local
# 1. Instalar nginx en Ubuntu
sudo apt update
sudo apt install nginx
# 2. Arrancar nginx
sudo systemctl start nginx
# 3. Verificar
sudo systemctl status nginx
4. Entender el fichero de configuración nginx.conf
Este fichero se encuenta en /etc/nginx/nginx.conf
Veamos el contenido de un fichero ejemplo:
worker_processes auto;
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 /usr/share/nginx/html;
index index.html index.htm;
}
}
}
Veamos las claves:
Un worker process se encarga del manejo de las peticiones. Con la opción auto dejamos enmanos de nginx que cree el número de workers en base a los cores de la CPU
events { worker_connections 1024; }
events indica la configuración del manejo de conexiones. worker_connections 1024; indica que cada worker puede manejar hasta 1024 conexiones simultáneas.
http {...}
Define la configuracion del manejo de las request HTTP
include mime.types;
Le indica a nginx la inclusión del fichero mime.types que mapea la extensión de un fichero a los tipos MIME. Por ejemplo .html como text/html, .jpg como image/jpeg )
default_type application/octet-stream;
Si no se puede obtener el tipo mime de un fichero, se utilizará por omisión application/octet-stream que significa "descargar este fichero"
sendfile on;
Para utilizar la llamada del sistema"sendfile" que permite el copiado de ficheros entre servidores o redes sin utilizar passar por los buffers de la memoria del usuario.
Ver CocCoc Techblog
keepalive_timeout 65;
Determina el tiempo que una conexión estará abierta en segundos antes que nginx la cierre. Por defecto son 65 segundos
5. La parte mas importante de nginx.conf: server
server
Para configurar un servidor virtual, por ejemplo un servidor que maneja la "request"para un dominio específico i una dirección IP
Repitamos esta parte:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
listen 80;
Le indica a nginx que escuche las peticiones del puerto 80. Sabemos que el puerto 80 es el puerto por omisión para HTTP
server_name localhost;
indica el nombre de dominio que este bloque de configuración del servidor va a responder. localhost se usa para test local, pero en producción se debe reemplazar por el dominio (por ejemplo example.com)
location / { ... }
Indica como responder a diferentes URIs de la "request". "/" indica que este bloque manejará las las "request" de la URL root . En este caso http:/localhost/ pues el server_name del punto anterior es localhost
root /usr/share/nginx/html;
La directiva root indica la carpeta donde nginx buscará los ficheros a servir. En este caso /usr/share/nginx/html que es la carpeta donde nginx guarda los ficheros HTML por omisión.
index index.html index.htm;
Cuando la request apunta a un directorio sin indicar un fichero de dicho directorio, entonces nginx buscará un fichero llamado index.html o index.htm dentro de dicho directorio para servirlo
6. Configuración básica de prueba de nginx
Supongamos que creamos este fichero para probar nginx ( /etc/nginx/nginx.conf). Ojo hacer una copia de seguridad del fichero anterior.
events {
}
http {
server {
listen 80;
server_name _; # This means it will respond to any server name
location / {
return 200 "Hello from Nginx Conf File";
}
}
}
Con esto, cualquier petición a cualquier servidor va a responder "Hello from Nginx Conf File"
pero hay que hacer un
nginx -s reload
Si creamos un directorio llamado /www/data y dentro de el creamos el fichero index.html
mkdir -p /www/data
echo "<h1>Welcome to Nginx</h1>" > /www/data/index.html
Podemos modificar la parte server del fichero nginx.conf con el posterior nginx -s reload para que muestre el contenido del fichero /www/data/index.html que es "<h1>Welcome to Nginx</h1>" . La "request" que debemos realizar es http://localhost:8080 que es la que apunta a "/"
server {
listen 80;
server_name localhost;
root /www/data;
location / {
try_files $uri $uri/ =404;
}
}
Observar que $uri es la ruta del recurso por ejemplo http://example.com/path/to/resource, $uri sería /path/to/resource.
7. Los bloques Server, Location y Upstream
Como se vió, el bloque server define laconfiguracion oara un dominio particular o dirección IP.
El bloque location define como responder a las URIs de "requests" específicas, por ejemplo:
location /images/ {
root /var/www/images;
}
que indica que para un servidor específico cuando accedemos a /images nos servirá los fichero de la carpeta /var/www/images
El bloque upstream define un grupo de servidors backend (segundo plano) para el balanceo de cargas, por ejemplo:
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
8. Reverse Proxy
Veamos unaconfiguración como reverse proxy
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
proxy_pass http://backend_server;
Para pasar la "request" a http://backend_server o sea backend_server va a ser el servidor encargado de responder a la "request"
proxy_set_header Host $host;
Asegura que el "header" del host original es pasado al servidor backend_server. La variable $host representa el valor del encabezado Host original de la "request" del cliente. Si elencabezado Hos noesta presente en la "request" toma el nombre sel servidor definido en server_name (en este caso example,.com) o dirección IP del servidor
proxy_set_header X-Real-IP $remote_addr;
Envía la dirección IP real del cliente al servidor de destino.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Agrega la dirección IP del cliente a la lista de encabezados X-Forwarded-For ,que es usado por el backend para identificar la IP original del cliente
9. Balanceo de carga
Veamos este ejemplo:
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
upstream backend { ... }
Define la lista se servidores backend
server backend1.example.com;
Añade dicho servidor a la lista de backend servers
proxy_pass http://backend;
Redirige la "request" a uno de los servidores de la lista de servidores backends
10. Securizando con SSL/TLS
Este protocolo encripta la transmisión entre cliente y servidor. Veamos como se configura:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
location / {
root /var/www/html;
index index.html;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Vemos que aparecen dos bloques server, uno para ssl (https) y otro http
listen 443 ssl;
Indica que utilice escuche el puerto 443 (por defecto el de https) con SSL habilitado
ssl_certificate /etc/nginx/ssl/example.com.crt;;
indica la ruta del certificado del servidor a utilizar por nginx
ssl_certificate_key /etc/nginx/ssl/example.com.key;
Indica la ruta donde está la clave del certificado de servidor
return 301 https://$host$request_uri;
return sirve para redirigir.
301 és el código de estado HTTP que indica Redirección permanente, indicando al navegador del cliente que el recurso solicitado se ha movido ae manera permanente a una nueva dirección.
https://$host$request_uri redirige al cliente a la misma dirección pero utilizando el protocolo https.
$host representa elbombre del host (en este caso example.com)
$request_uri incluye la ruta completa y los parámetros de la solicitud original, asegurando que la redirección sea precisa
11. Cacheando
Nginx puede cachear las respuestas del servidor backend para acelerar los tiempos de respuesta para posteriores "requests"
Por ejemplo:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
proxy_cache_path
Establece la carpeta y configuración para el caché, en este caso /var/cache/nginx
levels=1:2
Define la estructura del directorio para la caché. La estructura tendrá:
- 1 nivel con un subdirectorio de 1 carácter
- 2 niveles adicionales con subdirectorios de 2 caracteres cada uno
Con ello se distribuyen los archivos en múltiples directorios, evitando tener muchos archivos en una sola carpeta
keys_zone=my_cache:10m
Crea una zona de memoria compartida llamada my_cache con 10 MB de memoria. Esta zona compartida se utiliza para almacenar metadatos de los objetos de caché como claves y tiempos de expiración
max_size=1g
Limita el tamaño máximo a 1 GB. Cuando se alcanze este límite , se eliminan los objetos menos utilizados (uando el algoritmo LRU, "Least Reacently Used"
inactive=60m
Elimina los elementos del caché si no se ha accedido a ellos durante 60 minutos
12. Monitoreando y logging
Nginx hace una bitácora (log) de todas las peticiones y errores, permitiendo el control de errores (troubleshooting) y monitoreo
En este ejemplo:
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;
log_format main ...
Define un formato a medida de bitácora llamado main
Siendo:
$remote_addr la dirección IP del cliente que realizó el "request"
$remote_user el nombre del usuario autenticado si se utilizó la autenticación HTTP. Sinó se ha autenticado queda vacío
[$time_local] La hora local en que se realizó la petición en formato [día/mes/año:hora:minuto:segundo zona_horaria]
"$request" La solicitud HTTP completa, incluyendo el método (GET, POST...), el URI, y la versionb del protocolo, por ejemplo: GET /index.html HTTP/1.1
$status el código del estado devuelto, por ejemplo 200, 404, 500
$body_bytes_sent el número de bytes enviados al cliente, excluyendo los encabezados de respuesta.
"$http_referer" el encabezado Referer enviado por el cliente, que indica la página que ha visitado el cliente previamente para acceder al sitio actual.Si no hay un referer, queda vacío.
"$http_user_agent" el encabezado User-Agent, que identifica al cliente (por ejemplo, un navegador o una herramienta de línea de comandos).
"$http_x_forwarded_for" el encabezado X-Forwarded-For, que contiene las direcciones IP de los clientes originales en caso de que Nginx actúe como un proxy inverso. Si no existe este encabezado, queda vacío.
access_log /var/log/nginx/access.log main;
Almacena la bitácora de accesos en el fichero especificado (/var/log/nginx/access.log main) usando el formato de log definido como main
Veamos este ejemplo, donde un cliente con la dirección 192.168.1.1 accedeal recurso /index.html. Entonces se tendría una entrada como esta en el fichero de registro
192.168.1.1 - - [03/Jan/2025:12:34:56 +0000] "GET /index.html HTTP/1.1" 200 1024 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "-"
Siendo:
192.168.1.1: Dirección IP del cliente.
-: Sin usuario autenticado.
[03/Jan/2025:12:34:56 +0000]: Fecha y hora de la solicitud.
"GET /index.html HTTP/1.1": Solicitud HTTP realizada.
200: Código de estado HTTP.
1024: Bytes enviados al cliente (excluyendo encabezados).
"-": Sin Referer.
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)": User-Agent del cliente.
"-": Sin encabezado X-Forwarded-For
Los errores típicos que se reciben son:
400 Bad Request, 401 Unauthorized, 403 Forbidden, y 404 Not Found: Errores del cliente.
500 Internal Server Error, 502 Bad Gateway, y 503 Service Unavailable: Errores del servidor.
13. Códigos de estado típicos
En general los códigos de error típicos que se pueden obtener son:
1xx - Respuestas informativas
Indican que la solicitud fue recibida y el servidor está procesándola.
100 Continue: El cliente puede continuar con su solicitud.
101 Switching Protocols: El servidor acepta cambiar a un protocolo diferente solicitado por el cliente.
103 Early Hints: El servidor envía encabezados preliminares antes de la respuesta final.
2xx - Éxito. La solicitud se procesó correctamente.
200 OK: La solicitud fue exitosa y el servidor devolvió el contenido solicitado.
201 Created: La solicitud fue exitosa y se creó un nuevo recurso.
202 Accepted: La solicitud fue recibida, pero su procesamiento no ha concluido aún.
204 No Content: La solicitud fue exitosa, pero no hay contenido que devolver.
206 Partial Content: Se devuelve parte del contenido solicitado, usado en solicitudes con rangos.
3xx - Redirecciones. Indican que el cliente debe tomar medidas adicionales para completar la solicitud.
301 Moved Permanently: El recurso solicitado se ha movido de manera permanente a una nueva URL.
302 Found: El recurso se encuentra temporalmente en una ubicación diferente.
303 See Other: La respuesta está disponible en una URL diferente (usado después de una solicitud POST para redirigir a una página de confirmación).
304 Not Modified: Indica que el recurso no ha cambiado desde la última vez que fue solicitado (usado con caché).
307 Temporary Redirect: La redirección es temporal y debe usar el mismo método HTTP.
308 Permanent Redirect: Similar a 301, pero obliga a usar el mismo método HTTP.
4xx - Errores del cliente. Indican que la solicitud del cliente contiene un error.
400 Bad Request: La solicitud no es válida debido a un error de sintaxis.
401 Unauthorized: El cliente no está autenticado (requiere credenciales).
403 Forbidden: El cliente no tiene permisos para acceder al recurso.
404 Not Found: El recurso solicitado no existe en el servidor.
405 Method Not Allowed: El método HTTP usado no está permitido para el recurso.
408 Request Timeout: El servidor agotó el tiempo de espera para la solicitud.
409 Conflict: Hay un conflicto con el estado actual del recurso (por ejemplo, datos duplicados).
410 Gone: El recurso ya no está disponible y no se sabe su ubicación.
413 Payload Too Large: El cuerpo de la solicitud supera el límite permitido por el servidor.
414 URI Too Long: El URI de la solicitud es demasiado largo para ser procesado.
429 Too Many Requests: El cliente ha enviado demasiadas solicitudes en un tiempo determinado (límite superado).
5xx - Errores del servidor. Indican que el servidor falló al procesar la solicitud.
500 Internal Server Error: Error genérico cuando el servidor encuentra una condición inesperada.
501 Not Implemented: El servidor no soporta la funcionalidad requerida.
502 Bad Gateway: El servidor recibió una respuesta inválida de un servidor upstream.
503 Service Unavailable: El servidor no está disponible temporalmente, generalmente por mantenimiento o sobrecarga.
504 Gateway Timeout: El servidor upstream no respondió a tiempo.
505 HTTP Version Not Supported: El servidor no soporta la versión del protocolo HTTP usada en la solicitud.