Overview
This guide explains how to configure Apache HTTP Server to proxy requests to VT Docs Tomcat over an encrypted TLS connection. This is recommended when Apache and Tomcat are running on separate servers to ensure secure communication between the web server and application server.
Prerequisites
- VT Docs successfully installed and running (see How to Deploy VT Docs on Red Hat 9)
- Apache HTTP Server installed with mod_ssl and mod_proxy modules enabled
- Root or sudo access on both the Apache server and VT Docs Tomcat server
- Basic understanding of SSL/TLS certificates
Note: This guide assumes Apache is handling client-facing SSL/TLS (port 443) and focuses on securing the backend connection between Apache and Tomcat.
Architecture
Client --HTTPS--> Apache Server (443) --HTTPS--> VT Docs Tomcat Server (8080)
Step 1: Generate a Keystore and Certificate for Tomcat
VT Docs uses a Spring Boot Tomcat server, which supports multiple keystore formats:
- PKCS12 (.p12, .pfx) - Recommended, cross-platform standard
- JKS (Java KeyStore) - Legacy Java format
- PEM (.pem, .crt, .key) - Supported in modern Spring Boot versions
Option A: Create a Self-Signed Certificate (for internal/testing)
Generate a PKCS12 keystore with a self-signed certificate:
keytool -genkeypair -alias tomcat \ -keyalg RSA -keysize 2048 -validity 365 \ -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 \ -storepass changeit \ -dname "CN=vtdocs.example.com,OU=IT,O=YourCompany,L=City,ST=State,C=US"
Note: Replace vtdocs.example.com with your VT Docs server hostname and update the password (changeit).
Option B: Use an Existing Certificate (CA-signed or from internal CA)
If you have a certificate from a Certificate Authority or internal CA, you'll need to import it into a keystore.
If you have PEM files (certificate + private key + chain):
# If chain certificates are in separate files, combine them first # Order: your certificate, intermediate cert(s), root cert cat /path/to/certificate.crt /path/to/intermediate.crt /path/to/root.crt > /tmp/fullchain.pem # Create PKCS12 keystore with the full certificate chain openssl pkcs12 -export \ -in /tmp/fullchain.pem \ -inkey /path/to/private-key.key \ -out /opt/visiblethread/certs/keystore.p12 \ -name tomcat \ -passout pass:changeit # Clean up temporary file rm /tmp/fullchain.pem
Note: The -certfile option can also be used if your chain is in a separate file:
openssl pkcs12 -export \ -in /path/to/certificate.crt \ -inkey /path/to/private-key.key \ -certfile /path/to/ca-chain.crt \ -out /opt/visiblethread/certs/keystore.p12 \ -name tomcat \ -passout pass:changeit
If you need to add chain certificates to an existing keystore:
# Import intermediate certificate keytool -import -trustcacerts -alias intermediate1 \ -file /path/to/intermediate.crt \ -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 \ -storepass changeit # Import root certificate keytool -import -trustcacerts -alias root \ -file /path/to/root.crt \ -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 \ -storepass changeit
Verify the certificate chain:
keytool -list -v -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 -storepass changeit | grep -A 5 "Certificate chain length"
You should see "Certificate chain length: X" where X is the number of certificates in your chain (typically 2-3).
If you have a .pfx or .p12 file, you can use it directly or convert to JKS:
# Use PKCS12 directly (recommended) cp /path/to/existing.p12 /opt/visiblethread/certs/keystore.p12 # OR convert to JKS if needed keytool -importkeystore \ -srckeystore /path/to/existing.p12 -srcstoretype PKCS12 \ -destkeystore /opt/visiblethread/certs/keystore.jks -deststoretype JKS
Set Proper Permissions
sudo chown visiblethread:visiblethread /opt/visiblethread/certs/keystore.p12 sudo chmod 600 /opt/visiblethread/certs/keystore.p12
Step 2: Export Certificate for Apache to Trust
Apache needs to trust the Tomcat certificate. Export the certificate from the keystore in PEM format:
keytool -export -alias tomcat \ -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 \ -storepass changeit \ -rfc \ -file /opt/visiblethread/certs/tomcat.crt
Important: The -rfc flag exports the certificate in PEM format, which Apache requires.
Verify the certificate is in PEM format:
cat /opt/visiblethread/certs/tomcat.crt
You should see -----BEGIN CERTIFICATE----- at the beginning.
If Apache and Tomcat are on separate servers, copy this certificate file to your Apache server:
scp /opt/visiblethread/certs/tomcat.crt user@apache-server:/etc/pki/tls/certs/
Step 3: Configure VT Docs Tomcat to Use TLS
VT Docs uses a traditional Tomcat deployment. SSL must be configured in Tomcat's server.xml file.
Edit the Tomcat server configuration:
sudo vi /opt/visiblethread/tomcat/conf/server.xml
Find the <Connector port="8080" section and replace it with an HTTPS connector:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200" SSLEnabled="true" scheme="https" secure="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="/opt/visiblethread/certs/keystore.p12"
certificateKeystorePassword="changeit"
certificateKeystoreType="PKCS12"
type="RSA" />
</SSLHostConfig>
</Connector>
Alternative: Using PEM files directly (if you prefer not to use a keystore):
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200" SSLEnabled="true" scheme="https" secure="true">
<SSLHostConfig>
<Certificate certificateFile="/opt/visiblethread/certs/certificate.crt"
certificateKeyFile="/opt/visiblethread/certs/private-key.key"
certificateChainFile="/opt/visiblethread/certs/chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
Save the file and restart VT Docs:
sudo systemctl restart visiblethread-docs.service
Verify VT Docs is now listening on HTTPS:
systemctl status visiblethread-docs.service sudo ss -tlnp | grep 8080
Check the Tomcat logs to confirm SSL is enabled:
grep "https-jsse-nio-8080" /opt/visiblethread/tomcat/logs/catalina.$(date +%Y-%m-%d).log
You should see lines indicating the HTTPS protocol handler started:
INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-jsse-nio-8080"] INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-jsse-nio-8080"]
Test the HTTPS connection locally:
curl -k https://localhost:8080/getVersion.jsp
Note: The -k flag bypasses certificate verification for testing. You should see a response indicating VT Docs is running.
Step 4: Configure Apache to Proxy via TLS
On your Apache server, configure the proxy to use HTTPS when connecting to Tomcat.
Edit your Apache virtual host configuration (typically in /etc/httpd/conf.d/vtdocs.conf or /etc/httpd/conf.d/visiblethread.conf):
<VirtualHost *:443>
ServerName vtdocs.example.com
# Client-facing SSL configuration
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/vtdocs-public.crt
SSLCertificateKeyFile /etc/pki/tls/private/vtdocs-public.key
SSLCertificateChainFile /etc/pki/tls/certs/vtdocs-chain.crt
# Enable SSL proxy engine
SSLProxyEngine On
# Trust the Tomcat backend certificate
SSLProxyCACertificateFile /opt/visiblethread/certs/tomcat.crt
# Verify the backend certificate
SSLProxyVerify require
SSLProxyCheckPeerName on
# Proxy configuration
ProxyPreserveHost On
ProxyPass / https://vtdocs-backend.example.com:8080/
ProxyPassReverse / https://vtdocs-backend.example.com:8080/
# Headers for proper forwarding
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
# Logging
ErrorLog /var/log/httpd/vtdocs_error.log
CustomLog /var/log/httpd/vtdocs_access.log combined
</VirtualHost>
Important Configuration Notes:
- SSLProxyCACertificateFile: Points to the Tomcat certificate exported in Step 2. This tells Apache to trust the backend certificate.
- SSLProxyVerify require: Enforces certificate verification for security. This prevents man-in-the-middle attacks.
- SSLProxyCheckPeerName on: Ensures the certificate hostname matches the backend server.
- Replace
vtdocs-backend.example.comwith your actual VT Docs Tomcat server hostname.
Testing First: Disable Certificate Verification
For initial testing, you may want to temporarily disable backend certificate verification to ensure connectivity works:
SSLProxyEngine On # Temporarily disable verification for testing SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off
After confirming the connection works, re-enable certificate verification for production:
SSLProxyEngine On SSLProxyCACertificateFile /opt/visiblethread/certs/tomcat.crt SSLProxyVerify require SSLProxyCheckPeerName on
Alternative: Using a CA Certificate
If your Tomcat certificate is signed by an internal CA or public CA, you can configure Apache to trust the CA instead:
SSLProxyCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
This allows you to trust multiple backend servers signed by the same CA.
Restart Apache
sudo systemctl restart httpd sudo systemctl status httpd
Verify End-to-End Connection
From a client machine:
curl -v https://vtdocs.example.com/getVersion.jsp
You should receive a successful response from VT Docs.
Check Apache Logs
If you encounter issues, check the Apache error log:
sudo tail -f /var/log/httpd/vtdocs_error.log
Common errors:
-
Certificate verification failed: Ensure the Tomcat certificate is correctly exported and the path in
SSLProxyCACertificateFileis correct - Connection refused: Verify VT Docs Tomcat is listening on 8080 and the hostname/IP is correct
- SSL handshake failed: Check that TLS protocols match between Apache and Tomcat
Supported Certificate Formats Summary
| Format | Extension | Use Case | Tomcat Support | Apache Support |
|---|---|---|---|---|
| PKCS12 | .p12, .pfx | Modern standard, recommended | ✓ Yes | ✓ Yes |
| JKS | .jks | Legacy Java format | ✓ Yes | ✗ No |
| PEM | .pem, .crt, .key | Standard for web servers | ✓ Yes (Spring Boot) | ✓ Yes |
| DER | .der, .cer | Binary format | ✓ Yes (convert to PKCS12) | ✗ No (convert to PEM) |
Recommended approach: Use PKCS12 (.p12) format for Tomcat keystore and export to PEM format for Apache trust.
Security Best Practices
-
Use strong passwords: Replace
changeitwith a strong, unique password -
Restrict file permissions: Ensure keystore files are only readable by the
visiblethreaduser (chmod 600) - Use certificates from a trusted CA: Self-signed certificates are acceptable for internal networks but use CA-signed certificates for production
-
Enable certificate verification: Always use
SSLProxyVerify requirein production - Keep certificates up to date: Monitor expiration dates and renew certificates before they expire
- Use TLS 1.2 or higher: Disable older protocols (SSL 3.0, TLS 1.0, TLS 1.1)
- Regularly update: Keep Apache, Tomcat, and OpenSSL packages updated
Troubleshooting
VT Docs won't start after enabling TLS
Check the service logs:
sudo journalctl -u visiblethread-docs.service -f
Common issues:
-
Incorrect keystore path or password: Verify the path in
server.xmland password are correct -
Keystore file not readable: Ensure the file has proper permissions (
chmod 600) and is owned byvisiblethreaduser -
Invalid keystore format: Verify the keystore using
keytool -list -v -keystore /path/to/keystore.p12 -
Missing certificate alias: Ensure the alias specified in
server.xmlexists in the keystore
Tomcat is running but still shows "http-nio-8080" instead of "https-jsse-nio-8080"
This means SSL configuration wasn't applied. Check:
grep "ProtocolHandler" /opt/visiblethread/tomcat/logs/catalina.log
If you see http-nio-8080 instead of https-jsse-nio-8080, the SSL configuration in server.xml wasn't loaded correctly. Verify:
- The
<Connector>configuration is properly formatted XML - No duplicate Connector entries on port 8080
- The service was fully restarted after the change
Apache can't connect to Tomcat
Error: "SSL_ERROR_RX_RECORD_TOO_LONG" or "Error parsing HTTP request header"
This means Apache is trying to connect via HTTPS but Tomcat is still running HTTP. Verify Tomcat has SSL enabled:
openssl s_client -connect localhost:8080
If this fails or shows HTTP errors, Tomcat isn't running HTTPS.
Error: "AH01895: Unable to configure verify locations for client authentication"
The Tomcat certificate file isn't in the correct PEM format. Re-export with the -rfc flag:
keytool -export -alias tomcat \ -keystore /opt/visiblethread/certs/keystore.p12 \ -storetype PKCS12 \ -storepass changeit \ -rfc \ -file /opt/visiblethread/certs/tomcat.crt
Verify it's PEM format by checking for -----BEGIN CERTIFICATE----- at the top:
head -1 /opt/visiblethread/certs/tomcat.crt
Error: "AH02312: Fatal error initialising mod_ssl" or "Private key not found"
Apache can't find the client-facing SSL certificate or key file. Ensure both SSLCertificateFile and SSLCertificateKeyFile directives are present in your Apache configuration.
Certificate verification failures
Ensure the certificate exported from Tomcat matches what's configured in Apache:
openssl x509 -in /opt/visiblethread/certs/tomcat.crt -text -noout
Check the Subject and Issuer fields match your Tomcat certificate.
If using a wildcard certificate: Ensure the hostname in ProxyPass matches the certificate's CN or SAN entries. For example, if your cert is for *.visiblethread.com, use a hostname like vtdocs.visiblethread.com instead of localhost.
Testing backend TLS connection
Verify TLS is working on Tomcat from the Apache server:
openssl s_client -connect vtdocs-backend.example.com:8080 -showcerts
This should establish a connection and display the certificate chain. Press Ctrl+C to exit.
Additional Resources
- How to Deploy VT Docs on Red Hat 9
- Securing a VisibleThread customer hosted server
- Apache mod_proxy documentation: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
- Apache mod_ssl documentation: https://httpd.apache.org/docs/2.4/mod/mod_ssl.html
Need Help?
If you encounter issues not covered in this guide, please contact VisibleThread Support with:
- VT Docs version number (found in
/opt/visiblethread/tomcat/dashboard/getVersion.jsp) - Relevant log excerpts from both Apache (
/var/log/httpd/) and VT Docs (/opt/visiblethread/tomcat/logs/) - Operating system version (
cat /etc/redhat-release) - Apache version (
httpd -v) - Java version (
java -version)