HTTPS for Tomcat 7 with Let's Encrypt
February 13, 2016
In my last blog post I described the benefits of HTTPS and how to set up your Synology DiskStation to use HTTPS with a trusted certificate from Let’s Encrypt. However I am also running Tomcat 7 on my DiskStation, which is also accessible from the internet. Needless to say, I want to secure access to Tomcat, too. If you run Tomcat yourself and want to set it up for HTTPS, this is for you.
Update for DSM 6 Users!
In case you own a DSM 6 powered Diskstation, you do not want to follow the instructions described in this post. I found a much easier and automatable approach by using DSM 6 integrated Let’s Encrypt support and the new reverse proxy feature, which I described in a recent post over here.
Prerequisites
In case you want to follow along, make sure you have Java and Tomcat already running. I won’t cover how to set up Tomcat in this post. However, there is no need to worry! Especially if you are a DiskStation user, because both Java and Tomcat 7 are available in Synology Package Center for your one-click-install pleasure. Check this guide in case you need more advice on how to get Tomcat 7 running. You will also need openSSL, but I found it was already installed on my DiskStation. Furthermore I assume you already have a certificate from Let’s Encrypt. If you do not, check out my last post to learn how to get that certificate and set up your DiskStation to use it for HTTPS. Once you got the certificate issued with the official Let’s Encrypt client, you will find that the client created a directory for you: /etc/letsencrypt
. In this directory you will find the path live/yourDomain
which contains symbolic links to the latest version of their corresponding file in /etc/letsencrypt/archive/yourDomain
. Follow the links fullchain.pem and privkey.pem to grab their corresponding files. In a terminal you can do this like so:
`$ cp -L /etc/letsencrypt/live/yourDomain/fullchain.pem /remember/this/path/``$ cp -L /etc/letsencrypt/live/yourDomain/privkey.pem /remember/this/path/`
Now that you have these two files, we are ready to go!
What is acutally required for HTTPS?
To enable Tomcat to serve requests through HTTPS we need to provide it with a certificate and the entire chain required to validate that certificate. This way when accessing Tomcat with a browser, the browser will be able to validate the provided certificate. After making sure the certificate is valid, the browser checks if it is issued to the server the client actually called and if this is the case, the connection is trusted. But for the connection to also be private, Tomcat needs the private key corresponding to the certificate to decrypt the client generated random key. This client generated random key is encrypted with the server’s public key (which is part of the certificate) by the client, so it can be safely transmitted to your server. Your server decrypts the symmetric key with the private key and now both parties have the symmetric key that is actually used to encrypt the communication between them. If you want to know more about HTTPS, check out Robert Heaton’s post. Anyway, now you know why we grabbed fullchain.pem and privkey.pem earlier. However we can’t tell Tomcat to just use the PEM files we got from the Let’s Encrypt client. So what we will do is to put the full certificate chain and the private key all together inside one Java Key Store (JKS).
Create a keystore for Tomcat
Basically there are only two steps required to get our fullchain.pem and privkey.pem inside a JKS. First we bundle both our fullchain and the private key in a PKCS12 keystore. We do this, because apparently Java’s keytool (which we use to create our JKS) is not able to import pre-existing keys and certificates into a JKS, as described here. So open up your terminal and do something like this:
`$ openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out fullchain_and_key.p12 -name tomcat`
You will be asked to provide a password (called yourPKCS12pass in the following). Do not forget it. You will need it for our second step. Now that we have our PKCS12 keystore, we can use Java’s keytool to generate a JKS from our PKCS12 file like so:
`$ keytool -importkeystore -deststorepass _yourJKSpass_ -destkeypass _yourKeyPass_ -destkeystore MyDSKeyStore.jks -srckeystore fullchain_and_key.p12 -srcstoretype PKCS12 -srcstorepass _yourPKCS12pass_ -alias tomcat`
This will give you a file called MyDSKeyStore.jks. Now you are ready to configure Tomcat for HTTPS.
Configure Tomcat for HTTPS
Now that we have the required JKS, we configure Tomcat’s SSL Connector to use the generated JKS the way it is documented here and here. For this we need to edit Tomcat’s server.xml file found in $CATALINA_BASE/conf/
. For DiskStations users this should look something like this: /volume1/@appstore/Tomcat7/src/conf/
Open that file and find the block starting with <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
. Uncomment that block and add your details to the connector. The result should look something like this:
Note the sections in bold. Make sure you point to your JKS file and that the other values correspond to the values you used when creating the JKS file. The careful reader might have noticed that I added URIEncoding="UTF-8"
to the connector. This is for GitBlit and Jenkins. Without that setting, if you use non-ASCII characters as a git repository name or as a Jenkins job name, it will cause problems. See Containers and Tomcat i18n for Jenkins and GitBlit FAQ for more details. Anyway, we are all set! Restart Tomcat (I use DSM’s Package Center for that) and access Tomcat through HTTPS, which would look something like this: https://yourDomain:8443
You should see the Tomcat landing page and you can test that everything is setup correctly by providing your URL to Symantec CryptoReport (SSL Labs does not support ports other than 443).Note of Thanks
I did not come up with this solution on my own. Actually it was quite a ride until I figured out how this might work. Gladly the Let’s Encrypt Community is a wonderful place to ask questions, find people trying to overcome the same obstacles and to help each other. So I want to thank the Let’s Encrypt Community for helping me out to get my Tomcat server up and running with HTTPS! This opens up quite a few interesting usecases. One of them: Running GitBlit in Tomcat on my DiskStation and thus having a HTTPS accessible private Git server. In case you are interested in that, be sure to check back soon. I will definitely write a blog post about how to turn your DiskStation into a private Git server for you and your team in the near future.