CrtMgr Blog - SSL/TLS Certificate Management Insights

Expert insights on SSL/TLS certificate management, types, deployment, and best practices

How to Install SSL Certificate on Apache Tomcat

Tomcat SSL TLS Java Installation Guide

Apache Tomcat is a widely-used Java servlet container that powers enterprise applications worldwide. This comprehensive guide covers SSL/TLS certificate installation on Tomcat, from keystore creation to production-ready configuration.

Prerequisites

Before starting, ensure you have:

  • Apache Tomcat installed (version 8.5+ recommended)
  • Java Development Kit (JDK) installed
  • Root or administrative access to the server
  • SSL certificate files (or ability to generate them)
  • Basic understanding of Java keystores

Check your versions:

# Check Tomcat version
$CATALINA_HOME/bin/version.sh

# Check Java version
java -version

Understanding Java Keystores

Unlike other web servers that use PEM files, Tomcat uses Java keystores to store certificates and private keys. A keystore is a password-protected database file.

Keystore Types

  • JKS (Java KeyStore): Legacy format, widely supported
  • PKCS12: Modern format, recommended for new installations
  • JCEKS: Enhanced security features

For most applications, use PKCS12 format as it’s the industry standard.

Method 1: Self-Signed Certificate (Testing Only)

For development and testing environments, create a self-signed certificate.

Generate Self-Signed Certificate

# Navigate to Tomcat conf directory
cd $CATALINA_HOME/conf

# Generate keystore with self-signed certificate
keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 \
  -validity 365 -keystore tomcat-keystore.p12 \
  -storetype PKCS12

# You'll be prompted for:
# - Keystore password (remember this!)
# - Your name or domain name
# - Organizational unit
# - Organization
# - City/Locality
# - State/Province
# - Country code (2 letters)

Example interaction:

Enter keystore password: YourSecurePassword123
Re-enter new password: YourSecurePassword123
What is your first and last name?
  [Unknown]:  localhost
What is the name of your organizational unit?
  [Unknown]:  IT Department
What is the name of your organization?
  [Unknown]:  My Company
What is the name of your City or Locality?
  [Unknown]:  New York
What is the name of your State or Province?
  [Unknown]:  NY
What is the two-letter country code for this unit?
  [Unknown]:  US
Is CN=localhost, OU=IT Department, O=My Company, L=New York, ST=NY, C=US correct?
  [no]:  yes

Configure Tomcat for Self-Signed Certificate

Edit $CATALINA_HOME/conf/server.xml:

<!-- Comment out default HTTP connector if needed -->
<!--
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />
-->

<!-- Add HTTPS connector -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="conf/tomcat-keystore.p12"
                     certificateKeystorePassword="YourSecurePassword123"
                     certificateKeystoreType="PKCS12"
                     type="RSA" />
    </SSLHostConfig>
</Connector>

Restart Tomcat:

$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh

Access your application at https://localhost:8443

Note: Browsers will show security warnings for self-signed certificates. This is normal for testing but not acceptable for production.

Method 2: Commercial or Let’s Encrypt Certificate

For production environments, use certificates from trusted Certificate Authorities.

Step 1: Generate Certificate Signing Request (CSR)

# Create a new keystore with private key
keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 \
  -keystore tomcat-keystore.p12 -storetype PKCS12

# Generate CSR
keytool -certreq -alias tomcat -file tomcat.csr \
  -keystore tomcat-keystore.p12 -storetype PKCS12

When prompted, provide accurate information:

  • CN (Common Name): Your domain (e.g., example.com)
  • OU (Organizational Unit): Department name
  • O (Organization): Company legal name
  • L (Locality): City
  • ST (State): State or province
  • C (Country): Two-letter country code

Step 2: Submit CSR to Certificate Authority

# Display CSR content
cat tomcat.csr

Copy the entire CSR (including BEGIN and END lines) and submit to your CA:

  • DigiCert
  • GlobalSign
  • Sectigo
  • Let’s Encrypt (using Certbot)

Complete the domain validation process (email, DNS, or HTTP).

Step 3: Receive Certificate Files

You’ll receive:

  • Primary certificate (e.g., example.com.crt)
  • Intermediate certificate(s) (e.g., intermediate.crt)
  • Root certificate (sometimes included)

Step 4: Import Certificates into Keystore

First, import the root and intermediate certificates:

# Import root certificate (if provided separately)
keytool -import -trustcacerts -alias root -file root.crt \
  -keystore tomcat-keystore.p12 -storetype PKCS12

# Import intermediate certificate
keytool -import -trustcacerts -alias intermediate -file intermediate.crt \
  -keystore tomcat-keystore.p12 -storetype PKCS12

# Import your signed certificate
keytool -import -trustcacerts -alias tomcat -file example.com.crt \
  -keystore tomcat-keystore.p12 -storetype PKCS12

Important: Import certificates in order (root → intermediate → primary).

Step 5: Verify Keystore Contents

# List certificates in keystore
keytool -list -v -keystore tomcat-keystore.p12 -storetype PKCS12

# Verify certificate chain
keytool -list -keystore tomcat-keystore.p12 -storetype PKCS12

You should see the complete certificate chain.

Method 3: Let’s Encrypt with Certbot

For automated Let’s Encrypt certificates:

Install Certbot

# Ubuntu/Debian
sudo apt update
sudo apt install certbot

# CentOS/RHEL
sudo yum install certbot

Obtain Certificate

# Standalone mode (Tomcat must be stopped)
sudo certbot certonly --standalone -d example.com -d www.example.com

# Or webroot mode (Tomcat running)
sudo certbot certonly --webroot -w /path/to/tomcat/webapps/ROOT -d example.com

Certificates are saved to /etc/letsencrypt/live/example.com/

Convert to PKCS12 Keystore

Certbot creates PEM files, but Tomcat needs PKCS12:

# Convert PEM to PKCS12
sudo openssl pkcs12 -export \
  -in /etc/letsencrypt/live/example.com/fullchain.pem \
  -inkey /etc/letsencrypt/live/example.com/privkey.pem \
  -out /opt/tomcat/conf/tomcat-keystore.p12 \
  -name tomcat

# Set appropriate permissions
sudo chown tomcat:tomcat /opt/tomcat/conf/tomcat-keystore.p12
sudo chmod 600 /opt/tomcat/conf/tomcat-keystore.p12

Automate Renewal

Create renewal hook:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/tomcat-deploy.sh

Add:

#!/bin/bash
DOMAIN="example.com"
KEYSTORE_PASS="YourSecurePassword"
TOMCAT_HOME="/opt/tomcat"

# Convert renewed certificate
openssl pkcs12 -export -password pass:$KEYSTORE_PASS \
  -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem \
  -inkey /etc/letsencrypt/live/$DOMAIN/privkey.pem \
  -out $TOMCAT_HOME/conf/tomcat-keystore.p12 \
  -name tomcat

# Set permissions
chown tomcat:tomcat $TOMCAT_HOME/conf/tomcat-keystore.p12
chmod 600 $TOMCAT_HOME/conf/tomcat-keystore.p12

# Restart Tomcat
systemctl restart tomcat

Make executable:

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/tomcat-deploy.sh

Configuring Tomcat for Production SSL

Optimal server.xml Configuration

<Server port="8005" shutdown="SHUTDOWN">
  <!-- ... other configuration ... -->
  
  <Service name="Catalina">
    
    <!-- HTTP Connector - Redirect to HTTPS -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on"
               compressionMinSize="2048"
               noCompressionUserAgents="gozilla, traviata"
               compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json" />
    
    <!-- HTTPS Connector -->
    <Connector port="8443" 
               protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" 
               SSLEnabled="true"
               scheme="https" 
               secure="true"
               compression="on"
               compressionMinSize="2048">
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig protocols="TLSv1.2,TLSv1.3"
                       ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
                       honorCipherOrder="false">
            <Certificate certificateKeystoreFile="conf/tomcat-keystore.p12"
                         certificateKeystorePassword="YourSecurePassword123"
                         certificateKeystoreType="PKCS12"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    
    <!-- ... rest of configuration ... -->
  </Service>
</Server>

Force HTTPS for All Applications

Edit $CATALINA_HOME/conf/web.xml and add before </web-app>:

<!-- Force HTTPS for entire application -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Entire Application</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

Application-Specific HTTPS

For individual applications, edit WEB-INF/web.xml:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/admin/*</url-pattern>
        <url-pattern>/api/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

Using Tomcat Behind a Reverse Proxy

When Tomcat sits behind Nginx or Apache, configure Tomcat to trust proxy headers:

<!-- In server.xml, add to existing Connector -->
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443">
    <!-- Add valve for proxy awareness -->
    <Valve className="org.apache.catalina.valves.RemoteIpValve"
           remoteIpHeader="x-forwarded-for"
           proxiesHeader="x-forwarded-by"
           protocolHeader="x-forwarded-proto" />
</Connector>

This allows Tomcat to:

  • Detect HTTPS connections from proxy
  • Get real client IP addresses
  • Generate correct redirect URLs

Troubleshooting

Certificate Import Fails

Problem: “keytool error: java.lang.Exception: Failed to establish chain”

Solution: Import certificates in correct order (root → intermediate → primary)

# Delete existing aliases if needed
keytool -delete -alias tomcat -keystore tomcat-keystore.p12

# Start fresh with correct order
keytool -import -trustcacerts -alias root -file root.crt -keystore tomcat-keystore.p12
keytool -import -trustcacerts -alias intermediate -file intermediate.crt -keystore tomcat-keystore.p12
keytool -import -trustcacerts -alias tomcat -file example.com.crt -keystore tomcat-keystore.p12

Wrong Password Error

Problem: “keystore password was incorrect”

Solution: Reset keystore password if forgotten:

# Change keystore password
keytool -storepasswd -keystore tomcat-keystore.p12 -storetype PKCS12

# Change key password
keytool -keypasswd -alias tomcat -keystore tomcat-keystore.p12

Tomcat Won’t Start After SSL Configuration

Check logs:

tail -f $CATALINA_HOME/logs/catalina.out

Common issues:

  • Incorrect keystore path in server.xml
  • Wrong keystore password
  • Invalid XML in server.xml
  • Port 8443 already in use

Browser Shows “NET::ERR_CERT_AUTHORITY_INVALID”

Causes:

  • Self-signed certificate (expected for dev)
  • Incomplete certificate chain
  • Wrong certificate installed

Solution: Verify certificate chain:

# Check certificate in keystore
keytool -list -v -keystore tomcat-keystore.p12 | grep -A 5 "Certificate chain"

Security Best Practices

  1. Protect Keystore Files

    chmod 600 $CATALINA_HOME/conf/tomcat-keystore.p12
    chown tomcat:tomcat $CATALINA_HOME/conf/tomcat-keystore.p12
    
  2. Use Strong Passwords

    • Minimum 12 characters
    • Mix of letters, numbers, symbols
    • Different from system passwords
  3. Disable Weak Protocols

    <SSLHostConfig protocols="TLSv1.2,TLSv1.3">
    
  4. Regular Certificate Monitoring

    • Use CrtMgr to track expiration
    • Set up alerts 30 days before expiry
    • Test renewal procedures
  5. Keep Tomcat Updated

    # Check for security updates
    # Update Tomcat regularly
    

Testing Your Configuration

Command Line Tests

# Test HTTPS connection
openssl s_client -connect localhost:8443

# Check certificate details
echo | openssl s_client -connect localhost:8443 2>/dev/null | openssl x509 -noout -text

# Verify certificate chain
echo | openssl s_client -connect localhost:8443 -showcerts

Test from Browser

  1. Access https://your-domain:8443
  2. Click padlock icon
  3. View certificate details
  4. Verify issuer and expiration

Use SSL Labs

For public-facing servers:

Monitoring Certificate Expiration

Use CrtMgr to monitor your Tomcat certificates:

  1. Add your domain to CrtMgr dashboard
  2. Configure expiration alerts (e.g., 30, 7, 1 days)
  3. Set up public status page for your certificates
  4. Receive email notifications before expiration

Alternatively, create a monitoring script:

#!/bin/bash
KEYSTORE="/opt/tomcat/conf/tomcat-keystore.p12"
PASSWORD="YourKeystorePassword"
WARN_DAYS=30

# Extract certificate
keytool -list -v -keystore $KEYSTORE -storepass $PASSWORD -alias tomcat | \
  grep "Valid until" | \
  awk -F': ' '{print $2}'

Conclusion

Installing SSL certificates on Apache Tomcat requires understanding Java keystores, but the process is straightforward:

  1. Generate or obtain SSL certificate
  2. Create PKCS12 keystore
  3. Import certificates in correct order
  4. Configure server.xml
  5. Test and monitor

Key takeaways:

  • Use PKCS12 keystores for new installations
  • Import certificates in correct order (root → intermediate → certificate)
  • Enable TLS 1.2 and 1.3 only
  • Monitor certificates with tools like CrtMgr
  • Automate Let’s Encrypt renewals with hooks

With proper SSL configuration, your Tomcat server will serve secure HTTPS connections with optimal security settings. Regular monitoring prevents certificate expiration surprises.

Related Articles