Apache Tomcat handles SSL/TLS differently from web servers like Nginx and Apache HTTP Server. Instead of pointing to certificate and key files directly, Tomcat uses a Java keystore: a file that contains the private key and certificate chain in a standardized format. The keystore path and password are referenced in Tomcat’s server.xml connector configuration.
The configuration approach also depends on which Tomcat version you are running. Tomcat 9 introduced the SSLHostConfig and Certificate nested elements as the recommended SSL configuration method. Tomcat 10+ made this the standard approach. Tomcat 11 removed support for the older Connector-level SSL attributes entirely. Many online guides still show the older approach, which works for Tomcat 8 and early Tomcat 9 but produces deprecation warnings in Tomcat 9 and fails in Tomcat 11.
This guide covers SSL concepts specific to Tomcat, the keystore formats Tomcat supports, the configuration approach for each Tomcat version, and the most common configuration errors.
How Tomcat Handles SSL: The Connector and Keystore Model
Tomcat’s HTTP connector in server.xml handles both HTTP and HTTPS traffic. For HTTPS, the connector needs three pieces of information: where the keystore file is, what the keystore password is, and optionally which alias (entry) in the keystore to use for the certificate. The connector binds to a port (typically 8443 for HTTPS) and performs TLS negotiation using the certificate from the keystore.
The keystore is a binary container file that holds one or more certificate and private key entries, each identified by an alias. When Tomcat starts, it reads the keystore, loads the certificate for the specified alias (or the only entry if there is one), and uses it to negotiate TLS connections on the HTTPS port.
Tomcat does not use the standard Linux/macOS filesystem locations for certificates (/etc/ssl/certs). It reads only from the keystore file specified in server.xml. If you receive a certificate from a CA as PEM files (a .crt file and a .key file), you must convert them into a keystore before Tomcat can use them.
Keystore Formats: PKCS12 vs JKS
| Format | Extension | Status | Tomcat support | Notes |
| PKCS12 | keystore.p12 or keystore.pfx | Recommended since JDK 9 | Fully supported in all current Tomcat versions | Standard format; compatible with OpenSSL, Windows, macOS, keytool |
| JKS (Java KeyStore) | keystore.jks | Deprecated since JDK 9; still supported | Supported in Tomcat 9 and 10; check Tomcat 11 release notes | Proprietary Java format; cannot be used outside Java tools without conversion |
Use PKCS12 for all new Tomcat SSL configurations. If you have an existing JKS keystore, it continues to work but migration to PKCS12 is recommended. The keytool migration command is: keytool -importkeystore -srckeystore existing.jks -srcstoretype JKS -destkeystore new.p12 -deststoretype PKCS12.
Preparing the Keystore from CA-Issued Certificate Files
Certificate Authorities deliver signed certificates as PEM files (.crt or .pem) with a separate private key file (.key). These must be combined into a PKCS12 keystore for Tomcat. Use OpenSSL for this conversion:
| # Create a PKCS12 keystore from PEM certificate and key files:
$ openssl pkcs12 -export \ -in your_certificate.crt \ -inkey private.key \ -out tomcat_keystore.p12 \ -name tomcat \ -CAfile intermediate_and_root.crt \ -caname root \ -chain
# -name tomcat sets the alias. Use this exact alias in server.xml. # -CAfile should reference the CA bundle (intermediate + root chain). # You will be prompted for an export password. Remember this for server.xml.
# Verify the keystore contains the correct entries: $ keytool -list -keystore tomcat_keystore.p12 -storetype PKCS12 # Should show your certificate alias and a PrivateKeyEntry type. |
The -name parameter (the alias) in the openssl pkcs12 export command must match what you specify in the certificateKeyAlias attribute in server.xml. If you omit certificateKeyAlias in server.xml and the keystore has only one entry, Tomcat uses that entry automatically. If the keystore has multiple entries, you must specify the alias explicitly.
Tomcat 9, 10, and 11: The SSLHostConfig Approach (Recommended)
Tomcat 9 introduced the SSLHostConfig and Certificate elements as nested children of the Connector element. This is the recommended approach for Tomcat 9+ and the required approach for Tomcat 10.1+ and Tomcat 11. It supports SNI (Server Name Indication) for multiple certificates on one connector, and it cleanly separates the transport protocol configuration from the certificate configuration.
| <!– server.xml: Tomcat 9+ recommended HTTPS configuration –>
<Connector port=”8443″ protocol=”org.apache.coyote.http11.Http11NioProtocol” maxThreads=”150″ SSLEnabled=”true”> <SSLHostConfig> <Certificate certificateKeystoreFile=”conf/tomcat_keystore.p12″ certificateKeystorePassword=”your_keystore_password” certificateKeystoreType=”PKCS12″ certificateKeyAlias=”tomcat” type=”RSA” /> </SSLHostConfig> </Connector>
<!– Notes: – certificateKeystoreFile: path relative to CATALINA_HOME, or absolute path – certificateKeystoreType: PKCS12 (recommended) or JKS – certificateKeyAlias: the alias set with -name in openssl pkcs12 export – type: RSA (for RSA keys) or EC (for ECDSA keys) – protocol: Http11NioProtocol is standard; Http11Nio2Protocol is also available –> |
Tomcat 8 and Early Tomcat 9: Legacy Connector Attributes
For Tomcat 8 and as an alternative (not recommended) approach in Tomcat 9, SSL can be configured directly on the Connector element using keystoreFile, keystorePass, and related attributes. This approach works in Tomcat 8 and Tomcat 9 but produces deprecation warnings in Tomcat 9 and was removed in Tomcat 10.1 and Tomcat 11.
| <!– server.xml: Legacy Connector SSL (Tomcat 8, early Tomcat 9 only) –>
<!– DO NOT USE for Tomcat 10.1+ or Tomcat 11 –> <Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true” maxThreads=”150″ scheme=”https” secure=”true” keystoreFile=”conf/tomcat_keystore.p12″ keystorePass=”your_keystore_password” keystoreType=”PKCS12″ keyAlias=”tomcat” clientAuth=”false” sslProtocol=”TLS” /> |
The legacy Connector attribute approach is not forward-compatible. If you are configuring SSL on Tomcat 9 for a server that will eventually upgrade to Tomcat 10 or 11, use the SSLHostConfig approach from the start. Converting from legacy to SSLHostConfig during a version upgrade adds risk. The attribute names also differ slightly between the two approaches: keystoreFile vs certificateKeystoreFile, keystorePass vs certificateKeystorePassword, keyAlias vs certificateKeyAlias.
APR Connector: Different Attributes for Native TLS
Some Tomcat distributions include the Apache Portable Runtime (APR) native library, which provides an alternative TLS implementation using OpenSSL directly rather than JSSE (Java Secure Socket Extension). When APR is available and active, Tomcat uses a different connector protocol and different SSL attributes.
To check whether APR is active: look for a line like ‘Loaded Apache Tomcat Native library’ in the Tomcat startup log (catalina.out). If APR is loading, the connector may use org.apache.coyote.http11.Http11AprProtocol.
The APR connector uses Apache mod_ssl style attributes rather than keystore attributes:
| <!– APR connector: uses PEM files directly, not a keystore –>
<Connector port=”8443″ protocol=”org.apache.coyote.http11.Http11AprProtocol” SSLEnabled=”true” maxThreads=”150″ scheme=”https” secure=”true” SSLCertificateFile=”/path/to/your_certificate.crt” SSLCertificateKeyFile=”/path/to/private.key” SSLCertificateChainFile=”/path/to/chain.crt” clientAuth=”off” SSLProtocol=”TLSv1.2+TLSv1.3″ />
<!– APR takes PEM files directly (like Nginx/Apache), NOT a Java keystore. Do not mix APR attributes with JKS/PKCS12 keystore attributes. –> |
Port 8443 vs Port 443: Production Considerations
Tomcat defaults to port 8443 for HTTPS because binding to ports below 1024 on Linux and macOS requires root privileges, and running Tomcat as root is a security risk. For production deployments where users should access the site at https://example.com (port 443) without specifying a port number in the URL, several options exist:
- Reverse proxy (recommended): Run Nginx or Apache HTTP Server on port 443 as a reverse proxy in front of Tomcat on port 8080 or 8443. The reverse proxy terminates TLS, holds the certificate, and forwards requests to Tomcat. This is the most common production pattern and keeps Tomcat running without root privileges.
- Port redirect using iptables (Linux): Use iptables to redirect port 443 TCP traffic to port 8443. This allows Tomcat to bind to 8443 while appearing on 443 to external connections. No root process needed for Tomcat.
- Authbind: A utility that allows specific processes to bind to privileged ports without running as root. Configure authbind to allow the Tomcat user to bind to port 443, then set Tomcat’s HTTPS connector port to 443 directly.
- Run as root (not recommended): Tomcat can be configured to run as root and bind to port 443 directly. This is a security risk and should be avoided in production.
Common Tomcat SSL Errors and Fixes
| Error | Cause | Fix |
| java.io.FileNotFoundException: .keystore (No such file or directory) | Tomcat is looking in the default location ($CATALINA_HOME/.keystore) because keystoreFile was omitted. Or the path in server.xml is wrong. | Verify the certificateKeystoreFile path. Use an absolute path to avoid ambiguity. Relative paths are relative to CATALINA_HOME, not the conf/ directory. |
| java.io.IOException: Invalid keystore format | The keystore type specified in server.xml does not match the actual keystore file format | Verify the certificateKeystoreType (PKCS12 or JKS) matches the file. Check with: keytool -list -keystore yourfile.p12 -storetype PKCS12 |
| javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? | HTTP request arriving on the HTTPS port. A reverse proxy or redirect is sending plain HTTP to the HTTPS port. | Ensure all redirects send traffic to the correct HTTPS port. Check reverse proxy configuration. |
| Certificate does not match the expected hostname | Certificate’s SAN entries do not include the hostname being accessed | Reissue the certificate with the correct SAN entries, or update the Tomcat URL to match the certificate’s covered hostname. |
| AliasNotFound exception or wrong certificate served | Keystore has multiple entries and the alias specified in server.xml does not match any entry, or was omitted when multiple entries exist | Run keytool -list on the keystore to see all aliases. Set certificateKeyAlias to the exact alias shown for the correct certificate entry. |
Verifying the SSL Configuration After Restart
After updating server.xml and restarting Tomcat, verify the SSL configuration from an external perspective. Check the Tomcat startup log (catalina.out or catalina.log) for any SSL-related exceptions during startup. If Tomcat starts without errors, use an external tool to confirm the correct certificate is being served.
| # Check which certificate Tomcat is serving:
$ openssl s_client -connect yourdomain.com:8443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -text | grep -E ‘Subject:|Issuer:|Not After|DNS:’
# The output shows the certificate subject, issuer, expiry, and SAN entries. # Confirm the Subject and DNS entries match your domain.
# Run SSL Labs for a comprehensive check (replace PORT if not 443): # ssllabs.com/ssltest — note SSL Labs only checks standard port 443. # For port 8443, use: openssl s_client -connect host:8443 -showcerts |
Frequently Asked Questions
What keystore format should I use for Tomcat SSL?
Use PKCS12 (file extension .p12 or .pfx). It is the industry standard format, the default since JDK 9, and compatible with OpenSSL and other tools outside the Java ecosystem. JKS (Java KeyStore) is deprecated since JDK 9 and still supported in Tomcat 9 and 10 but its long-term support in future versions is not guaranteed. For all new Tomcat SSL configurations, use PKCS12 and specify certificateKeystoreType=”PKCS12″ in server.xml.
What is the difference between the old Connector SSL attributes and SSLHostConfig?
The old approach puts SSL attributes directly on the Connector element: keystoreFile, keystorePass, keyAlias. This approach works in Tomcat 8 and Tomcat 9 but is deprecated in Tomcat 9 and removed in Tomcat 10.1 and Tomcat 11. The new SSLHostConfig approach uses nested SSLHostConfig and Certificate elements inside the Connector, using attributes named certificateKeystoreFile, certificateKeystorePassword, and certificateKeyAlias. The SSLHostConfig approach also supports SNI for multiple certificates. For any Tomcat 9+ deployment, use SSLHostConfig.
Why is Tomcat serving the wrong certificate?
The most common cause is that the keystore contains multiple certificate entries and the certificateKeyAlias is not set or is set to an alias that does not exist. Run keytool -list -keystore yourfile.p12 -storetype PKCS12 to see all aliases in the keystore. Set certificateKeyAlias in server.xml to the exact alias of the certificate you want Tomcat to serve. If the keystore has only one entry, the alias is optional and Tomcat uses that entry automatically.
How do I configure Tomcat for HTTPS on port 443 without running as root?
The recommended production approach is a reverse proxy. Run Nginx or Apache HTTP Server on port 443 with an SSL certificate, and proxy requests to Tomcat on a non-privileged port (8080 or 8443). This keeps Tomcat running as a non-root user, offloads TLS processing to the reverse proxy, and allows using Nginx’s or Apache’s more flexible certificate management. Alternatively, use iptables to redirect port 443 to Tomcat’s port 8443, which allows Tomcat to bind to 8443 (no root needed) while appearing on 443 externally.
