Configurar certificados SSL/TLS gratis en Nginx (Let’s Encrypt)

A día de hoy, hay pocos motivos para no configurar un sitio web con HTTPS. El único que se me ocurre es que se encuentre en un servicio de alojamiento compartido y la opción no esté disponible. En ese caso, quizás la solución no pasa por no habilitar protocolo seguro en nuestro sitio web, sino por migrar a otro servidor de alojamiento. Los VPS, por ejemplo, están a precio de derribo.

Gracias a Let’s encrypt, tenemos la posibilidad de disponer gratuitamente de certificados SSL y además con una configuración extremadamente sencilla, tanto para la instalación como para la renovación (cada tres meses). Para ello, vamos a utilizar la herramienta certbot.

Certbot es una herramienta en Python que permite automatizar el despliegue de certificados SSL/TLS de Let’s Encrypt, tanto para la instalación (alta del certificado, validación, configuración de NGINX y redirección HTTP → HTTPS redirects) como la renovación.

Instalación de Certbot

La instalación es sencilla, simplemente instalad el paquete certbot del respositorio de vuestro sistema, en el caso de RHEL o CentOS:

# yum install certbot

Si queréis automatizar también la configuración del servidor web (Nginx, Apache…) instalad también el paquete correspondiente:

Nginx:

yum install python2-certbot-nginx

Apache:

yum install python2-certbot-apache

Crear y configurar certificado SSL/TLS

Una vez instalado certbot, dar de alta el certificado SSL/TLS y configurarlo sólo requiere un comando:

# certbot --nginx -d foo.com

Los parámetros básicos son especificar el tipo de servidor web en el que lo vamos a instalar --nginx y el common name (CN) del certificado con -d. Recordad que el CN es el hostname asociado al certificado.

El proceso de instalación sería algo similar a esto, en el caso de que sea la primera vez que lo ejecutáis, os pedirá una dirección de correo electrónico y aceptar los términos de licencia de Let’s Encrypt:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for foo.com
Waiting for verification...
Cleaning up challenges
Resetting dropped connection: acme-v02.api.letsencrypt.org
Deploying Certificate to VirtualHost /etc/nginx/conf.d/foo.com.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/foo.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://foo.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=foo.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/foo.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/foo.com/privkey.pem
   Your cert will expire on 2019-08-03. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

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

Y ya está, el certificado se encuentra instalado y es completamente funcional. Si os fijáis, certbot automáticamente ha dado de alta el certificado, ejecutado todas las validaciones necesarias y reconfigurado Nginx para que funcione. También se ha forzado la redirección HTTP a HTTPS.

Si el sitio estaba configurado sólo para HTTP en Nginx, veréis automáticamente toda la configuración HTTPS configurada en el archivo, ejemplo:

[...]
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/foo.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/foo.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
[...]

server {
    if ($host = foo.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name foo.com
    return 404; # managed by Certbot


}


  • Logs de Let’s Encrypt: /var/log/letsencrypt
  • Ruta de almacén de certificados: /etc/letsencrypt/live/
  • Ruta de configuración y parametrización de SSL: /etc/letsencrypt/ssl-dhparams.pem y /etc/letsencrypt/options-ssl-nginx.conf

Renovación automática de certificados

Los certificados de Let’s Encrypt tienen una validez máxima de tres meses, así que es necesario automatizar la renovación. Con Certbot, es tan sencillo como establecer un cron que diariamente verifique si es necesario renovarlos:

0 3 * * * certbot --nginx renew >/dev/null 2>&1

Y ya está, automáticamente verificará si hay que renovar cada uno de los certificados instalados en nuestro NGINX. En los logs (/var/log/letsencrypt) podréis encontrar un registro de las acciones realizadas y de si ha sido necesaria o no la renovación, ejemplo:

2019-05-02 03:00:02,743:DEBUG:certbot.main:certbot version: 0.31.0
2019-05-02 03:00:02,744:DEBUG:certbot.main:Arguments: ['--nginx']
2019-05-02 03:00:02,744:DEBUG:certbot.main:Discovered plugins: PluginsRegistry(PluginEntryPoint#manual,PluginEntryPoint#nginx,PluginEntryPoint#null,PluginEntryPoint#standalone,PluginEntryPoint#webroot)
2019-05-02 03:00:02,778:DEBUG:certbot.log:Root logging level set at 20
2019-05-02 03:00:02,778:INFO:certbot.log:Saving debug log to /var/log/letsencrypt/letsencrypt.log
2019-05-02 03:00:02,797:DEBUG:certbot.plugins.selection:Requested authenticator nginx and installer nginx
2019-05-02 03:00:02,797:DEBUG:certbot.cli:Var authenticator=nginx (set by user).
2019-05-02 03:00:02,797:DEBUG:certbot.cli:Var installer=nginx (set by user).
2019-05-02 03:00:02,809:INFO:certbot.renewal:Cert not yet due for renewal
2019-05-02 03:00:02,810:DEBUG:certbot.plugins.selection:Requested authenticator nginx and installer nginx
2019-05-02 03:00:02,812:DEBUG:certbot.plugins.selection:Selecting plugin: * nginx
Description: Nginx Web Server plugin
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: nginx = certbot_nginx.configurator:NginxConfigurator
Initialized: 
2019-05-02 03:00:02,814:DEBUG:certbot.cli:Var authenticator=nginx (set by user).
2019-05-02 03:00:02,814:DEBUG:certbot.cli:Var installer=nginx (set by user).
2019-05-02 03:00:02,834:INFO:certbot.renewal:Cert not yet due for renewal
2019-05-02 03:00:02,835:DEBUG:certbot.plugins.selection:Requested authenticator nginx and installer nginx
2019-05-02 03:00:02,837:DEBUG:certbot.plugins.selection:Selecting plugin: * nginx
Description: Nginx Web Server plugin
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: nginx = certbot_nginx.configurator:NginxConfigurator
Initialized: 
2019-05-02 03:00:02,838:DEBUG:certbot.renewal:no renewal failures

Como podéis observar: Cert not yet due for renewal y no renewal failures indican que ningún certificado instalado requiere renovación y que no ha habido errores durante el proceso.