Just recently, I started seeing problems where one Let's Encrypt certificate
was not being renewed by acme-client.

Digging around the issue after waiting a few days to see if the issue as
temporal, I found that the temporary file set by acme-client in
/var/www/acme/ is not available when Let's Encrypt checks for it; instead,
httpd is generating a 404.

I'm running 7.9

$ uname -a
OpenBSD www 7.9 GENERIC#8 amd64

Relevant portions of /etc/acme-client.conf
------------------------------------------

authority letsencrypt-staging { 
api url "https://acme-staging-v02.api.letsencrypt.org/directory";
account key "/etc/acme/letsencrypt-staging-privkey.pem" } 

domain www.example.com {
 domain key "/etc/ssl/private/www.example.com.key.pem"
 domain full chain certificate "/etc/ssl/certs/www.example.com.chain.pem"
 sign with letsencrypt-staging
}


Relevant parts of httpd.conf
----------------------------

server "www.example.com" {
  alias "www2.example.com"
  listen on 203.0.113.1   port 80
  listen on 3fff:a:b::2 port 80
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
    pass
  }
  block return 301 "https://$HTTP_HOST$REQUEST_URI";
}


Here is a breakdown of the transaction; running acme-client shows the error:

# acme-client -v www.example.com
acme-client: https://acme-staging-v02.api.letsencrypt.org/directory: directories
acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 172.65.46.172
acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 
2606:4700:60:0:f41b:d4fe:4325:6026
acme-client: account key: 
https://acme-staging-v02.api.letsencrypt.org/acme/acct/999999999
acme-client: dochngreq: 
https://acme-staging-v02.api.letsencrypt.org/acme/authz/999999999/4323610543
acme-client: challenge, token: 0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ, 
uri: 
https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ,
 status: 0
acme-client: /var/www/acme/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ: created
acme-client: 
https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ:
 challenge
acme-client: order.status 0
acme-client: dochngreq: 
https://acme-staging-v02.api.letsencrypt.org/acme/authz/999999999/4323610543
acme-client: challenge, token: 0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ, 
uri: 
https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ,
 status: 0
acme-client: /var/www/acme/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ: created
acme-client: 
https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ:
 challenge
acme-client: 
https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ:
 bad HTTP: 409
acme-client: transfer buffer: [{
  "type": "urn:ietf:params:acme:error:conflict",
  "detail": "Unable to update challenge :: failed to mark authz as processing: 
Authorization is already being validated. This may indicate your client 
attempted the same challenge multiple times, possibly due to a client bug.",
  "status": 409
}] (296 bytes)
acme-client: bad exit: netproc(58779): 1


Looking at the output that LE provides at the following URL shows an HTTP
404 when trying to fetch the challenge file.
<https://acme-staging-v02.api.letsencrypt.org/acme/authz/999999999/4322736873>

{
  "identifier": {
    "type": "dns",
    "value": "www.example.com"
  },
  "status": "invalid",
  "expires": "2026-09-10T14:03:56Z",
  "challenges": [
    {
      "type": "http-01",
      "url": 
"https://acme-staging-v02.api.letsencrypt.org/acme/chall/999999999/4323610543/MtUOoQ";,
      "status": "invalid",
      "validated": "2026-09-03T14:03:57Z",
      "error": {
        "type": "urn:ietf:params:acme:error:unauthorized",
        "detail": "203.0.113.1: Invalid response from 
http://www.example.com/.well-known/acme-challenge/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ:
 404",
        "status": 403
      },
      "token": "0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ",
      "validationRecord": [
        {
          "url": 
"http://www.example.com/.well-known/acme-challenge/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ";,
          "hostname": "www.example.com",
          "port": "80",
          "addressesResolved": [
            "3fff:a:b::2",
            "203.0.113.1"
          ],
          "addressUsed": "3fff:a:b::2"
        },
        {
          "url": 
"http://www.example.com/.well-known/acme-challenge/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ";,
          "hostname": "www.example.com",
          "port": "80",
          "addressesResolved": [
            "3fff:a:b::2",
            "203.0.113.1"
          ],
          "addressUsed": "203.0.113.1"
        }
      ]
    }
  ]
}

So there is definitely a 404 occuring, but the file DOES exist in
/var/www/acme/ (as shown during the time of the transaction)

# find /var/www/acme -ls
155520    4 drwxr-xr-x    2 root     daemon        512 Sep  3 09:03 
/var/www/acme
155521    4 -r--r--r--    1 root     daemon         87 Sep  3 09:04 
/var/www/acme/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ


/var/www/logs/access.log shows the HTTP 404 being served.

www.example.com 66.133.109.36 - - [03/Sep/2026:09:04:07 -0500] "GET 
/.well-known/acme-challenge/0qew5-cCl8MYLRX1I58Ald50lxppE4yM0RZy-aeJRUQ 
HTTP/1.1" 404 0


Is anyone else experiencing this issue? What have you done to work around it?

Thanks in advance.

Reply via email to