How to Install SSL Certificate on Apache Tomcat
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
Protect Keystore Files
chmod 600 $CATALINA_HOME/conf/tomcat-keystore.p12 chown tomcat:tomcat $CATALINA_HOME/conf/tomcat-keystore.p12Use Strong Passwords
- Minimum 12 characters
- Mix of letters, numbers, symbols
- Different from system passwords
Disable Weak Protocols
<SSLHostConfig protocols="TLSv1.2,TLSv1.3">Regular Certificate Monitoring
- Use CrtMgr to track expiration
- Set up alerts 30 days before expiry
- Test renewal procedures
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
- Access
https://your-domain:8443 - Click padlock icon
- View certificate details
- Verify issuer and expiration
Use SSL Labs
For public-facing servers:
- Visit https://www.ssllabs.com/ssltest/
- Enter your domain
- Review the grade and recommendations
Monitoring Certificate Expiration
Use CrtMgr to monitor your Tomcat certificates:
- Add your domain to CrtMgr dashboard
- Configure expiration alerts (e.g., 30, 7, 1 days)
- Set up public status page for your certificates
- 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:
- Generate or obtain SSL certificate
- Create PKCS12 keystore
- Import certificates in correct order
- Configure server.xml
- 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.