Una página web o una API siempre requiere comunicaciones seguras reforzadas por el cifrado. Para ello, es necesario un certificado SSL/TLS. Let's Encrypt es una autoridad certificante que emite certificados grautitos. Tiene la particularidad de que esos certificados son válidos sólo por 90 días, por lo que cada 3 meses habrá que renovarlos. La alternativa es adquirir uno pagando una buena suma de dinero a una CA diferente. ¿Gratutito es malo? De ninguna manera, Let's Encrypt genera certificados de la misma calidad que una CA de pago.
Let's Encrypt emite un certificado sólo si nosotros podemos probar que se encuentra bajo nuestro control. Es decir, el certificado está 'nominado' a un dominio. Si el certificado está instalado en el servidor con el domino certificado hará que las comunicaciones sean cifradas, es decir, ningun equipo que se encuentre entre el cliente y el servidor podrá observar los datos que se están transmitiendo (entiéndase esto como contraseñas, archivos sensibles, etc.)
Para generar el certificado, lo primero será instalar el software necesario. Como usuario de Debian, todo este instructivo será basado en él. Lo primero será instalar Certbot que es una herramienta que permite generar un certificado e instalarlo en nuestro sistema. Certbot cuenta con plugins que ayudan a generar un certificado para cada servicio de cloud computing, lo cuál simplifica considerablemente el proceso. En mi caso, todo el ejemplo será configurando un servidor en DigitalOcean.
Certbot se encuentra en los repositorios de Debian. Pero tiene un problema: su versión está desactualizada y algunos de sus plugins no son compatibles, al menos con DigitalOcean. Para ello, deberemos instalar Snap en nuestro equipo remoto. Snap es un gestor de paquetes desarrollado por Canonical.
# Instalo Snap
sudo apt-get install snap
# Instalo Certbot y su plugin para Digita Ocean
sudo snap install --classic certbot
sudo snap install certbot-dns-digitalocean
Lo primero y fundamental para que el plugin de Certbot de DigitalOcean trabaje con el servicio es obtener un token. Para ello, nos logueamos con nuestra cuenta y accedemos a la sección API y damos click en Generate New Token. Completamos el formulario de la siguiente manera:
Una vez que generamos el token, lo copiamos en lugar seguro, ya que lo necesitaremos para que Certbot pueda interactura con DigitalOcean de aquí en adelante. Para esto, vamos a crear un archivo en el directorio 'home' (por ejemplo) con el nombre credentials.ini. Lo llenaremos de la siguiente manera:
dns_digitalocean_token = <aqui va el token>
Es buena práctica mover el archivo a una carpeta distinta (por ejemplo: /etc/letsencrypt) y además cambiar los permisos sólo el usuario propietario pueda leer y escribir:
chmod 600 credentials.ini
Esto no debería influir en la ejecución automática de Certbot, ya que lo hace como usuario root.
Una vez instalados todos los programas necesarios, habiendo obtenido un token de DigitalOcean con permiso para interactuar con los dominios y creado el archivo de configuración para Certbot credentials.ini, pasamos a generar el certificado.
sudo certbot certonly \
--dns-digitalocean \
--dns-digitalocean-credentials ~/credentials.ini \
-d midominio.com \
-d '*.midominio.com'
El parámetro '-d' está indicando para qué dominio configuramos el certificado. En esta configuración hay 2: midominio.com y *.midominio.com . La razón de esto es configurar el certificado para que trabaje sobre el dominio base y también para todos los subdominios, es decir, 'www', 'admin', etc. Para la mayoría de los proyectos, esto bastará y cubrirá todas las necesidades.
El comando mencionado arriba generará los archivos que corresponden al certificado en la siguiente ruta:
/etc/letsencrypt/live/midominio.com/
La ruta contendrá:
Posiblemente, dependiendo de qué servidor se esté empleando, lo único que se requiere son los archivos privkey.pem y fullchain.pem. Esos dos serán los que se deberán instalar en Nginx o Apache o en otro servidor que se esté empleando.
Hasta aqui es la generación del certificado asociado al dominio. Este proceso, si es fallido o se realizan varias pruebas, puede dar lugar a un ban temporal por parte de Let's Encrypt y nos arruinará la jornada de trabajo. La línea de comandos de Certbot está pensada para cubrir todo el dominio. Cosas más específicas requerirán una lectura cuidadosa de la documentación de Certbot.
Como mencioné al principio, Let's Encrypt otorga la validez de 90 días para cada certificado. Para ello, habrá que habilitar la herramienta de renovación automática de Certbot. Para que todo funcione adecuadamente, debemos preservar el archivo credentials.ini en la ruta elegida (el home del usuario, en este ejemplo) y habilitar el servicio certbot.timer. Esto hará que de manera periódica verifique si el certificado es válido y, si no lo es, hará la renovación automáticamente.
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
Al habilitar certbot.timer se creará un archivo de configuración en:
/etc/letsencrypt/renewal/midominio.com.conf
Allí es posible personalizar la configuración, pero sólo la modificaremos si tenemos motivos o razones fundadas para hacerlo.
Para observar si el timer está corriendo correctamente:
systemctl list-timers | grep certbot
Debermos tener algo en la salida indicando que certbot está configurado para correr.
Certbot permite ejecutar scripts antes y después de su ejecución, de modo que es posible crear un script de Bash con 2 o 3 líneas que copien el certificado a una ruta específica (sobreescribiendo el viejo) y reinicien el servidor web (Nginx, Apache, etc.) Este script se colocará en la ruta de post-ejecución de Certbot.
# Para ejecutar antes de la regeneración del certificado
/etc/letsencrypt/renewal-hooks/pre
# Para ejecutar después de la regeneración del certificado
/etc/letsencrypt/renewal-hooks/post
Por ejemplo, colocamos en el directorio 'post' un archivo denominado post-midominio.com.sh con el contenido:
#!/bin/bash
cp /etc/letsencrypt/live/midominio.com/fullchain.pem /ruta-instalacion-certs/ # solo si es necesario
cp /etc/letsencrypt/live/midominio.com/privkey.pem /ruta-instalacion-certs/ # solo si es necesario
systemctl restart nginx # o el comando que reinicie el servicio
No se debe olvidar dar permisos de ejecución:
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/post-midominio.com.sh
Las rutas referenciadas en post-midominio.com.sh deberán ser absolutas para que todo funcione correctamente.
Creado el certificado y configurada su renovación, resta probar la configuración. El siguiente comando hace una 'simulación' para evitar que Let's Encrypt nos penalice.
sudo certbot renew --dry-run
Este es el método con el cual verificamos que todo funciona correctamente. La salida debe ser algo como esto:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/midominio.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for midominio.com and *.midominio.com
Waiting 10 seconds for DNS changes to propagate
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/midominio.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Hook 'post-hook' ran with output:
OK
En este ejemplo se observa una salida exitosa, diciendo que todo funciona correctamente. Con esto doy por finalizadas mis notas sobre cómo generar un certificado en Let's Encrypt con Certbot para un servicio de DigitalOcean. Espero le sea de utilidad para alguien más.