Certbot fails renewal with http-01 challenge on NGINX: Connection refused

dub 14 2019

The problem

This has been bothering me for more than half of a year. You might be unable to automatically renew certificates if the following conditions are true:

  • You're using the python-certbot-nginx plugin to install certificates and handle their renewal on your webserver.
  • You're using different location for acme-challenge than the actual folder inside installation root - this is most likely if you're using NGINX as a proxy for a different service.

During the renewal process you will most likely receive the following error:

Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Failed authorization procedure. example.com (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching https://www.example.com/.well-known/acme-challenge/1hDMJJfjSOPJENxVmuXdDiphrVlEgRGXfHWB7Z8: Connection refused

However testing the connection with curl or wget from any location predictably gives just a 404 error. To fix it, I had to delete the old certificate configuration and reinstall it with the certbot-nginx plugin each time. This would allow http-01 challenge to pass successfully.

After pulling my hair for a while and playing with the --dry-run option, I've finally noticed the following message:

Plugins selected: Authenticator webroot, Installer nginx

This is wrong. It should be:

Plugins selected: Authenticator nginx, Installer nginx

The reason for the failure appears to be the alternate acme-challenge folder location. Webroot authenticator doesn't handle it and it will attempt to verify using regular sub-folder in webroot.

The solution

Open /etc/cron.d/certbot file and add --nginx option to the renew command, the python-certbot-nginx should be adding it automatically but it doesn't.