There are several ways to make Jenkins work over HTTPS, here I’m just providing the path we followed using Apache as a proxy that connects to Jenkins internally.
The goal then is to allow users to connect to a URL like https://jenkins.example.com, preventing connections over http (insecure) and direct one to the Jenkins instance (which by default runs on the port 8080), please notice that Jenkins was installed on an Ubuntu distro using the apt command, and also that in order to follow the instructions provided here you need root access to the server or at least a user with sudo permissions.
The first step is to configure the Jenkins service so that it only responds only to Apache local requests, we edited the file
/etc/default/jenkins, adding a variable
And and argument for Jenkins start command:
So, our file looks like this:
After these changes we restarted the Jenkins service and checked that accessing http://jenkins.example.com:8080 is not possible anymore
The second step is related to the Apache configuration:
We created a folder to be used as document root (so that Certbot can create some validation files there) e.g. /var/www/vhosts/jenkins
and a Vhost configuration file, let’s call it jenkins-cert-renewal.conf
<VirtualHost *:80> DocumentRoot "/var/www/vhosts/jenkins/" ServerName jenkins.example.com <Directory "/srv/apps/jenkins/"> AllowOverride None Require all granted </Directory> </VirtualHost>
Once this conf file is created, it’s required to enable the Vhost and reload/restart Apache:
sudo a2ensite jenkins-cert-renewal.conf; sudo service apache2 restart
By going to http://jenkins.example.com you must get a blank page now
OK, so the next step is to generate the SSL certificate for the first time, make sure Certbot is intalled, if not, follow instructions provided here: https://certbot.eff.org/lets-encrypt/ubuntuxenial-apache.html; to generate the certificate we executed the command:
sudo certbot --apache certonly -d jenkins.example.com -w /var/www/vhosts/jenkins
In the output of this command you can find the path to the certificates and with that proceed to create a second vhost configuration file, this will be used most of the time and will have the logic to redirect the connections from HTTP to HTTPS as well as keeping the HTTPS configuration, let’s call this file jenkins.conf
<VirtualHost *:80> DocumentRoot "/var/www/vhosts/jenkins/" ServerName jenkins.example.com # Redirects traffic to https RewriteEngine On RewriteRule ^.*$ https://jenkins.example.com/ [L,R=302] </VirtualHost> <VirtualHost *:443> ServerName jenkins.example.com SSLEngine on SSLCertificateFile /etc/letsencrypt/live/jenkins.example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/jenkins.example.com/privkey.pem ProxyPreserveHost On ProxyRequests Off AllowEncodedSlashes NoDecode ProxyPass / http://127.0.0.1:8080/ nocanon ProxyPassReverse / http://127.0.0.1:8080/ ProxyPassReverse / https://jenkins.example.com/ <Proxy http://127.0.0.1:8080*> Order deny,allow Allow from all </Proxy> </VirtualHost>
Certbox certificates expire after 3 months, since we don’t want to be renewing manually, we decided to create a simple Bash script and configure a cronjob to run it every 3 months
So, the content of the script is something like this:
#!/bin/bash sudo a2dissite jenkins.conf sudo a2ensite jenkins-cert-renewal.conf sudo service apache2 reload # renew command is pretty basic sudo certbot renew sudo a2dissite jenkins-cert-renewal.conf sudo a2ensite jenkins.conf sudo service apache2 reload
Then we edited the crontab for the user, adding a job to be executed on a specific day every 3 months (make sure the Bash script created has execution permissions):
# command to renew Jenkins SSL certificate 00 03 18 3,6,9,12 * /path/to/script/ssl-renew-script
We just configured it to run at 3AM every March, June, September and December 18th.
We will keep an eye out on it in 3 months to see how it goes.