Instalar un certificado SSL de Let’s Encrypt en Debian 8 (Jessie) con Apache 2.4

En este post voy a explicar cómo instalar un certificado SSL de Let’s Encrypt en Debian 8 (Jessie) con Apache 2.4.

Si dispongo de acceso por shell y permisos de administración, en la web de Let’s Encrypt recomiendan hacerlo a través del cliente Certbot. En esta web selecciono el servidor web y el sistema operativo donde voy a instalar el certificado y me dirige a una guía de instalación.

A continuación aparece una guía paso a paso de cómo llevar a cabo la instalación.

En este tutorial lo voy a hacer de una forma más “artesana”, para ir viendo los pasos seguidos.

Lo primero que hago es añadir el repositorio de los backports, donde se encuentra el software de Let’s Encrypt para Debian 8 y Apache 2

sudo echo 'deb http://ftp.debian.org/debian wheezy-backports main' >>  /etc/apt/sources.list.d/backports.list

A continuación actualizo los paquetes

sudo apt-get update

Instalo el paquete desde backports

sudo apt-get install python-certbot-apache -t jessie-backports

Ejecuto el comando de creación de los certificados

certbot certonly --webroot -w /var/www/midominio.com/www/ -d www.midominio.com -d midominio.com

donde:

  • /var/www/midominio.com/www/ es la ruta base del sitio web para el que quiero asegurar la comunicación.
  • www.midominio.com es uno de los dominios para los que quiero crear el certificado.
  • midominio.com es otro de los dominios para los que quiero crear el certificado. En este caso es el anterior sin las “www”, situación habitual en la administración de sistemas.

El mismo certificado vale para ambos dominios. Let’s Encrypt tiene un límite de 100 dominios.

Aparece una pantalla azul en la que el programa ejecuta una serie de comandos

Si todo funciona correctamente, el programa muestra el siguiente texto por consola

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
 /etc/letsencrypt/live/midominio.com/fullchain.pem. Your cert
 will expire on 2017-04-20. To obtain a new or tweaked version of
 this certificate in the future, simply run certbot again. 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

Es importante tener claro que este modo de generación del certificado (plugin webroot) trabaja creando un archivo temporal para cada uno de los dominios solicitados en la ruta

${directorio-raiz-del-dominio}/.well-known/acme-challenge

A continuación el servidor de validación de Let’s Encrypt realiza peticiones HTTP para validar los DNS para cada uno de los dominios solicitados mediante el comando “certbot”.

Hay que tener cuidado si en la configuración del host virtual están denegados los archivos o directorios que empiezan por punto “.”, ya que no se podrá acceder desde fuera a este directorio. También es importante comprobar que el firewall permita la comunicación con los servidores de Let’s Encrypt.

Si consulto el directorio /etc/letsencrypt/live/midominio.com/

ls /etc/letsencrypt/live/midominio.com/

veo que certbot ha creado 4 archivos:

  • cert.pem: el certificado de los dominios.
  • chain.pem: el certificado de la cadena de Let’s Encrypt.
  • fullchain.pem: los dos certificados anteriores combinados.
  • privkey.pem: la clave privada de mi certificado.

Realmente son enlaces simbólicos a 4 archivos existentes en el directorio /etc/letsencrypt/archive/midominio.com/ . Si lo consulto

ls /etc/letsencrypt/archive/midominio.com/

veo que los cuatro archivos

  • cert1.pem
  • chain1.pem
  • fullchain1.pem
  • privkey1.pem

son los mismos que los nombres de los enlaces simbólicos pero su nombre acaba en un número. Cada vez que renueve el certificado (tienen una duración de 3 meses) se crearán 4 archivos nuevos, con este número incrementado en una unidad, y los 4 enlaces simbólicos apuntarán a estos nuevos archivos.

Tras generar el certificado tengo que configurar el host virtual de Apache. Para ello voy a /etc/apache2/sites-available/ (en este ejemplo supongo que el host virtual ya ha sido habilitado mediante el comando “a2ensite” y que tiene su correspondiente enlace simbólico en /etc/apache2/sites-enabled/)

cd /etc/apache2/sites-available/

y edito el host virtual de mi dominio o dominios:

vi midominio.com.conf

Suponiendo que tengo un <VirtualHost *:80> para atender al puerto 80 (HTTP), duplico esta entrada y en la segunda entrada cambio el 80 por el 443, que es el puerto por defecto de HTTPS.

<VirtualHost *:443>

# Aquí estará el contenido del virtualhost, igual al existente: DocumentRoot, ServerName, elementos de error,...

</VirtualHost>

Además, dentro de este nuevo VirtualHost tengo que indicarle dónde están los certificados. Para ello añado la siguiente información

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/midominio.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/midominio.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/midominio.com/chain.pem

Con esto ya tendría la configuración realizada. A mayores voy a redireccionar todo el tráfico HTTP hacia el HTTPS. Para ello introduzco la siguiente línea dentro del <VirtualHost *:80>

Redirect permanent / https://midominio.com/

Un ejemplo de host virtual, al que le falta toda la parte específica del lenguaje usado en la aplicación web (FastCgi,…) puede ser el siguiente

<VirtualHost *:80>
      ServerAdmin webmaster@midominio.com
       DocumentRoot /home/midominio/wwww
       ServerName midominio.com
       ServerAlias www.midominio.com
       Redirect permanent / https://midominio.com/
       <Directory />
             Options -Indexes +FollowSymLinks +MultiViews
             AllowOverride All
             Require all granted
       </Directory>
       ErrorLog ${APACHE_LOG_DIR}/midominio-error.log
       LogLevel warn
       CustomLog ${APACHE_LOG_DIR}/midominio-access.log combined
</VirtualHost>
<VirtualHost *:443>
       ServerAdmin webmaster@midominio.com
       DocumentRoot /home/midominio/wwww
       ServerName midominio.com
       ServerAlias www.midominio.com
       <Directory />
             Options -Indexes +FollowSymLinks +MultiViews
             AllowOverride All
             Require all granted
       </Directory>
       SSLEngine on
       SSLCertificateFile /etc/letsencrypt/live/www.midominio.com/cert.pem
       SSLCertificateKeyFile /etc/letsencrypt/live/www.midominio.com/privkey.pem
       SSLCertificateChainFile /etc/letsencrypt/live/www.midominio.com/chain.pem
       ErrorLog ${APACHE_LOG_DIR}/midominio-error.log
       LogLevel warn
       CustomLog ${APACHE_LOG_DIR}/midominio-access.log combined
</VirtualHost>

Ejecuto

apache2ctl -t

para comprobar que la sintaxis de los host virtuales es correcta. Si aparece

Syntax OK

Puedo reinciar Apache y ya tendré listo mi certificado. Para ello ejecuto

service apache2 restart

Y tras recargar mi sitio web en el navegador puedo ver que la comunicación está asegurada

Solo me falta por configurar la renovación automática del certificado, ya que su validez es de 3 meses. Para ello lo que hago es introducir en el cron una tarea que trate de renovar el certificado dos veces por día.

A priori parece que con hacerlo mensualmente llegaría, pero la recomendación de Let’s Encrypt es la siguiente:

Note:

if you’re setting up a cron or systemd job, we recommend running it twice per day (it won’t do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let’s Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.

Ejecuto el siguiente comando para ver cómo se realiza el proceso de renovación

certbot renew --post-hook "service apache2 restart"

Su salida es

Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/midominio.com.conf
-------------------------------------------------------------------------------
Cert not yet due for renewal

The following certs are not due for renewal yet:
 /etc/letsencrypt/live/midominio.com/fullchain.pem (skipped)
No renewals were attempted.
No renewals attempted, so not running post-hook

El programa trató de renovar el certificado, pero como no está próximo a caducar no hizo nada (tampoco se reinicia Apache).

Busco la ubicación del programa certbot, ya que en el cron usaré rutas absolutas

which certbot

Su ubicación es

/usr/bin/certbot

Edito el cron

sudo crontab -e

Y añado la siguiente línea, que se ejecuta a las 2:15 y a las 14:15 horas (2 veces al día) y será la encargada de renovar los certificados existentes en la máquina.

15 2,14 * * * /usr/bin/certbot renew --quiet --post-hook "service apache2 restart"

Leave a Reply

Your email address will not be published. Required fields are marked *