Icono del sitio Un lugar en el mundo…

Pasar de http a https en una web con nginx y wordpress

«Papá» Google dejó claro hace unos meses que quería darle un empujoncito en sus rankings a quienes usaran https en lugar de http. Y allá vamos todos como tiernos corderitos a hacer la migración. ¡Faltaría más! Lo bueno (por verle algo) es que a los que esto no nos va ni nos viene nos sirve para motivarnos a remozar un poquillo el blog y hacer cosas nuevas. Y en eso estamos. Hasta hace bien poquito si queríamos usar https en una web y no queríamos gastarnos dinero en certificados teníamos las opciones que nos ofrecían StartSSL o CaCert. Pero desde finales del año pasado contamos con Let’s Encrypt: un proyecto patrocinado, entre otros, por la EFF y Mozilla del que todo el mundo habla maravillas. Había que probarlo, estaba claro.

Con Lets Encrypt no hacemos la instalación de un certificado a la antigua usanza, sino que instalamos en nuestro servidor un programa que se encarga de realizar la instalación y posterior renovación periódica de forma automática. Además, si usamos Apache se encarga de realizar la configuración necesaria en nuestro servidor de forma automática. Está previsto que en el futuro también existirá un script para nginx pero de momento esta posibilidad no existe aún.

Nuestro punto de partida es un servidor web que funciona en Debian 8.4 usando nginx como servidor web y wordpress como CMS. El fichero de definición para nuestro virtualhost es de lo mas sencillito que se despacha:

server {
        listen   80 default_server;
        root /var/www/myblog;
        index index.php;
        server_name www.myblog.com;
        access_log /var/log/nginx/myblog-access.log;
        error_log /var/log/nginx/myblog-error.log;
        location / {
                try_files $uri $uri/ /index.php?q=$uri&$args;
        }
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
              root /usr/share/nginx/www;
        }
        location ~ \.php$ {
		include snippets/fastcgi-php.conf;
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $request_filename;
		}
}

Lo primero que necesitamos es instalar el cliente de Lets Encrypt. Para ello ejecutamos lo siguiente (con privilegios de root):

apt-get install -y git
git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt
./letsencrypt-auto

El código anterior instala el paquete git y copia el código necesario al directorio /opt/letsencrypt. Luego nos posiciona en dicho directorio y ejecuta el script que realizará la instalación de dependencias necesarias (augeas, gcc y python), instalará los certificados raices en nuestro servidor y creará el directorio /etc/letsencrypt.

Lo siguiente que necesitamos es crear un directorio temporal para letsencrypt accesible a través de nuestro servidor web. En la documentación nos recomiendan hacerlo de la siguiente forma:

cd /var/www
mkdir letsencrypt
chown www-data:www-data letsencrypt

En tercer lugar crearemos un fichero de configuración con los datos del certificado que queremos crear. Dicho fichero debe de estar en el directorio /etc/letsencrypt/configs/ y debería de llamarse como el dominio para el que queremos crear el certificado pero añadiendo la extensión .conf. En nuestro caso, por tanto, el fichero se llamará www.myblog.com.conf y tendrá el siguiente contenido:

domains = www.myblog.com
rsa-key-size = 2048 # Si lo deseas puedes usar claves de 4096
server = https://acme-v01.api.letsencrypt.org/directory
email = josemaria@myblog.com # Recibirás recordatorios de renovación en esta dirección
text = True
authenticator = webroot
webroot-path = /var/www/letsencrypt/

Cuarto paso: tenemos que hacer accesible el directorio letsencrypt que creamos anteriormente en /var/www a nuestro servidor web. Para ello añadimos las siguientes líneas dentro del bloque server de la definición de nuestro virtualhost:

location /.well-known/acme-challenge {
        root /var/www/letsencrypt;
    }

Para que el cambio anterior tenga efecto necesitamos hacer un reload del servicio de nginx:

systemctl reload nginx
NOTA: Para asegurarte de que no has metido la pata al editar los ficheros de configuración de nginx puedes hacer un test antes del reload:
nginx -t

Ahora ya vamos a solicitar el certificado a Let’s Encrypt. Para ello ejecutamos lo siguiente:

cd /opt/letsencrypt
./letsencrypt-auto --config /etc/letsencrypt/configs/www.myblog.com.conf certonly

Si todo ha salido bien se descargará el certificado a nuestra máquina y obtendremos una salida similar a esta:

Checking for new version...
Requesting root privileges to run letsencrypt...
   /root/.local/share/letsencrypt/bin/letsencrypt --config /etc/letsencrypt/configs/www.myblog.com.conf certonly

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.myblog.com/fullchain.pem. Your
   cert will expire on 2016-07-10. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Fíjate que el certificado descargado es válido sólo durante seis meses. Acuerdate de esto que luego veremos como renovarlo. Bien. Pues ya nos queda sólo ún último paso para terminar: tenemos que modificar de nuevo el fichero de definición del virtualhost de nuestro servidor web para que atienda las peticiones https, sepa donde está el certificado que necesita para ello y redireccione todas las peticiones que se hagan a través del puerto 80 al nuevo servicio que reside en el 443. El nuevo fichero de definición de virtualhost quedaría como sigue:

server {
        listen   80;
        server_name www.myblog.com;
        return 301 https://www.myblog.com/$request_uri;
}

server {
        listen   443 ssl default_server;
        root /var/www/myblog;
        index index.php;
        server_name www.myblog.com;
        location /.well-known/acme-challenge {
        	root /var/www/letsencrypt;
    	}
        ssl_certificate /etc/letsencrypt/live/www.myblog.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.myblog.com/privkey.pem;

        access_log /var/log/nginx/myblog-access.log;
        error_log /var/log/nginx/myblog-error.log;
        location / {
                try_files $uri $uri/ /index.php?q=$uri&$args;
        }
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
              root /usr/share/nginx/www;
        }
        location ~ \.php$ {
		include snippets/fastcgi-php.conf;
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $request_filename;
		}
}
NOTA: Si quieres ver que líneas hemos añadido basta con que compares con las líneas que hemos dejado un poco más arriba 😉

Volvemos a hacer un reload de la configuración de nginx y nuestro servidor ya debería de funcionar correctamente con https y, es más, redirigir todas las peticiones de enlaces a través de http que hubiera en cualquier sitio de internet al nuevo servicio https. Puedes comprobar las características del nuevo certificado que acabas de instalar a traves de los servicios de SSLABS

¿Hemos dicho que hemos terminado? Bueno, en realidad no… Faltarían un par de detallitos. El primero, acordarte de que el certificado caduca a los seis meses. Para renovarlo basta con ejecutar de nuevo lo siguiente:

cd /opt/letsencrypt
./letsencrypt-auto --config /etc/letsencrypt/configs/www.myblog.com.conf certonly

Pero los chicos que llevan nginx nos han dejado un útil script que podemos crear y programar desde crontab:

#!/bin/sh

cd /opt/letsencrypt/
./letsencrypt-auto --config /etc/letsencrypt/configs/my-domain.conf certonly
if [ $? -ne 0 ]
 then
        ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
        echo -e "The Let's Encrypt cert has not been renewed! \n \n" \
                 $ERRORLOG
 else
        nginx -s reload
fi
exit 0

Para que funcione debes de crear un directorio llamado letsencrypt colgando de /var/log. Allí se dejarán los mensajes de error en caso de que la renovación no pueda realizarse correctamente. Ah, y no apures los seis meses de vida del certificado hasta el final. Por si acaso… Lets Encrypt nos deja renovar nuestros certificados hasta 5 veces al día, así que si lo programas para que se ejecute cada cuatro meses, por ejemplo, no va a morirse nadie 😉

En segundo lugar, si nuestra web lleva funcionando desde hace tiempo con http, google nos tendrá indexados en multitud de sitios y si no queremos perder el ranking de esos enlaces debemos de informarle del cambio. Existe una guía editada por la propia Google donde nos dicen paso a paso como hacer esto.

En tercer y, ahora si, último lugar, aunque nuestro servicio redirige todas las peticiones http a https, estas redirecciones podrían penalizar un poco el rendimiento de nuestra web. Debemos de tratar de ir eliminando los antiguos enlaces que estén en nuestra mano y para ello deberíamos de empezar por la propia configuración de wordpress cambiando la dirección del sitio en la entrada de Ajustes Generales.

Si necesitas alguna otra cosa no cubierta aquí tienes disponible un completito manual aquí

ACTUALIZACIÓN: La mejor forma ahora de instalar los certificados de Let’s Encrypt es usar certbot. Además hay otros cambios sobre lo aquí escrito: un paquete en Debian backports llamado certbot, la caducidad de los certificados se ha bajado a tres meses y alguna cosilla mas… Así que usa este artículo como base si quieres pero no te lo creas todo a pies juntillas que se ha quedado viejo muy pronto!

Salir de la versión móvil