Certificación de dominio con Let’s Encrypt, NGINX y Docker Compose
Tags: espanol, docker, certificacion, devops
Published: 2020-09-03 20:24:23

#Algunas definiciones

###¿Qué es un Certificado SSL?
Un certificado SSL es un tipo de certificado digital que proporciona autenticación para un sitio web y habilita una conexión encriptada. Estos certificados comunican al cliente que el host del servicio web demostró la propiedad del dominio a la autoridad de certificación en el momento de la emisión del certificado.

SSL (Secure Socket Layer) es un protocolo de seguridad que encripta el envío y recepción de información entre el servidor y el cliente. Este crea una capa de conexión segura entre el navegador y el servidor del sitio web al que el usuario se conecta. Cualquier información que pase a través de esta capa está encriptada y es descifrada cuando llega a su destino.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/srxylkbe9rmv844xi4c5.jpg)


###Let’s Encrypt
[Let's Encrypt](https://letsencrypt.org/es/) es una autoridad de certificación (también conocidas como AC o CA por sus siglas en inglés) gratuita, automatizada, y abierta, que existe para el beneficio del público. Es un servicio provisto por el [Internet Security Research Group o ISRG](https://www.abetterinternet.org/).

###Certbot
[Cerbot](https://certbot.eff.org/) es un cliente extensible con todas las funciones para Let’s Encrypt CA, o cualquier otra autoridad de certificación que se comunique a través del protocolo [ACME](https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md), capaz de automatizar las tareas de obtener certificados y configurar servidores web para usarlos.

###Nginx
[NGINX](https://www.nginx.com/) es un servidor web/proxy inverso ligero de alto rendimiento y un proxy para protocolos de correo electrónico.​​


#Cómo certificar

###Pre-Requisitos
- Dominio registrado
- [Docker Compose instalado](https://docs.docker.com/compose/install/) 

Compose es una herramienta para definir y ejecutar aplicaciones Docker de varios contenedores. Se usa un archivo YAML para configurar los servicios de tu aplicación y luego, con un solo comando, crea e inicia todos los servicios desde tu configuración. 


###Pasos

**1.** Lo primero que haremos es **crear los directorios** donde Certbot alojará la configuración de los certificados y donde pondremos la configuración de nuestro servidor Nginx:


```data/nginx
data/certbot/www/.well-known
```


Es muy importante que esté creado el directorio .well-known ya que en el mismo se guardará el challenge que Let’s encrypt utiliza para corroborar que tenemos control sobre el dominio. Es útil conocer los diferentes tipos de *challenges* que existen para elegir el más adecuado según el caso, es decir, el tipo de validación que Let’s Encrypt utiliza para verificar el control sobre el dominio.


**2.** Luego, **crearemos el archivo de configuración** de Nginx dentro del directorio recién creado, con el siguiente contenido:


```
server {
  listen 80;
  server_name NOMBRE_DEL_HOST;
  location / {
    return 301 https:// NOMBRE_DEL_HOST;
  }
  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }
}
server {
  listen 443 ssl;
  server_name NOMBRE_DEL_HOST;
  location / {
    proxy_pass http://NOMBRE_DEL_HOST;
  }
  ssl_certificate /etc/letsencrypt/live/NOMBRE_DEL_HOST/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/NOMBRE_DEL_HOST/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
```


El archivo de configuración deberá estar en dicho directorio: 
 `data/nginx/web.conf`



**3.** Una vez listo, pasaremos a **crear el Compose** que vamos a utilizar:


```
version: "3"
services:
  nginx:
     image: nginx:1.15-alpine
     ports:
       - "80:80"
       - "443:443"
     volumes:
       - ./data/nginx:/etc/nginx/conf.d
       - ./data/certbot/conf:/etc/letsencrypt
       - ./data/certbot/www:/var/www/certbot
     command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
  
  certbot:
     image: certbot/certbot
     volumes:
       - ./data/certbot/conf:/etc/letsencrypt
       - ./data/certbot/www:/var/www/certbot
     entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
```



Creado el Compose, no lo ejecutaremos, porque fallará la creación del Nginx debido a que no se encuentra creado el certificado que declaramos anteriormente en el archivo de configuración de Nginx.

----------------------

Vamos a explicar un poco lo que hicimos en ese Compose: cruzamos datos entre Certbot y Nginx mediante los directorios creados anteriormente. Esto se debe a que necesitamos que el contenedor Nginx pueda acceder a los certificados y el *challenge* creados por el contenedor de Certbot.

En el contenedor de Certbot agregamos un *entrypoint* el cual verifica cada 12 horas si se puede renovar el certificado.

Por su parte, en el contenedor de Nginx agregamos un command el cual permite iniciar Nginx en primer plano y recarga su configuración y certificados cada 6 horas en segundo plano, asegurando que siempre tenga los nuevos certificados que se generen.

--------------------

**4.** Finalmente, debemos **crear el siguiente script** cambiando los valores de *domains* y *email*:


{% gist https://gist.github.com/mapets89/0af960bedb9a82c4f5a71c5fe8a214af %}



El script debe estar en el mismo directorio donde se encuentra el docker-compose y el directorio data que creamos anteriormente. Vamos a darle permiso de ejecución al script y luego ejecutarlo:


```
chmod +x init-letsencrypt.sh 
sudo ./init-letsencrypt.sh
```

------------------

Como dijimos anteriormente, si queremos utilizar el comando `docker-compose up`no funcionará porque no se encuentran creados los certificados que seteamos en la configuración de Nginx. Ahí es donde entra en juego el script. Este script lo que hace es crear certificados *dummies* utilizando el contenedor de Certbot, para poder inicializar el contenedor de Nginx sin errores. Luego de que el contenedor esté inicializado, elimina los certificados *dummies*, le pide a Let’sEncrypt certificados para nuestro dominio y reinicia la configuración del contenedor de Nginx para recargar los certificados válidos. De este modo, no va a ser necesario utilizar dicho comando.

Si al ejecutar el script falla la creación de los certificados, es **muy importante** que lean y resuelvan el inconveniente antes de volver a ejecutarlo, ya que Let’sEncrypt bloqueará el dominio si hacen más de 5 intentos fallidos.

------------------

Por último, cabe aclarar que en este artículo tomamos información de varias fuentes, recopilando aquellas más completas para que este paso a paso resulte más fácil y práctico. Espero que les sea útil y cualquier consulta no duden en dejarla en los comentarios. 

Para más info sobre este tema recomendamos nuestra nota en Medium:
 

{% medium https://medium.com/eudaimonia-ar/certificar-dominios-con-letsencrypt-y-nginx-con-docker-compose-a6a948f47f2f %}


¡Muchos éxitos!