Instalar Nginx con Pagespeed y Certbot

Let's Encrypt + Http/2 + Nginx + Pagespeed

No es la primera vez que me enfrento a esta tesitura, de hecho ya he hecho alguna entrada previa en el blog, sin embargo me he dado cuenta que de práctico tiene bastante poco, sobre todo en cuanto a lo que se refiere a obtener certificados SSL gratuitos con certbot. Recordemos que Nginx debe ser compilado en específico con el módulo de Apache pagespeed, y esto hace que salte por los aires cualquier integración que terceras herramientas tengan con el servidor, amén de otras configuraciones que trae por defecto tu distribución y que no podrás usar.

Dividiremos este artículo en tres partes para facilitar la lectura: la primera tratará sobre cómo compilar nginx, la segunda parte sobre la configuración y tendremos una última para pedir un certificado SSL con nuestra configuración. Comentaré que dejamos atrás mucha configuración relacionada con pagespeed o cacheo de peticiones, pero lo trataremos seguramente en siguientes entregas.

Instalando y compilando Ngnix con Pagespeed

Vuelvo a citar al artículo publicado previamente por si necesitáis volver a él para alguna aclaración, pero pondremos por aquí todo para evitar dispersiones y sobre todo para actualizar alguno de los comandos, que desde hace tiempo han cambiado, aunque sea ligeramente.

Logo del proyecto Apache Pagespeed

Empezaremos instalando algunos paquetes que, dependiendo de qué distribución estés usando, es posible que no vengan por defecto y así evitamos repetir ciertos pasos de este proceso. Como estamos en Ubuntu 20.04, los paquetes son los siguientes. Podrían variar si estamos ante otra distribución:

sudo apt update && sudo apt upgrade
sudo apt install libssl-dev

Lo siguiente que debemos hacer, es, como siempre, acudir a nuestras fuentes, en este caso a la página del proyecto, y no deberíamos tardar mucho en encontrar las instrucciones a seguir. Ahí veremos que se nos sugiere un comando para una «automated install», y por lo que he probado, creo que es la mejor opción y la más rápida. Se limita a un único comando:

bash <(curl -f -L -sS https://ngxpagespeed.com/install) --nginx-version latest

Durante la ejecución del instalador se nos pedirá que, si queremos opciones adicionales de compilación, que las escribamos en ese momento. Nosotros pondremos las siguientes:

--with-http_ssl_module --with-http_v2_module

Si todo ha ido como debería, el resto del proceso debería ser nítido y transparente: nos preguntará si deseamos continuar un par de veces, y eventualmente, cuando dejemos de ver las llamadas al compilador, tendremos nuestra instalación en /usr/local/nginx. Este pequeño detalle empezará a ser la madre de todos nuestros problemas que intentaremos ir resolviendo a continuación.

Configuración de Nginx

Tal y como he comentado antes, tener la instalación en la carpeta /usr/local no indica que las cosas vayan a ser fáciles. Sin embargo trataremos de imitar la ruta de carpetas y demás para que cuando venga certbot sepa encontrar dónde generar e instalar los certificados.

Logo Nginx
Logo de Nginx

Lo primero que haremos será crear un servicio para systemd de tal forma que podamos iniciar y parar nuestro servidor con systemctl. Tal y como nos indican en la documentación oficial, tendremos que crear un archivo /lib/systemd/system/nginx.service y poner el siguiente contenido:

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

El lector avispado habrá notado que el binario /usr/sbin/nginx no existe todavía. El siguiente paso es, precisamente, crear un enlace a él:

ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx

Para la configuración, crearemos una carpeta en /etc/nginx que contendrá los ficheros que se necesitarán y modificaremos. Creamos también de golpe algunos enlaces simbólicos a carpetas y otros ficheros que nos serán necesarios.

mkdir -p /etc/nginx
ln -s /usr/local/nginx/conf /etc/nginx/conf
ln -s /etc/nginx/conf/nginx.conf /etc/nginx/nginx.conf
ln -s /etc/nginx/conf/mime.types /etc/nginx/mime.types
mkdir /usr/local/nginx/conf/sites-enabled/
ln -s /usr/local/nginx/conf/sites-enabled/ /etc/nginx/sites-enabled

Lo siguiente que vamos a hacer es crear un bloque de configuración para nuestro sitio web. Por facilitar las cosas, voy a asumir que está en PHP y que ya tienes instalado PHP7.4 en el sistema. Esta configuración podría valer perfectamente para poner en funcionamiento un sitio como WordPress. Abrimos el fichero directamente en /etc/nginx/sites-enabled/default.conf y escribimos lo siguiente:

server {

    # [IMPORTANTE] Cambia aquí el dominio por uno que vayas a usar tú
    server_name default.cambiadeso.es;
    listen 80;

    root /var/www/default;

    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

    location / {
	    # First attempt to serve request as file, then
	    # as directory, then fall back to displaying a 404.
	    try_files $uri $uri/ /index.php?$args;
    }

    # pass PHP scripts to FastCGI server
    location ~ [^/]\.php(/|$) {
	    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
	    if (!-f $document_root$fastcgi_script_name) {
		    return 404;
	    }

	    include /usr/local/nginx/conf/fastcgi.conf;

	    # regex to split $uri to $fastcgi_script_name and $fastcgi_path
	    fastcgi_split_path_info ^(.+\.php)(/.+)$;
	    
	    # Check that the PHP script exists before passing it
	    try_files $fastcgi_script_name =404;
	    
	    # Bypass the fact that try_files resets $fastcgi_path_info
	    # see: http://trac.nginx.org/nginx/ticket/321
	    set $path_info $fastcgi_path_info;
	    fastcgi_param PATH_INFO $path_info;

	    fastcgi_param HTTP_PROXY "";
	    fastcgi_index index.php;

	    # With php-fpm (or other unix sockets):
	    fastcgi_pass unix:/run/php/php-fpm.sock;

	    # With php-cgi (or other tcp sockets):
	    #fastcgi_pass 127.0.0.1:9000;
    }

    error_log  /var/log/nginx/default-error.log debug;
    access_log /var/log/nginx/default-access.log combined;

}

Ahora abrimos la configuración general de nginx, la que tenemos en el fichero /etc/nginx/nginx.conf y añadimos dentro de la directiva html { } la siguiente sentencia:

include sites-enabled/*;

Recomiendo hacerlo al final de esa directiva, y debería quedar justo antes del corchete de cierre. De esta forma hacemos que nginx sepa reconocer cuáles son los bloques extra que iremos añadiendo en otros ficheros (los que metamos en la carpeta sites-enabled). Dejaré en este gist una copia de cómo deberían quedar los ficheros de configuración, por si alguno se ha perdido un poco.

Aprovechando que tenemos este fichero de configuración abierto, buscamos la primera línea y la editamos, de tal forma que haremos que nginx corra como el usuario www-data. Este no hará falta que esté dentro de ninguna directiva ni nada.

user  www-data;

Cerramos el archivo, y lo siguiente que haremos será crear rutas para las carpetas de log que hemos configurado, así como dar los permisos adecuados a las mismas para que nginx pueda escribir:

sudo mkdir -p /var/log/nginx/
sudo mkdir -p /var/www/default
sudo chown www-data:www-data /var/log/nginx/
sudo chown www-data:www-data /var/www/default

Es en este momento cuando ya podremos empezar a crear contenido para nuestra web. Para nuestro ejemplo, vamos a ir a la ruta de inicio en /var/www/default y creamos un fichero index.php con este contenido:

<?php echo("Hello world"); ?>

Y podríamos decir que todo esto ya estaría configurado. Para probarlo debemos iniciar el servicio de nginx con este comando y cruzar los dedos para que todo haya salido bien:

sudo systemctl restart nginx

Si este comando no nos «escupe» ningún error, podremos ir a nuestra ruta que hemos configurado en el dominio: http://default.cambiadeso.es/

Es cierto que puede ocurrir lo contrario, que nos aparezca algún error. Si este fuera el caso, podremos analizarlo usando el comando:

sudo journalctl -exu nginx

El resto de la configuración que hagamos será probablemente bastante específica a la aplicación que estés usando. No descarto hacer en algún futuro algún tutorial para explicar más concretamente qué configuración podremos aplicar para ciertos casos, pero, creo que es importante que esta entrada tenga un inicio y un fin, no nos vayamos a alargar indefinidamente…

Instalación y configuración de un certificado HTTPS (SSL) con Certbot

Y es aquí cuando llegamos a la parte definitiva. Si podemos ver y acceder a nuestra web a través del puerto 80, estaremos preparados para instalar certbot en nuestro sistema y configurar el certificado SSL gratuito, gracias a la iniciativa Let’s Encrypt. Como he comentado antes, si accedemos a la página oficial veremos las instrucciones de instalación para Ubuntu 20.04. Por simplicidad, voy a reproducirlas aquí.

El método recomendado es instalar certbot a través de snap. Por lo que lo primero que hacemos es asegurarnos de que tenemos la última versión de snap en nuestro sistema con este comando

sudo snap install core; sudo snap refresh core

Ahora lo instalamos en nuestro sistema y creamos un enlace simbólico para acceder más fácilmente y no andar «toqueteando» el path del sistema:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Finalmente, si hemos hecho todo bien, este comando debería hacer todos los pasos de la certificación, configuración e instalación del certificado SSL totalmente guiado y sin problemas:

sudo certbot --nginx

Ten a mano una dirección de correo electrónico y el dominio que has configurado con tu servidor. Te harán falta. Visita la misma URL que pusimos antes, esta vez con el protocolo «https» en lugar del «http»: https://default.cambiadeso.es/

¡Comprobando que tenemos un certificado SSL funcionando!

Como vemos, sin tocar más la configuración de nginx, Certbot ha sabido instalar el certificado y configurar una redirección del puerto 80 al puerto 443 usado para el protocolo HTTPS.

Espero que os haya sido de interés este tutorial.

Un saludo!

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.