Let's Encrypt SSL with Apache (Reverse Proxy) + Tomcat using win-acme
Objective
Secure a website (example.com
) served by Tomcat (port 8080) through an Apache reverse proxy on Windows using a free Let's Encrypt SSL certificate generated by win-acme.
Prerequisites
Domain name pointing to your public IP.
Apache (XAMPP) installed and running on port 80.
Tomcat server running on port 8080.
win-acme
ACME client (https://www.win-acme.com/).
Apache Virtual Host Configuration (Port 80)
<VirtualHost *:80>
ServerName example.com
# Serve ACME challenge
Alias /.well-known/acme-challenge/ "C:/xampp/.well-known/acme-challenge/"
<Directory "C:/xampp/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
# Prevent proxying of ACME challenge
ProxyPassMatch ^/.well-known !
# Reverse proxy to Tomcat
ProxyPreserveHost On
ProxyPass /exampledept/ http://localhost:8080/exampledept/
ProxyPassReverse /exampledept/ http://localhost:8080/exampledept/
ProxyPass / http://localhost:8080/exampledept/
ProxyPassReverse / http://localhost:8080/exampledept/
ErrorLog "logs/example.com-error.log"
CustomLog "logs/example.com-access.log" common
</VirtualHost>
win-acme Manual Validation Setup
Run
wacs.exe
and chooseM
(Full Options).Select manual input of domain:
example.com
Choose HTTP validation method:
Save verification files on (network) path
Path for challenge files:
C:\xampp\
(No need to mention .well-known/acme-challenge)Choose to skip
web.config
copy.Choose key type:
RSA
Output format:
PEM files
Output directory:C:\example_ssl
Skip additional installation or bindings steps.
Validation Troubleshooting (Optional)
Ensure the ACME challenge file is directly accessible at:
http://example.com/.well-known/acme-challenge/<token>
If you see 404s, verify:
Apache is not proxying
.well-known
paths.Challenge file exists in
C:/xampp/.well-known/acme-challenge/
.No Tomcat redirection is interfering with validation.
Installing SSL
Apache Virtual Host Configuration (Port 443)
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile "C:/xampp/ssl/cert.pem"
SSLCertificateKeyFile "C:/xampp/ssl/key.pem"
SSLCertificateChainFile "C:/xampp/ssl/chain.pem"
# Serve .well-known/acme-challenge locally (optional, for renewal)
Alias /.well-known/acme-challenge/ "C:/xampp/.well-known/acme-challenge/"
<Directory "C:/xampp/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
ProxyPreserveHost On
ProxyPass /exampledept/ http://localhost:8080/exampledept/
ProxyPassReverse /exampledept/ http://localhost:8080/exampledept/
ProxyPass / http://localhost:8080/exampledept/
ProxyPassReverse / http://localhost:8080/exampledept/
ErrorLog "logs/example-ssl-error.log"
CustomLog "logs/example-ssl-access.log" common
</VirtualHost>
Final Steps
Restart Apache and Tomcat.
Access your secure site via:
https://example.com/exampledept/
(Optional) Setup a scheduled task or cron for renewal with win-acme.
(Optional but Recommended) Force HTTPS Redirect
In your current port 80 VirtualHost, add this to redirect users to HTTPS:
<VirtualHost *:80>
ServerName example.com
# Redirect everything to HTTPS
Redirect permanent / https://example.com/
# Keep acme challenge local (optional for renewal)
Alias /.well-known/acme-challenge/ "C:/xampp/.well-known/acme-challenge/"
<Directory "C:/xampp/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
ErrorLog "logs/example.com-error.log"
CustomLog "logs/example.com-access.log" common
</VirtualHost>
Last updated
Was this helpful?