Apache Reverse Proxy and Certbot SSL: A Troubleshooting Experience
Recently, I set up my web applications behind an Apache reverse proxy with SSL provided by Certbot. I faced several challenges along the way—from conflicting default pages to browser caching issues—and I want to share my experience and final solution to help anyone facing similar problems.
Background
I had two internal applications that I needed to expose securely:
- dify.ruianding.com: My application running on an internal port
27360
needed to be reverse proxied to this domain on port 443. - json.ruianding.com: Another application running on port
8888
should be accessible via this domain on port 443, with all requests automatically redirected from the root to/editor
.
Note: My applications are running inside Docker containers on my local client machine. I use Apache as a reverse proxy to forward requests from these containers to the public domain, enhancing security by not exposing container ports directly.
Initially, I used FRP to map internal ports to public ports, but to enhance security, I decided to only expose the applications through Apache reverse proxy and handle SSL with Certbot.
The Issues I Encountered
1. Apache Default Page Conflict
When I first configured Apache for dify.ruianding.com, I encountered an unexpected behavior: despite having a custom reverse proxy configuration, accessing the domain still showed Apache’s default page.

Investigation:
- I discovered that Certbot automatically generated a default virtual host configuration file (
dify-le-ssl.conf
) for SSL, which did not include the reverse proxy settings. - My custom configuration (
dify.conf
) also existed, but Apache was prioritizing the default certbot-generated config.

2. Browser Caching Problems
After making adjustments to disable the default site, I still couldn’t see the correct page on my desktop browser. Switching to my phone revealed the intended content.
Conclusion:
- The issue was ultimately due to browser cache. Clearing the cache or using an incognito window resolved the problem.
3. Concerns about Certbot Renewal
I was also worried that by disabling the Certbot default virtual host, the certificate renewal process might fail.
Finding:
- Certbot relies on the ACME challenge response. As long as a correctly configured virtual host for the domain exists (i.e., one that handles the
/.well-known/acme-challenge/
requests), renewal proceeds without issue.
Final Solution and Configuration
A. Configuring dify.ruianding.com
I merged the necessary reverse proxy directives into the SSL virtual host configuration. For example, my final /etc/apache2/sites-enabled/dify-le-ssl.conf
looked like this:
<IfModule mod_ssl.c> <VirtualHost *:443> ServerName dify.ruianding.com SSLEngine on SSLCertificateFile /etc/letsencrypt/live/dify.ruianding.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/dify.ruianding.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # Reverse proxy configuration: forward requests to internal port 27360 ProxyPreserveHost On ProxyPass / http://127.0.0.1:27360/ ProxyPassReverse / http://127.0.0.1:27360/ </VirtualHost> </IfModule>
I ensured that the necessary Apache modules were enabled:
sudo a2enmod proxy proxy_http ssl rewrite sudo systemctl reload apache2
B. Configuring json.ruianding.com with a Redirection to /editor
For json.ruianding.com, I created a separate virtual host file (e.g., /etc/apache2/sites-enabled/json.ruianding.com.conf
) with both HTTP and HTTPS configurations:
<VirtualHost *:80> ServerName json.ruianding.com # Redirect HTTP to HTTPS RewriteEngine On RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </VirtualHost> <VirtualHost *:443> ServerName json.ruianding.com SSLEngine on SSLCertificateFile /etc/letsencrypt/live/json.ruianding.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/json.ruianding.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # Redirect root requests to /editor RewriteEngine On RewriteCond %{REQUEST_URI} ^/$ RewriteRule ^/?$ https://%{HTTP_HOST}/editor [R=301,L] # Reverse proxy configuration: forward requests to internal port 8888 ProxyPreserveHost On ProxyPass / http://127.0.0.1:8888/ ProxyPassReverse / http://127.0.0.1:8888/ ErrorLog ${APACHE_LOG_DIR}/json_error.log CustomLog ${APACHE_LOG_DIR}/json_access.log combined </VirtualHost>
C. Using Certbot for SSL Certificates and Auto-Renewal
1. Install Certbot and Apache Plugin
sudo apt update sudo apt install certbot python3-certbot-apache
2. Obtain SSL Certificates
Run the following command for each domain. For example, for json.ruianding.com:
sudo certbot --apache -d json.ruianding.com
During the process, you’ll be prompted to enter your email, agree to the terms, and choose whether to redirect HTTP to HTTPS (choose to redirect).
3. Test Auto-Renewal
After obtaining the certificates, test the auto-renewal process:
sudo certbot renew --dry-run
If the test runs successfully, Certbot will handle certificate renewals automatically.
Conclusion
In summary, I resolved the issues by:
- Disabling the unwanted Certbot-generated default virtual host to ensure the custom reverse proxy configuration was used.
- Clearing browser cache to see the updated content.
- Verifying that disabling the default page did not affect the Certbot renewal process, as the active virtual host correctly handled the ACME challenges.
This experience taught me the importance of carefully managing virtual host configurations and remembering that sometimes the simplest issues—like browser caching—can cause a lot of headaches. I hope this blog post helps others in navigating similar challenges when setting up Apache reverse proxies with Certbot SSL.