Usar nginx como reverse proxy (Y utilizar http 2)
17.02.2017 Linux Hosting Apache Nginx HTTP/2Si sos curioso, habrás notado que este blog está usando el protocolo http2 para servir las páginas:
Para esto utilicé una configuración que es bastante popular: Nginx como reverse proxy comunicándose con el cliente y sirviendo el contenido estático, y delegando en Apache (que escucha en otro puerto) el contenido PHP.
Vamos a ver el paso a paso para dejar este stack andando en Ubuntu 16.04.
Instalar Apache, Nginx y PHP7
Como primer y obvio paso, instalamos el stack (para este artículo voy a obviar la instalación de la DB, yo personalmente suelo utilizar mariaDB por sobre MySQL)
Instalamos apache:
sudo apt install apache2
Ya en este momento, si accedemos al server por su IP deberíamos ver la página default de apache en ubuntu:
Como próximo paso, instalamos PHP:
sudo apt install php libapache2-mod-php
Acá solo instalé lo básico, seguramente se van a necesitar varias librerías más (curl, xml, db, etc). Vamos a chequear que PHP esté instalado, creando un archivo info en /var/www/html/info.php con el siguiente contenido:
<?php
phpinfo();
Ahora, yendo a http://ip_publica/info.php deberíamos ver algo así:
Perfecto. Tenemos PHP7 corriendo sobre apache, ahora vamos a instalar nginx como reverse proxy. Para eso tenemos que detener apache (sino la instalación de nginx nos va a dar errores, porque ambos van a querer escuchar por el mismo puerto, el 80). Entonces corremos los siguientes comandos en nuestro server:
sudo apache2ctl stop
sudo apt install nginx
Si ahora nos vamos nuevamente a http://ip_publica, debería ser Nginx el que nos reciba:
Tenemos todo instalado, vamos a configurar un par de cosas.
Modificar los puertos de apache
El que va a servir el contenido al cliente (por los puertos 80 y 443) va a ser nginx, por lo que vamos a modificar apache para que deje esos puertos libres y escuche, por ejemplo, en el 8080 y el 8043. Modificamos entonces el archivo /etc/apache2/ports.conf para que quede así:
Listen 8080
<IfModule ssl_module>
Listen 8043
</IfModule>
<IfModule mod_gnutls.c>
Listen 8043
</IfModule>
Una vez hecho esto, ya podemos habilitar Apache nuevamente, ya que no hay más conflicto con Nginx:
sudo apache2ctl start
(Test rápido: si vamos a http://ip_publica:8080 deberíamos ver la misma página default de Apache que en el 1er paso).
Obtener certificado SSL
Un detalle no menor: si bien en el prótocolo HTTP/2 el uso de cifrado TLS es opcional, los browsers más importantes ya han anunciado que solo soportarán HTTP 2.0 sobre TLS, por lo que vamos a necesitar un certificado para nuestro sitio. Por suerte la gente de Let's Encrypt está haciendo un gran trabajo y obtener un certificado gratuito es hoy bastante sencillo.
Configurar nginx como reverse proxy
Con Apache escuchando en el puerto 8080 y nuestro certificado SSL instalado, es hora de configurar nginx. Vamos a modificar el archivo /etc/nginx/sites-available/default (se puede crear un nuevo archivo en esa carpeta, especialmente si la idea es utilizar vhosts, pero por simplicidad modificaremos el sitio default):
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
root /var/www/html;
index index.php index.html index.htm;
server_name example.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
location ~* \.(gif|jpg|jpeg|js|css)$ {
try_files $uri =404;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 80;
listen [::]:80;
server_name example.com
return 301 https://$server_name$request_uri;
}
Esta configuración hace básicamente lo siguiente:
Escucha en el puerto 443 utilizando el protocolo HTTP/2, y pasa todo a apache (al puerto 8080), excepto el contenido estático (imágenes, js, css). También escucha en el puerto 80 y redirecciona a https. Nota: si se quiere una capa más de seguridad, se puede enviar el contenido al puerto 8043 utilizando TLS, lo cual tendra un pequeño costo en performance.
Y eso es todo. Reiniciamos nginx y tenemos configurado nuestro server con un reverse proxy y sirviendo contenido con HTTP/2.
Hay muchos factores a tener en cuenta que dejé de lado en este artículo (modificar ssl_protocols y ssl_ciphers de Nginx, configurar virtual hosts, modificar los keep alive de ambos servers, etcétera) porque la idea era mantenerlo simple y que sirva como punto de partida para quien quiera utilizar esta configuración que cada vez gana más popularidad.