devops

Enable SSL in Jenkins in Docker

Jenkins can be a pretty important piece of infrastructure to a company. This is especially true if you’re using it as an continuous delivery platform to various environments. One of the important aspects of securing Jenkins is to enable SSL/HTTPS support so that the traffic to and from Jenkins is encrypted. In this guide we’re going to use a Jenkins instance that runs inside a Docker container. We’re going to use the official Jenkins Docker image available at DockerHub.

Creating a Keystore

If you haven’t bought a certificate already this would be a good place to start. If you don’t want to buy a certificate you can simply generate a self-signed keystore for testing purposes like this:

$ keytool -genkey -keyalg RSA -alias selfsigned -keystore jenkins_keystore.jks -storepass mypassword -keysize 2048

If you have already bought a certificate things will be a bit more complicated. It’s common that the purchase comes with various files such as the ones below (in this case we have a wildcard certificate but it doesn’t really matter):

File Name Description
STAR_my_site_com.crt The signed certificate (public key)
STAR_my_site_com.key This is the private key
SomeSoftwareCertificateAuthority.crt An intermediate certificate*
TrustSomeExternalCARoot.crt Root certificate

* An intermediate certificate can sign certificates on behalf of the root CA. The root CA signs the intermediate certificate, forming a chain of trust. There may be many intermediate certificates.

So let’s begin by creating an encrypted PKCS#12 file that contains a combination of the signed certificate (public key) and our private key (you’ll be prompted to choose a password, write this down somewhere safe):

$ openssl pkcs12 -export -in .crt -inkey .key -out jenkins.p12

This will generate an encrypted PKCS#12 file called `jenkins.p12`. Next create a Java keystore from this file (and write down the password somewhere safe):

$ keytool -importkeystore -srckeystore jenkins.p12 -srcstoretype PKCS12 -destkeystore jenkins_keystore.jks -deststoretype JKS

Now we have our keystore file but it’s not yet complete. We must also import all of our intermediate certificates and the root CA certificate to our keystore. First assemble all the intermediate certificates and the root certificate into one file, let’s call it `intermediaries.crt`. To do this simply open each intermediary certificate in a text editor and copy its content into the `intermediaries.crt` file (and don’t forget to do include the root certificate as well into this file). Ok now we’re ready to import them to our keystore:

$ keytool -importcert -keystore jenkins_keystore.jks -trustcacerts -alias intermediateCA -file intermediaries.crt

Voila! The keystore should now be complete and ready to be used by Jenkins. You can check that everything looks ok by doing:

$ keytool -list -v -keystore jenkins_keystore.jks | egrep "Alias|Valid"

It should say that the keystore is valid (among other things).

Using the Keystore in Jenkins

We’re going to use the official Jenkins Docker image to start up our Jenkins instance. Luckily the Dockerfile used to generate the image contains an EntryPoint pointing to the jenkins.sh script which allows passing command-line arguments to Jenkins when starting the container.

So we need to somehow expose our `jenkins_keystore.jks` file to Jenkins. One way to do this is to mount a volume from the host filesystem to Jenkins. For example we want Jenkins to store its data in a folder on the host called `/home/ubuntu/johndoe/jenkins` then we should copy the `jenkins_keystore.jks` into this folder. Next let’s start Jenkins:

$ docker run -v /home/ubuntu/johndoe/jenkins:/var/jenkins_home -p 443:8443 jenkins --httpPort=-1 --httpsPort=8443 --httpsKeyStore=/var/jenkins_home/jenkins_keystore.jks --httpsKeyStorePassword=

And that’s it! Jenkins should now start (inside Docker) and expose port 443 on the host which is forwarded to port 8443 in the container. We specify `–httpPort=-1` to disable HTTP traffic to Jenkins altogether and force the use of HTTPS. You should replace the <keystore password> with the password you chose earlier when creating the `jenkins_keystore.jks` file.

Conclusion

Going all the way from the crt files to a Jenkins instance running with SSL support inside Docker requires a bit of work so hopefully this guide can make the process a bit easier.

I must also end this guide by giving well-deserved credit to the people having written the stackoverflow answers (see here and here) I’ve used as an inspiration to this blog.

5 thoughts on “Enable SSL in Jenkins in Docker

  1. am trying to set up a jenkins with ssl over docker

    sudo docker run –name trial -d -p 443:8443 -p 50003:50000 -v /path/to/data/persisted:/var/jenkins_home -httpPort=-1 -httpsPort=8443 -httpsKeyStore=/local/home/jenkins_keystore.jks -httpsKeyStorePassword= –restart unless-stopped

    I container is created!
    but I do not find the jenkins in my browser with https://:443

    1. Container is created, but unable to access jenkins url in my browser. Can someone pls help here

Leave a Reply

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