What we want to do
The facts
- Https (ssl) is a requirement in many sites.
- Let's Encrypt offers free ssl certificates
- We use Jenkins for admin tasks
- We use an Nginx with Docker to publish our sites.
What we want to achieve
We want to add ssl certificates to a site inside our Nginx (that is in a Docker container), and automatize its renewals from Jenkins.
Let's do it
Create Certificates
We have used Let's Encrypt certificates and certbot to create them.
First we have installed certbot in the main machine (no Docker). In our case a Ubuntu, so:
sudo apt-get install letsencrypt
In order to create the certificates the software needs to publish a file in the webserver (in example.com/.well-known/acme-challenge/). We have used the following volume (in docker-compose.yml file)
- ./letsencrypt/well-known:/www/letsencrypt
And published the folder (in Nginx config). Replace example.com for your site (ex: trito.dev):
location '/.well-known/acme-challenge' {
default_type "text/plain";
root /www/letsencrypt/example.com/;
allow all;
}
Now we are ready to create the certificates (Replace example.com and user):
sudo mkdir /home/user/docker/nginx/letsencrypt/well-known/example.com
sudo letsencrypt certonly --webroot -w /home/user/docker/nginx/letsencrypt/well-known/example.com -d example.com
Certificates created
Move to https
First we need to create a volume with the certificates
- /etc/letsencrypt/:/etc/letsencrypt/
Now we change nginx configuration to redirect to https. And create the new server for ssl. You will have something like:
server {
listen 80;
server_name example.com;
location / {
return 301 https://$host$request_uri;
}
location '/.well-known/acme-challenge' {
default_type "text/plain";
root /www/letsencrypt/example.com/;
allow all;
}
}
server {
listen 443 ssl;
server_name example.com;
# Configure file root, proxy_pass or whatever you use here
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
keepalive_timeout 70;
}
Moreover, we need to add 443 port from nging-docker to be linked with host 443 port (in Nginx docker-compose.yml):
ports:
- 80:80
- 443:443
Done. We acces now to our website using https.
Renew certificates
To test the renew process. Using the dry-run option we will only perform a test, not update the certificates.
sudo letsencrypt renew --dry-run --agree-tos --email youremail@example.com
Renew from Jenkins
We want to create a jenkins task that will execute the renewal as a cron.
We first need to enable the letsencrypt command to be executed as sudo without password. We need to execute
sudo visudo
and add the following line (trito is the user)
trito ALL = NOPASSWD: /usr/bin/letsencrypt
We create a renew_certificates.sh with the following:
sudo letsencrypt renew --agree-tos --email youremail@example.com
And we create a jenkins task that executes the script each day.
That's all folks!