Complete Guide to Enabling HTTPS on Apache Tomcat

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)

SymptomMost common causeFix
ERR_SSL_VERSION_OR_CIPHER_MISMATCHWeak/old cipher listUpgrade JDK & restrict ciphers to TLS 1.2+
Certificate not trustedImported only server cert, not full chainImport CA + intermediates before server cert
Port 8443 connection refusedConnector commented out or wrong protocolUncomment Nio connector and restart
Redirect loopProxy in front doing SSL offloadingSet 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_IP valve for correct scheme
  • Guard your keystore – chmod 600 ankurm.jks; chown tomcat:tomcat ankurm.jks

Summary

Enabling HTTPS on Apache Tomcat boils down to:

  1. Create a keystore with keytool
  2. Install a certificate (self-signed for development, public CA for production)
  3. Add an <Connector> on port 8443 in server.xml
  4. Force SSL via <security-constraint> in web.xml
  5. 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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.