"all-in-one" es la descripción que posa en la página oficial de nginx, sin duda es una herramienta muy versátil, entre sus principales usos está el balanceador de carga, proxy reverse y hasta de web server (entrando aquí en una disputa por el puerto 80 con el gran apache) ver Figura 1, en esta ocasión hablaré un poco de la gran utilidad que podemos obtener con herramientas como nginx trabajando como reverse proxy brindando una capa adicional de configuración y de cierta forma quitando también una capa de complejidad para temas relacionados con certificados SSL

Figura 1 guerra por el puerto 80 obtenido de https://twitter.com/turnoff_us/status/822561117537009664

Proxy Reverse

Uno de los mayores usos de nginx es utilizarlo como proxy reverse (aquí pueden ver testimonios de su uso) podría definirse como un elemento de una arquitectura que interactúan entre clientes y uno o más servidores (de ahí es donde vendría su uso como balanceador de cargas) el objetivo aquí es que todas las peticiones hacia una aplicación pasen primero por el proxy reverse, este las limpia, transforma  y valida  después de ello envía esta petición a la aplicación y la respuesta de la aplicación se le devuelve al respectivo cliente como se aprecia en la Figura 2, el objetivo de usar aquí como proxy reverse a nginx es liberar trabajo de nuestras aplicaciones y algunas configuraciones que pueden ser tediosas, bien iniciare por los ejemplos de configuración

Figura 2:  Arquitectura básica del funcionamiento de nginx como proxy reverse

Configuración Básica

Cuando se instala nginx por defecto en ubuntu en la carpeta /etc/nginx encontraran un archivo llamado nginx.conf que contiene la configuración de entrada de nginx donde está el puerto en que se levantara por defecto el 80 (si tienen otra aplicación deben gestionar los puertos) hay una carpeta aquí llamada conf.d/ donde  se ubicaran las configuración que usare para mis dominios, estos deben tener una terminación .conf y tiene una sintaxis básica como se aprecia a continuación

server {
    listen       80;
    server_name  myapp.jairoandres.com;


     location / {
        proxy_pass http://127.0.0.1:9000;

    }

    
    
}

en este caso estoy ejecutando en mi servidor una app en python en el puerto :9000 pero solamente en localhost, para darle salida al acceso público utilizó nginx la estructura de su sintaxis la describo a continuación

  • server es como inician todas las configuraciones que se quieren hacer con nginx aquí se pueden tener algunos atributos al mismo nivel como listen que es el puerto en el que se ejecuta y server_name el dominio desde donde vendrá la petición y se capturara
  • location es un "match" que captura una url y le pasa esa petición a cierta acción en este caso captura todo el path "/" y le pasa todas las peticiones a la aplicación en python, ejemplo si yo entro a http://myapp.jairoandres.com/home pasara esta peticion a http://127.0.0.1:9000/home
  • proxy_pass es una acción que se ejecuta en donde se dice que la solicitud al servidor público proxy es reemplazado por el parámetro que es puesto en proxy pass que puede ser una url o una ip, es decir que cuando llega una petición al servidor público nginx la recibe  y ejecuta un llamado al parámetro que está en proxy pass con su location match  como se aprecia en la Figura 3
Figura 3: Arquitectura compuesta con archivos de configuración de nginx

Modificando encabezados

Como se ha podido apreciar al final del día la petición a mi aplicación independiente del cliente siempre se hará desde nginx, esto hace que algunas veces unos parámetros de los headers se pierdan por ello deben setearse a los parámetros de cada cliente que realiza la petición, a continuación se muestra un ejemplo de los principales parámetros

server {
    listen       80;
    server_name  myapp.jairoandres.com;


     location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
	    proxy_read_timeout 610s;

    }

    
    
}
  • Host indica desde donde se está realizando la petición, este valor del header debe modificarse por que al realizarse la petición desde nginx este valor muchas veces toma el valor de localhost un ejemplo de cómo se vería el encabezado sería
GET /home HTTP/1.1
Host: www.myfront.jairoandres.com

es importante aclarar que en la versión HTTP 1 este atributo es obligatorio

  • HTTP version por defecto la versión que utiliza para llamar a la aplicación nginx es la versión 1, sin embargo algunas veces se requiere cargar grandes contenidos de archivos estáticos y diferentes peticiones disparadas al tiempo, por lo que se necesita utilizar el concepto de keepalive connections ver Figura 4 y tener un mejor rendimiento, esto es implementado en la versión HTTP 1.1 por lo tanto se debe setear este encabezado
Figura 4: Explicacion de keealive connections obtenido de https://www.nginx.com/blog/http-keepalives-and-web-performance/

Certificado SSL

Letscrypt es un Certificate Authority (CA) que permite generar certificados usando el ACME protocol , por medio de esta herramienta es posible obtener certificados ssl de forma gratuita y muy fácil ya que han desarrollado una herramienta guiada llamada certbot desarrollada en python que ha automatizado el proceso de certificación, esto lo mostraré a continuación, primero se debe instalar certbot

sudo snap install core; sudo snap refresh core

el comando anterior permite actualizar la versión de snap, la plataforma de certbot tiene una gran cantidad de tutoriales no solo del sistema operativo si no de herramientas en específico en este caso sobre nginx siguiendo el proceso de instalación referenciado después se procede a generar el certificado

sudo certbot --nginx

esta tool lee la carpeta conf.d/ y genera un certificado para los sitios que se desee por ello es importante tener configurado los dominios y apuntando sus dns a el servidor ya que es de esta manera que letsencrypt verifica el control del dominio, en mi caso yo configure el dominio myapp.jairoandres.com

Figura 5: Generación de certificados ssl con letsencrypt

aqui seleccionas el dominio a generar el certificado luego de ello letsencrypt realiza la validación del dominio y genera las llaves

Figura 6: Generación de certificados ssl con letsencrypt

y listo con esto ya se tiene la gestión de las llaves para tener certificado ssl muy fácil esto gracias a que certbot realiza toda la tarea pesada reduciendo todo a 2 comandos, finalmente como se puede apreciar anteriormente la arquitectura que se plantea con nginx se puede ver en la Figura 7 donde nginx es el encargado de tener las configuraciones de las diferentes dominios y certificados para permitir la comunicación utilizando SSL, luego de ello este se encarga de llevar la petición a la aplicación correspondiente utilizando el protocolo HTTP

Figura 7: Arquitectura final de nginx con ssl

Conclusión

Nginx funciona como un componente muy versátil dando soporte para muchas tareas algunas de ellas relacionadas a servir documentos estáticos y otras como se vio en en este artículo fungir como reverse proxy con una configuración bastante sencilla quitando trabajo a las aplicaciones desarrolladas y además agregando una capa adicional que puede servir como filtro de seguridad