How-to guide · Install on a server
How to install a certificate in Tomcat and other Java servers
In one sentence
Tomcat, or a Spring Boot or other Java server, serves your certificate with its full chain from PEM files or a PKCS #12 keystore, verified from outside.
- Platforms
- Linux
- Windows
- Java
- Tomcat
- Level
- Practitioner · 6 steps
On this page
Before you start
- Your server certificate (the leaf certificate), the CA’s intermediate certificate or certificates, and the private key, as PEM files, or a PKCS #12 file that holds all three.
- Tomcat 9, 10.1 or 11 on a supported Java; the attributes below are the same in all three.
- Write access to Tomcat’s
conf/server.xmland the right to restart it.
Why it matters: Java servers send the chain you configure, and Java clients do not fetch a missing intermediate, so a short chain breaks every Java, Python and Node.js client that calls your service.
Steps
1. Prepare the files, readable by Tomcat only
Keep the leaf, the chain and the key in separate files; step 2 explains why. On Ubuntu, Tomcat runs as the user tomcat:
sudo mkdir -p /etc/tomcat10/tls
sudo cp www.example.com.crt /etc/tomcat10/tls/cert.pem
sudo cp intermediate.crt /etc/tomcat10/tls/chain.pem
sudo cp www.example.com.key /etc/tomcat10/tls/privkey.pem
sudo chown root:tomcat /etc/tomcat10/tls/*
sudo chmod 640 /etc/tomcat10/tls/privkey.pem
Unlike nginx and Apache, Tomcat reads the key as its own unprivileged user, so the key must be readable by that user and nobody else.
2. Configure the HTTPS connector with PEM files
Add a connector inside <Service> in server.xml (Tomcat HTTP connector):
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig hostName="_default_" protocols="TLSv1.2+TLSv1.3">
<Certificate certificateFile="/etc/tomcat10/tls/cert.pem"
certificateChainFile="/etc/tomcat10/tls/chain.pem"
certificateKeyFile="/etc/tomcat10/tls/privkey.pem" />
</SSLHostConfig>
</Connector>
protocols defaults to all, which includes TLS 1.0 and 1.1, so state it. Port 8443 is Tomcat’s convention; for 443, put a load balancer or reverse proxy in front, or give Java permission to bind low ports.
3. Or use a PKCS #12 keystore
A keystore works with Tomcat’s JSSE implementation and with most other Java servers, such as Jetty and WildFly. Build it with the chain included (PFX and PEM; from an old JKS file, see JKS to PKCS #12):
openssl pkcs12 -export -out www.p12 -inkey www.example.com.key -in www.example.com.crt -certfile intermediate.crt -name tomcat
<SSLHostConfig hostName="_default_" protocols="TLSv1.2+TLSv1.3">
<Certificate certificateKeystoreFile="/etc/tomcat10/tls/www.p12"
certificateKeystorePassword="use-a-real-secret"
certificateKeystoreType="PKCS12" />
</SSLHostConfig>
The password sits in server.xml, so keep that file readable only by root and Tomcat as well.
4. Restart and read the log
sudo systemctl restart tomcat10
sudo journalctl -u tomcat10 | grep 'Connector \[https'
Our test logged which files each connector loaded (timestamp removed):
Connector [https-openssl-nio-29445], TLS virtual host [_default_], certificate type [UNDEFINED] configured from key [/etc/tomcat10/tls/privkey.pem], certificate [/etc/tomcat10/tls/cert.pem] and certificate chain [/etc/tomcat10/tls/chain.pem] with trust store [null]
The name shows the implementation: https-openssl-nio or https-jsse-nio. Read the log after every change: in our tests Tomcat kept running even when the HTTPS connector failed to start.
5. Spring Boot
Embedded Tomcat in Spring Boot takes PEM files directly (Spring Boot: configure SSL). An SSL bundle can also reload renewed files without a restart (SSL bundles):
server:
port: 8443
ssl:
bundle: "web"
spring:
ssl:
bundle:
pem:
web:
reload-on-update: true
keystore:
certificate: "file:/etc/myapp/tls/fullchain.pem"
private-key: "file:/etc/myapp/tls/privkey.pem"
Run the same outside check (below) on Spring Boot: we did not test how its PEM loader handles a full chain in one file.
6. Plan for renewal
Tomcat reads the files at start-up. After a renewal, restart it, or reload only the TLS files with the Manager application’s /manager/text/sslReload?tlsHostName=_default_ command (Manager how-to). With short certificate lifetimes, automate this step.
Check it worked
From another machine if you can:
openssl s_client -connect www.example.com:8443 -servername www.example.com </dev/null 2>/dev/null | grep -E '^ [0-9] s:|Verify return code'
Our test server (private test CA, so we added -CAfile corp-root.crt):
0 s:CN = intranet.example.com
1 s:C = BE, O = Example Corp, CN = Example Corp Issuing CA 1
Verify return code: 0 (ok)
Two certificates and code 0. Paste the -showcerts output into the chain checker:
If something goes wrong
- One certificate is sent; clients report
unable to verify the first certificate,unable to get local issuer certificateor, in Java,PKIX path building failed. Move the intermediates tocertificateChainFile(step 2), or rebuild the keystore with-certfile(step 3). See build the full chain. java.io.IOException: keystore password was incorrectin the log. ThecertificateKeystorePassworddoes not match the file.java.io.FileNotFoundException: /etc/tomcat10/tls/www.p12 (Permission denied). The Tomcat user cannot read the file (step 1).java.net.BindException: Address already in use. Another process holds that port.- Java clients report
Received fatal alert: handshake_failure. No common protocol or cipher, or the connector started without a certificate; read the Tomcat log first. - The key does not match the certificate. Check them before you restart.
Why this works
Tomcat builds a TLS context per SSLHostConfig from the certificate, chain and key you name, then presents that chain in the TLS handshake and proves it holds the key. The client builds a certificate chain from your leaf through the intermediates to a root in its own trust store. See Certificate chains and path validation, The TLS 1.3 handshake and Certificate file formats.
Go deeper
- Tomcat 10.1: SSL support in the HTTP connector: every
SSLHostConfigandCertificateattribute. - Tomcat SSL/TLS how-to: keystores, PEM files and the two implementations.
- Spring Boot: SSL bundles: PEM bundles and reloading.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.