Let's encrypt unable to renew

My certificate does not want to renew with Let’s encrypt.

sudo certbot certonly --dry-run  --webroot -w /srv/www/htdocs/mydomain -d "www.mydomain.ca" 
[sudo] password for root: 
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Simulating a certificate request for www.mydomain.ca

Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
  Domain: www.mydomain.ca
  Type:   unauthorized
  Detail: 2a02:c206:2104:354::1: Invalid response from http://www.mydomain.ca/.well-known/acme-challenge/0C9WNMVOdTU2sXMJ__XY7olXz8oNtaemwhY5wQv9A0Y: 400

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.

Some challenges have failed.
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.

I’m trying to resolve this issue by debugging it using curl:

url -LI http://www.mydomain.ca
HTTP/1.1 301 Moved Permanently
Date: Thu, 10 Apr 2025 22:15:25 GMT
Server: Apache
Location: https://www.wrongsite.com/error/HTTP_BAD_REQUEST.html.var
Content-Length: 267
Connection: close
Content-Type: text/html; charset=iso-8859-1

HTTP/1.1 200 OK
Date: Thu, 10 Apr 2025 22:15:25 GMT
Server: Apache
Vary: accept-language,accept-charset
Strict-Transport-Security: max-age=31536000;
Upgrade: h2,h2c
Connection: Upgrade
Accept-Ranges: bytes
Content-Type: text/html; charset=utf-8
Content-Language: en

And does shows that firstly wrongsite is accessed. But mydomain is configured to with a vhost file for port 80 and a vhost for port 443. The vhost for port 80 is only redirecting traffic to 443:

<VirtualHost www.mydomain.ca:80>
    ServerName www.mydomain.ca
    ServerAlias mydomain.ca

    Redirect / https://%{SERVER_NAME}
</VirtualHost>

When accessing the domain in the browser this works as expected.

I’m lost as to why wrongsite is used with curl (though that explains why LE is not working).

Is your router properly forwarding to your host? (That’s an easy thing to check, but also an easy thing to miss when using that particular challenge type.)

Depending on who your DNS provider is, you might change to using the DNS challenge rather than the .well-known endpoint. I use AWS’ Route53 myself, and moved to the DNS challenge a couple years ago, and never looked back.

It’s always challenging to diagnose things like this on the local network - if you can try from a device off-network (even using a mobile phone that’s not on your wifi network), that migth help identify what the issue is.

This is not a home server. I have tried in the past the DNS challenge, but that was not a success. I can look into that again…

Home server or not, I’d still look at the port forwarding from the internet-facing routing system. If there’s a reverse proxy in front of the server (behind the router/in your DMZ), make sure it’s not restricting access to the .well-known endpoints as well. If they’re not accessible from outside the network the web server is in, that’ll break it.

The DNS challenge option does require that certbot be able to modify records in the zone.

I’m one step further. I found a configuration issue in one of my vhosts file. I have resolved that by removing those lines and I updated my redirect in my vhost file providing the issue. Now curl is resolving nicely, but Let’s Encrypt is still giving issues.

I don’t have a proxy, just straight Apache. I created a test.html: .well-know/acme-challenge/test.html
That file is accessible when I go directly to the URL. I tried the dry-run again on the domain and the log returns a status 403. It is not allowed to write. I’m running certbot as root user and the challenge directory’s owner is wwwrun:www with 755 as permissions.

Should the permission/ owner be different?

Root should be able to create files just fine - with your test.html file, did you set the ownership/permissions to the same as other files, or as root?

Might be worth trying setting the ownership/permissions the same as other files owned by wwwrun just to rule that out.