Install a TLS certificate on Apache Tomcat

Tomcat 8.5 and later can read PEM files directly — set `certificateFile`, `certificateKeyFile` and `certificateChainFile` on an `SSLHostConfig`, and no keystore is needed at all. The older keystore route still works: convert to PKCS#12 with `openssl pkcs12 -export` and point `keystoreFile` at it with `keystoreType="PKCS12"`. Prefer PKCS#12 over JKS, which has been deprecated since Java 9. The most common failure is a keystore password that differs from the key password, which Tomcat does not handle.

Updated August 19, 2026 Verified against OpenSSL 3.5.7

The modern way — PEM directly #

Tomcat 8.5 introduced SSLHostConfig, which reads PEM without any keystore:

conf/server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
         maxThreads="150" SSLEnabled="true">
  <SSLHostConfig>
      <Certificate
          certificateFile="/etc/ssl/certs/certificate.crt"
          certificateKeyFile="/etc/ssl/private/private.key"
          certificateChainFile="/etc/ssl/certs/chain.crt"
          type="RSA" />
  </SSLHostConfig>
</Connector>

Replace these values

PlaceholderWhat to put there
certificateFileThe server certificate alone — not the full chain.
certificateChainFileThe intermediates. Tomcat is one of the few servers with a separate directive for this.
certificateKeyFileThe private key, unencrypted PKCS#8.

The key must be PKCS#8. If yours starts BEGIN RSA PRIVATE KEY, convert it — writing to a new file rather than over the original, so a mistake is recoverable:

openssl pkcs8 -topk8 -in pkcs1.key -out private-pkcs8.key -nocrypt

See PKCS#1 to PKCS#8.

The keystore way #

Required on Tomcat before 8.5, and still common.

Build a PKCS#12 keystore
openssl pkcs12 -export \
-in certificate.crt -inkey private.key -certfile chain.crt \
-name tomcat -out keystore.p12 -passout pass:changeit
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
         maxThreads="150" SSLEnabled="true"
         scheme="https" secure="true"
         keystoreFile="/opt/tomcat/conf/keystore.p12"
         keystorePass="changeit"
         keystoreType="PKCS12"
         keyAlias="tomcat"
         clientAuth="false" sslProtocol="TLS" />

Starting from a PFX you were given #

cp certificate.pfx /opt/tomcat/conf/keystore.p12

A PFX is a PKCS#12 keystore — no conversion needed, just point keystoreFile at it and set keystoreType="PKCS12". Find the alias first, because Tomcat needs it:

keytool -list -keystore certificate.pfx -storetype PKCS12

Restart and verify #

systemctl restart tomcat
What is actually being served
openssl s_client -connect example.com:8443 -servername example.com </dev/null 2>/dev/null \
| grep -E "Verify return code|subject="
Is the chain complete?
openssl s_client -connect example.com:8443 -servername example.com -showcerts </dev/null 2>/dev/null \
| grep -c "BEGIN CERTIFICATE"
Expected output
2

Common Tomcat failures #

Symptom Cause Fix
Cannot recover key Key password ≠ keystore password Set both the same
Alias name [x] does not identify a key entry Wrong keyAlias, or a certificate-only entry keytool -list and use the real alias
Connector fails to start, no detail Wrong keystoreType for the file PKCS12 for .p12/.pfx, JKS for .jks
Works, but clients report an untrusted issuer certificateChainFile missing Point it at the intermediates
PEM key rejected Key is PKCS#1, not PKCS#8 Convert it

Frequently asked questions

Do I still need a keystore?
Not on Tomcat 8.5 or later, which reads PEM directly via certificateFile and friends. That removes the conversion step and makes ACME renewal far simpler, since certbot already writes PEM.
Why does Tomcat fail with "Cannot recover key"?
The key password inside the keystore differs from the keystore password. Tomcat assumes they are the same. Fix it with keytool -keypasswd -alias myalias -keystore keystore.p12, setting the key password to match.
JKS or PKCS#12?
PKCS#12. It has been the Java default since version 9, keytool warns about JKS on every use, and OpenSSL can read PKCS#12 directly, which makes every later operation easier.
Does Tomcat reload the certificate without a restart?
Not by default. Some versions support SSLHostConfig reload through JMX, but a restart is the reliable route. Plan renewal around that.

References