How to make Tomcat allow subfolder to be written by certbot renew process?

Story:
We run an app server that needs to connect to domain ghsemarang.com. The domain is using SSL and needs to access our app. But since the website is using SSL, our app has to be turned into SSL as well under domain hms.ghsemarang.com.

Installation was successful when I used standalone and turn tomcat off. But, when I turn the tomcat on again, the renewal failed. The renewal conf was using standalone. I changed it to webroot.

I created a folder under webapps/ROOT/.well-known/acme-challange made sure it is chmod to 777 and then I add in the web.xml the following:

<servlet>
    <servlet-name>DefaultServletOverride</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
        <param-name>listings</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Add a mapping for our new default servlet -->
<servlet-mapping>
    <servlet-name>DefaultServletOverride</servlet-name>
    <url-pattern>/.well-known/acme-challenge/</url-pattern>
</servlet-mapping>
</web-app>

I was able to test and see the content of acme-challenge, but upon running dry run renewal, I was met with error message like below (404) with a hint that I need to make sure the folder are allowed to be used to save file from internet.

How do I do that with tomcat. I added both init param listing=true and readonly=false and it is still producing error. How do I allow tomcat to make my subfolder receive any file?

All helps are greatly appreciated.

My domain is: app.mydomain.com
I ran this command: certbot renew --dry-run
It produced this output:

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/hms.ghsemarang.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for hms.ghsemarang.com

Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
  Domain: app.mydomain.com
  Type:   unauthorized
  Detail: x.x.x.x: Invalid response from http://app.mydomain.com/.well-known/acme-challenge/mtYvurZuCy6IIpCRvvId7r7Sc8tdmxbZ5KyvhzThYKc: 404

Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.

Failed to renew certificate hms.ghsemarang.com with error: Some challenges have failed.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
All simulated renewals failed. The following certificates could not be renewed:
  /etc/letsencrypt/live/hms.ghsemarang.com/fullchain.pem (failure)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 renew failure(s), 0 parse failure(s)
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

My web server is (include version): Tomcat 9.0.1
The operating system my web server runs on is (include version): Ubuntu 16.04.7 LTS
My hosting provider, if applicable, is: Self hosted server behind public IP.
I can login to a root shell on my machine (yes or no, or I don't know): yes
I'm using a control panel to manage my site (no, or provide the name and version of the control panel): No. Pure conf file.
The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot): certbot 1.32.2

Hi @cinlung,

The 404 error is probably not related to file permissions, but rather to the selection of the webroot directory. As a first guess, if you really made the directory

then that would explain the problem because the one checked by the certificate authority is spelled acme-challenge (not acme-challange).

If this isn't the specific problem, then it would be worth testing: if you put a text file called (for example) test.txt in the webapps/ROOT/.well-known/acme-challenge directory on your server, is it visible with a web browser at http://ghsemarang.com/.well-known/acme-challenge/test.txt?

Until that works correctly, the validation process from the Internet won't work correctly.

Another thing to check is that the webroot you specified to Certbot with --webroot is pointing at webapps\ROOT and not at webapps\ROOT\.well-known\acme-challenge (since Certbot expects the specified webroot to be the top level content directory for the site, where it will then add /.well-known/acme-challenge).

4 Likes

Hi Schoen. Thanks for the reply.

I just found out, that the folder .well-known/acme-challenge is actually auto created by certbot. So, adding that into the conf would create the same folder inside the manually created acme-challenge. I deleted the folder and run certbot renew and it was successful, but the site is still showing old certificate. I am going to investigate further and post the result.

2 Likes

Unless expressly configured to do otherwise, certbot will only renew the cert.
Anything that uses that cert must be restarted/reloaded for it to use the new cert.

3 Likes

Thank you. I think this is the case. I will check tomorrow after I get a permit to reboot the server. I checked the cerbot certificates command it it showed the certificate is valid.

1 Like

Yes, there is no built-in Tomcat integration; so, if you're using Tomcat to serve the certificate via a JKS file or similar, you have to regenerate that file.

You can script this using Certbot's --deploy-hook option, which lets you specify a command to be run every time the certificate is renewed.

Even if you are serving the PEM certificate directly, Certbot doesn't default to telling Tomcat to reload itself (you could also script that with the --deploy-hook option).

4 Likes

You might not need to use a hammer that big - LOL
Perhaps there is a smaller one that can just reload the service.

2 Likes

Unfortunately, Tomcat doesn't support that. There is at least one open source project that extends Tomcat with certificate monitoring and reloading.

So the options are:

  • use a post-hook to reboot tomcat
  • install and configure a tomcat service to monitor ssl certs to reload as needed.
  • install a reverse proxy in front of tomcat, terminate ssl there, and proxy all traffic onto tomcat. nginx works great here, haproxy does too. i don't know if caddy has high enough performance to function here, but it may.

I strongly suggest the third option and using a proxy to terminate SSL. Tomcat is a pain to manage and using a proxy has many advantages (e.g.: it can serve static files as well, it can be used to better shape traffic, it can be used to set up downtime maintenance websites, etc)

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.