ssl
tomcat
This 2018 I needed to install an SSL Certificate for a web application. Since Tomcat 9 features virtual hosted web application with differentiated SSL hosts, the next step were easy to guess: move to Java 10 plus Tomcat 9 and make use of these new features. This article goes about the process to its final ending, this web site.
First issues when migrating
Java 9 and above no longer include JAXB. Simply add the JAXB library to Tomcat 9.
Tomcat 9 no longer put the final slash to the URL (does not redirect). Modify conf/context.xml
to include mapper
attributes:
<Context ...
mapperContextRootRedirectEnabled="true"
mapperDirectoryRedirectEnabled="true"/>
Requirements
- Tomcat 9, although I've been told 8.5 also supported SSL host virtualization.
- Java 8 or higher. This example has been tested with Java 10.
Elements used for this article
- This web site, an open source web application.
- A Comodo Essential Certificate.
- A full weekend

Asking for the certificate
If you already have a certificate you may want to skip this part. Otherwise, buy a certificate and continue.
First thing the provider ask for is a Certificate Signing Request. Lets generate one:
openssl req -new -newkey rsa:2048 -nodes -out [yourdomain].csr -keyout [yourdomain].key -subj "/C=[country]/ST=[state]/L=[city]/O=[organization]/OU=[department]/CN=[domain]"
Field |
Description |
yourdomain |
This will be the file name. For example www_domain_whatever, in my case www_turro_org . |
country |
Two uppercase letters of your country, see ISO 3166-1. |
state |
Your state or province, as is. |
city |
Your city. |
organization |
Your organization name. |
department |
Department managing de certificate. |
domain |
As for Comodo Essential, the domain will apply to www.[domain] and [domain] as longer as you use www. .
Recomendation: use www.domain , in my case www.turro.org . |
Once executed, this command generated two files, yourdomain.csr
and yourdomain.key
. The CSR file is the Certificate Signing Request, and is the first thing you will need to provide when asking your certificate. The second is the Private Key. Keep them both in a secure place.
Installing the certificate into a keystore
If everything has gone well, you now have a response from the Certification Provider and some certificates in you hard disk. Copy them where you saved previous generated files, CSR and private key. If you followed the instructions, you private key is stored in [yourdomain].key
file.
Now, one of the certificates you received is your certificate. The rest are called root certificate and chain certificates.
Change to convenient format
First thing we'll do is convert your private key and your certificate to PKCS12 format. Don't bother now as to why we use this format, I want a single keystore to include the whole bunch of certificates to simplify Tomcat configuration, and it turns out that Tomcat NIO likes this format. So, have it.
openssl pkcs12 -export -in [yourcertificate] -inkey [yourdomain].key -name [yourdomain] -out [yourdomain].p12
Field |
Description |
yourcertificate |
Your certificate is one of those the certification provider sent you. As for Comodo, my certificate was www_turro_org.crt , so it was easy to point out which one was mine. |
yourdomain |
This will be the file name. For example www_domain_whatever, in my case www_turro_org . |
Import private key and certificates into the keystore
This step creates a new keystore file.
keytool -importkeystore -destkeypass [password] -destkeystore [yourdomain].keystore -srckeystore [yourdomain].p12 -srcstoretype PKCS12 -srcstorepass [password]
Now, add the root and chain certificates. Bellow the example with Comodo certificates. You may follow instructions provided for your own certificate provider. Notice that the only pattern used is alias equal to certificate file minus extension.
keytool -import -trustcacerts -alias AddTrustExternalCARoot -file AddTrustExternalCARoot.crt -keystore [yourdomain].keystore
keytool -import -trustcacerts -alias COMODORSAAddTrustCA -file COMODORSAAddTrustCA.crt -keystore [yourdomain].keystore
keytool -import -trustcacerts -alias COMODORSADomainValidationSecureServerCA -file COMODORSADomainValidationSecureServerCA.crt -keystore [yourdomain].keystore
If you followed the instructions, you have a keystore named [yourdomain].keystore
with everything required by Tomcat.
Installing the keystore
Let's explain something about Tomcat. Tomcat has a single Connector
for SSL configuration. Once you configure your keystore, it will be available by all the web application installed, but will only certificate your domain. So, where SSL hosting virtualization is?
Don't panic, there is SSL hosting virtualization. You achieve the goal by creating SSLHostConfig
elements with hostName
attribute set to match one of the Host
elements its name
attribute. One of them will need to be the defaultSSLHostConfigName
attribute in the Connector
element. Messy? See the server.xml
example with the values we used:
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
defaultSSLHostConfigName="[domain]"
...
>
<SSLHostConfig hostName="[domain]">
<Certificate certificateKeystoreFile="[yourdomain].keystore"
certificateKeystorePassword="[password]"/>
</SSLHostConfig>
....
</Connector>
...
<Engine name="Catalina" defaultHost="[domain]">
<Host name="[domain]" appBase="/anyfolder"
unpackWARs="false" autoDeploy="false">
</Host>
...
</Engine>
Let's suppose we followed the steps with [domain2]
values. The server.xml
will look like:
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
defaultSSLHostConfigName="[domain]"
...
>
<SSLHostConfig hostName="[domain]">
<Certificate certificateKeystoreFile="[yourdomain].keystore"
certificateKeystorePassword="[password]"/>
</SSLHostConfig>
<SSLHostConfig hostName="[domain2]">
<Certificate certificateKeystoreFile="[yourdomain2].keystore"
certificateKeystorePassword="[password2]"/>
</SSLHostConfig>
....
</Connector>
...
<Engine name="Catalina" defaultHost="[domain]">
<Host name="[domain]" appBase="/anyfolder"
unpackWARs="false" autoDeploy="false">
</Host>
<Host name="[domain2]" appBase="/anyfolder2"
unpackWARs="false" autoDeploy="false">
</Host>
...
</Engine>
Now everything is more clear. [domain]
is the default SSL configuration, but when somebody visits [domain2]
there is a match between SSLHostConfig
its hostName
attribute and Host
its name
attribute. Thus, [yourdomain2].keystore
will be used.
Restart your Tomcat and... That's all!