Validation of required challenges (fix?)

I believe I know what the issue is but… I have a cert working for the site so it must have worked at some time.

I tried the site (nice) for and it seems to indicate that I need and don’t have anything listening to port 80. Is that the case? I’m only listening on 443. The browser returns a simple confirmation page so the service is up and running.

This is a little service I wrote using ExpressJS do I just need to return something (anything) on port 80?


OK I added a service on port 80 and it now passes the test. But simply returning a string doesn’t seem to make the renewal service happy. I get a sense it didn’t return the expected response. What is the simplest implementation that satisfies that? Thanks.

The key authorization file from the server did not match this challenge.

well it gets this now using Test: Could not verify URL is accessible:

I see the folder there isn’t anything in it but I imagine that happens magically because I never pointed any other site at the folder. Now I am getting too many failed attempts.

too many failed authorizations recently: see Failed Validation Limit - Let's Encrypt

If you’re using default web/http validation… then the validation has to happen with port 80. This is Let’s Encrypt’s requirement, rather than Certify. If port 80 forwards to HTTPS/443 or any other port… it will be happy enough as long as the challenge is met.

When Certify makes the certificate request to Let’s Encrypt, the API tells Certify to create a file with a specific(random) name with specific(random) contents. This is the challenge. It proves that you control the webserver on port 80. If necessary, Certify can spin up its own webserver to meet this challenge on port 80.

As you’ve discovered, you met the hourly(?) rate limit on Let’s Encrypt. Wait a bit and try again.

If you find port 80 validation to be an issue, your other alternative is DNS validation… but this requires you can programmatically control your domain’s DNS entries. If you can’t manage that, you can redirect DNS entries to a service that can… but that’s another topic that I have not done myself.


Hi Tom,

Yes so domain validation requires either HTTP validation (via TCP port 80) or DNS validation (by updating an _acme-challenge record in your domains DNS.

Even if you don’t have an http listener on port 80, if you are running Certify The Web on that machine then Certify can answer for you as long as nothing else is consuming port 80 (it knows how to share with IIS but other service types like node etc don’t allow that). By default Certify will start up a temporary http challenge listener (this can be enabled/disabled under the app Settings section) during validation. If you have been using this and it’s stopped working then that sometimes means a reboot would be helpful.

So to be clear, you do not strictly need IIS or other http port 80 listener to complete http validation using Certify. IIS is used as a fallback if present.

Beyond that, http validation can also be completed by specifying the web root for files so that your server (whatever it is) can serve the http challenge response files form the ./well-known/acme-challenge/ path. This sometimes need special configuration on your web server to allow the file to be served (as an extension-less text file).

The configcheck file that we use in the Test is something our challenge response service offers by default (and we write out to disk if using a web server instead). It provides a basic diagnostic (extensionless) text file with a known name for easy testing to confirm the challenge response path is reachable externally.

For DNS validation, you are using Cloudflare for your domains DNS and this is also pretty easy to setup. The API token method is the easiest and you can restrict it’s scope to a single domain etc: Cloudflare DNS | Certify The Web Docs - once setup the app can update the TXT record for you in your DNS and you don’t have to do anything else for future renewals.

If you are testing to figure out validation and want to avoid rate limits you can add a Let’s Encrypt Staging account under Settings > Certificate Authorities> Add Account (set Staging on the Advanced tab). Then on the managed certificate itself set Certificate > Advanced > Certificate Authority to Let’s Encrypt and check “Use Staging Mode”. This will use the test Let’s Encrypt system and the certificates issued will not be publicly trusted, you can then set it back to Auto when you have validation sorted out and use Request Certificate to get a valid cert again.

Note also that the app supports many different other free Certificate Authorities (ZeroSSL, Google Trust, BuyPass etc), so if you ever get stuck with rate limits it’s easy to change CA - you add a CA account as above then select that CA as your preferred CA in the certificate settings. If trying out different CAs I also recommend selecting Advanced > Actions > Reset Failure Status to prevent the app attempting CA Failover as failover that can be a bit confusing if you are experimented with CA settings and the cert has already failed multiple times.

As you are using Express JS you will then also need to have a Deployment Task under Tasks to Export the resulting certificate file in the format you require (usually the full chain pem file and a private key file), you perhaps have this setup already. You can also use a Stop/Start/Restart task to restart your ExpressJS app if required (or you can periodically check in your nodejs app for updated certs).

I seem to be a bit further ahead BUT… it’s always something. I’m not using IIS (which I may have been using when I first got the cert) so that might explain why I have a valid cert now but cannot renew it.

Using ExpressJs (not my first choice) but it’s working. I added a path to the .well-known/acme-challenge folder on both port 443 and 80. I dropped a test.html file into it and I can access it via the website on either port. I had to permit dotFiles access (on Express) which I have and it is working.

For a confirmation test I created another folder “Test” told Express it can use it for static files also and that worked. So static files from alternate folders is enabled.

At this point I’m guessing that the Http Challenge Server is interfering. I tried turning it off but received the same error about the URL being inaccessible (I’m using the Test option). If I disable the challenge server that’s for all certificates which isn’t ideal. Only this one site is on a non-IIS server.

I’m going to reboot the server but I don’t believe it will have any affect in this case.

No change as expected. Could not verify URL is accessible:

Tried setting the Site Root Directory (same error). Tried unchecking “Perform challenge response config checks” but that seems to be a requirement. Tried unchecking “Perform web application auto config” (same error).

Seems to generate a 404 (Forbidden) error if that is any clue. Possibly the filename is the issue?

Oh I see 2 files that weren’t there before. configCheck which confirms files without an extension (it seems) and web.config which contains settings that I’m pretty certain are IIS-specific and won’t have any affect in this case.

And via my browser using http I was able to access the configCheck file so files definitely serve up from there.

Yes if you can get your existing server to serve the configcheck file that Certify is writing out then your http validation will work.

If you already have a process listening on port 80 the Certify Http Challenge Process won’t even start listening because it won’t be able to bind the port, this will be logged as Http Challenge Server Unavailable in the log file.

You mentioned about “all certificates” - you only have one port 80 on your server. So only IIS (technically http.sys) or Node/ExpressJS can use that, node doesn’t know how to share. Do you intend to have multiple IIS sites AND ExpressJS on the same server? I’m not sure that’s practical without using reverse proxying from IIS or using unconventional ports on ExpressJS.

Not sure if you end up solving your problem or not? If not, please state what you currently see.

Hi again and thanks. I have multiple IP addresses on the server and have it set up so IIS is servicing a few of them and ExpressJS is running as a server on one. I was unable to get IIS to host one particular node service correctly so I made it standalone and it works fine. IIS serves up status pages to let me know the services are running and the same occurs with the ExpressJS service. I only had it listening on 443 but due to the requirement of using port 80 I added that now.

I can see the status webpage being returned from the service whether I use http or https. At the moment it works like I suppose that it should. If I can get the status page returned and Let’s Debug thinks it looks good I’m at a loss to figure out where the issue is.

Could CTW be writing the file into the wrong folder? Maybe a permissions thing?

1 Like

What do you mean by “status page”? Regarding letsdebug, it’s just checking your site can be accessed via http but it doesn’t know if the challenge response file is being served correctly or not.

For certify writing to challenge out, it uses the path set under Authorization > http > Site Root Directory as the place where it will expect to create the ./well-known directory. You should see this happen when you click “Test” as well.

Screenshot 2023-09-20 232346

This is what I get when I run the test with the server enabled. I see configcheck appear when I check the other certs (sites hosted on IIS). I don’t see it on the one in question which I assume is the source of the failure.

well I had that set to discover… I have set it to the root folder and configcheck and web.config appear in the acme-challenge folder.

By status page I only meant a simple html file that tells me the service is running. And I placed one in the acme-challenge folder and that is served up as well when requested.

Screenshot 2023-09-20 233500

When I uncheck the option to run the Challenge Server I got the following. Something about the Application Pool which shouldn’t be applicable. Any chance this only works with IIS?

No, people use this with Apache and nginx etc fairly regularly. The auto discovery thing only knows about IIS and is using the IIS site selected in the first tab dropdown. As you are not using IIS for this site you should probably set that to “No Site Selected” and manually provide the domains.

The test can fail locally if the local machine is unable to resolve that URL (even if the URL is publicly accessible), so the real test is still to use Request Certificate.

If you put a text file called ‘test’ (with no .txt extension) under /.well-known/acme-challenge/ can you leave it there and I’ll check if I can access that?

Can you explain (in simple terms) the challenge once again. Clearly CTW is writing a file into the acme-challenge. Is something ultimately requesting that file? Without intervention on my part ExpressJS wouldn’t be serving files out of there. I have placed the folder as being able to serve static files however.

I had “No Site Selected” but I didn’t have the domain to add. I added that now and I got the same error.

I ran the Request. I saw the test file appear in the folder. I got an error and the file was removed. It is generating a 404 error.

404 [Forbidden :: urn:ietf:params:acme:error:unauthorized]

Before I go into detail that may not help, can you humor me by manually creating your own ‘test.txt’ file text file with the content “OK” under your website in the ./well-known/acme-challenge path? Then rename the file to just “test” instead of “test.txt” - in Windows Explorer you need to show file extensions to do that rename.

I (and you) should then be able to get to it as

This would prove:

  • the files are being written to the expected path
  • extensionless text files work and are served as text
  • that the 404 handler for Express is not intercepting the request
  • that externally the IP bound for Express is OK

test.txt worked but test (no extension) made MSS Edge offer to download it instead.

I think that is a setting on ExpressJS… making the modification now