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 estás buscando cómo instalar un certificado SSL de Let’s Encrypt en Debian 7 (Wheezy) con Apache 2.2 puedes encontrar un tutorial en este enlace.
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 jessie-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
Si tenemos distintas rutas en el servidor para los subdominios hay que indicarlo adecuadamente:
certbot certonly --webroot -w /var/www/midominio.com/magento/ -d www.midominio.com -d midominio.com -w /var/www/midominio.com/wordpress/ -d blog.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"