When your web application moves beyond hobby status, the first hardening step is wrapping every byte in TLS. Tomcat makes the process painless once you understand where the moving parts live. In this guide you will create (or import) a certificate, wire it into Tomcat’s connector, and verify that the padlock appears in every browser.
Why HTTPS on Tomcat Matters
Plain HTTP exposes cookies, credentials, and payloads to anyone on the wire. Search engines penalize insecure sites, browsers now flag non-TLS pages as “Not Secure”, and compliance frameworks such as PCI-DSS simply forbid clear-text traffic. Turning on HTTPS:
- Encrypts data in transit
- Proves server identity to clients
- Unlocks HTTP/2 and modern protocols
- Keeps Google and your security team happy
Prerequisites and Environment
Before touching configuration files ensure:
- Tomcat 9.x or 10.x is installed and starts cleanly on port
8080 - JAVA_HOME points to JDK 8+ (keytool comes with the JDK)
- OpenSSL 1.1+ if you prefer generating private keys externally
- Server DNS name (e.g.
app.ankurm.com) resolves to the VM or container
Step 1 – Create a Keystore and Private Key
The Java ecosystem stores certificates and keys inside a password-protected JKS (or PKCS12) keystore. Use JDK’s keytool so there are no extra dependencies.
$ keytool -genkeypair \
-alias tomcat \
-keyalg RSA -keysize 2048 \
-keystore /opt/tomcat/conf/ankurm.jks \
-validity 365 \
-ext SAN=DNS:app.ankurm.com,IP:10.0.0.7
Answer the prompts—important: First & last name must be the fully-qualified domain name the browser will use. Pick a strong keystore password and write it down; you’ll need it twice more.
Step 2 – Obtain or Create a Trusted Certificate
A. Self-signed (dev / internal labs)
Your keystore already contains a certificate, but browsers will distrust it. Export it anyway so you can import into client truststores if needed.
$ keytool -exportcert -alias tomcat -keystore /opt/tomcat/conf/ankurm.jks \
-file ankurm.cer
B. Public CA (Let’s Encrypt, Digicert, GoDaddy, …)
Create a CSR:
$ keytool -certreq -alias tomcat \
-keystore /opt/tomcat/conf/ankurm.jks \
-file ankurm.csr \
-ext SAN=DNS:app.ankurm.com
Upload the CSR to your CA. You’ll receive two files:
ankurm.crt(server certificate)ca-bundle.crt(intermediate chain)
Import them in the correct order:
# 1. Add root + intermediates
$ keytool -importcert -alias root -keystore ankurm.jks -file root.crt
$ keytool -importcert -alias intermediate -keystore ankurm.jks -file intermediate.crt
# 2. Finally the server cert
$ keytool -importcert -alias tomcat -keystore ankurm.jks -file ankurm.crt
Step 3 – Declare the HTTPS Connector in server.xml
Open $CATALINA_BASE/conf/server.xml, locate the existing <Connector port="8080" block and add a second one right below it.
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="conf/ankurm.jks"
keystorePass="CHANGEIT"
clientAuth="false" sslProtocol="TLS"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256"
compression="on"
compressableMimeType="text/html,text/xml,text/plain,
application/json,application/javascript" />
Restart Tomcat:
$ cd $CATALINA_HOME/bin
$ ./shutdown.sh
$ ./startup.sh
Verify the port is listening:
$ netstat -tlnp | grep 8443
tcp6 0 0 :::8443 :::* LISTEN 12345/java
Step 4 – Redirect All HTTP Traffic to HTTPS
Drop the following <security-constraint> into every web application’s WEB-INF/web.xml (or in $CATALINA_BASE/conf/web.xml to apply globally).
<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>
Restart the application; requests to http://localhost:8080/myapp now receive a 302 redirect to https://localhost:8443/myapp.
Step 5 – Automate Certificate Renewal (Let’s Encrypt)
If you chose Let’s Encrypt, certificates expire every 90 days. Use certbot in --csr mode or the acme.sh client; both can deploy a PKCS12 bundle into a running Tomcat without downtime.
Example acme.sh hook snippet:
--reloadcmd "cd \$CATALINA_HOME/bin && ./shutdown.sh && sleep 3 && ./startup.sh"
Keep the renewal hook inside a systemd timer or cron job.
Quick Troubleshooting Checklist (Just In Case)
| Symptom | Most common cause | Fix |
|---|---|---|
| ERR_SSL_VERSION_OR_CIPHER_MISMATCH | Weak/old cipher list | Upgrade JDK & restrict ciphers to TLS 1.2+ |
| Certificate not trusted | Imported only server cert, not full chain | Import CA + intermediates before server cert |
| Port 8443 connection refused | Connector commented out or wrong protocol | Uncomment Nio connector and restart |
| Redirect loop | Proxy in front doing SSL offloading | Set scheme="https" inside Tomcat RemoteIpValve |
Hardening Tips for Production
- Disable weak protocols – add
sslEnabledProtocols="TLSv1.2,TLSv1.3" - Enable HSTS – let the browser remember to always use HTTPS
- Use HTTP/2 – Tomcat 9+ supports it out of the box on Nio+TLS
- Offload at reverse proxy? (Nginx, HAProxy) – still keep a backend-TLS connector or at least use
REMOTE_IPvalve for correct scheme - Guard your keystore –
chmod 600 ankurm.jks; chown tomcat:tomcat ankurm.jks
Summary
Enabling HTTPS on Apache Tomcat boils down to:
- Create a keystore with
keytool - Install a certificate (self-signed for development, public CA for production)
- Add an
<Connector>on port8443inserver.xml - Force SSL via
<security-constraint>inweb.xml - Automate renewal if you use short-lived certificates
Once in place all browser traffic is encrypted, cookies and credentials travel safely, and compliance checklists get their mandatory green tick. Bookmark this guide and repeat the renewal steps every 90 days—or script them away and never think about TLS again.