Hi William.

On 2025-11-21 (Fr.) 23:10, William Lallemand wrote:
On Fri, Nov 21, 2025 at 10:22:53PM +0100, Aleksandar Lazic wrote:
Are you sure you recompiled with the latest master version ? It does not
process the 2nd domain like if you didn't applied my fix?

Yes.
I have now done the following to be 100% sure.
Now I get another message.

acme: none.at.pem: challenge error: "Incorrect TXT record
"Vbqf5UyduQlpoKDfLbxSa3b3YljtSYOW4cxtk15Ci-w" (and 1 more) found at
_acme-challenge.none.at" (urn:ietf:params:acme:error:unauthorized) (HTTP
status code 200) Aborting.

I will delete all _acme-challenge records and wait over night that the TTL
expires and will then test it tomorrow again.
Thank you for your time and patience.


Looks like you are affected by DNS caching indeed, you should try to use a
small value for the TTL.

Yep.

I just pushed a new commit based on your feebacks which gives a bit more
details when doing the "challenge_ready" command. Might help.

Thank you.

Now I got it. :-)

> acme: none.at.pem: Successful update of the certificate.

Great work :-)

Here the logs for the archive.

```shell
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:05:17_CET /datadisk/git-repos/haproxy $
# ./haproxy -W -db -f ../haproxy_acme.cfg
[NOTICE]   (6069) : Initializing new worker (6071)
[NOTICE] (6071) : config : No certificate available for 'none.at.pem', generating a temporary key pair before getting the ACME certificate [NOTICE] (6071) : config : acme: generate account key 'DNS1.account.key' for acme section 'DNS1'.
Sharing caphdr with caphdr
Sharing caphdr with caphdr
Sharing ptrcap with ptrcap
Sharing ptrcap with ptrcap
[NOTICE]   (6071) : Automatically setting global.maxconn to 524263.
Sharing stk_ctr with caphdr
[NOTICE]   (6069) : Loading success.
acme: none.at.pem: Starting update of the certificate.
-:- [22/Nov/2025:08:05:29.428] <ACME> -/- 138/0/319/161/616 200 152 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "GET https://acme-staging-v02.api.letsencrypt.org/directory HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- -:- [22/Nov/2025:08:05:30.044] <ACME> -/- 2/0/0/157/157 200 158 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "HEAD https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- -:- [22/Nov/2025:08:05:30.202] <ACME> -/- 2/0/0/212/212 400 963 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/new-acct HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- -:- [22/Nov/2025:08:05:30.415] <ACME> -/- 2/0/0/276/276 201 991 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/new-acct HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- -:- [22/Nov/2025:08:05:30.692] <ACME> -/- 2/0/0/167/167 201 870 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/new-order HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- acme: none.at.pem: dns-01 requires to set the "_acme-challenge.none.at" TXT record to "StQiL5JrufnS8PrI1-zu2kpLm7O-Lo4qC7Yj3YBcQLQ" and use the "acme challenge_ready none.at.pem domain none.at" command over the CLI -:- [22/Nov/2025:08:05:30.859] <ACME> -/- 2/0/0/163/163 200 776 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/authz/244976483/20362691543 HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- acme: none.at.pem: dns-01 requires to set the "_acme-challenge.none.at" TXT record to "_wcHgxxgc7UodVnjkroQknQSHZKrggzFVgkt7KAk320" and use the "acme challenge_ready none.at.pem domain none.at" command over the CLI -:- [22/Nov/2025:08:05:31.023] <ACME> -/- 2/0/0/163/163 200 776 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/authz/244976483/20362691533 HTTP/1.1" 0/0000000000000000/-/-/0 -/-/- -:- [22/Nov/2025:08:07:07.654] <ACME> -/- 4/0/0/653/655 200 796 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691543/maH2Iw HTTP/1.1" 0/0000000000000000/-/-/1 -/-/- -:- [22/Nov/2025:08:07:08.310] <ACME> -/- 2/0/0/161/161 200 796 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691533/RLZYJw HTTP/1.1" 0/0000000000000000/-/-/1 -/-/- -:- [22/Nov/2025:08:07:13.473] <ACME> -/- 2/0/0/159/159 200 793 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691543/maH2Iw HTTP/1.1" 0/0000000000000000/-/-/1 -/-/- -:- [22/Nov/2025:08:07:13.633] <ACME> -/- 2/0/0/159/159 200 793 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691533/RLZYJw HTTP/1.1" 0/0000000000000000/-/-/1 -/-/- -:- [22/Nov/2025:08:07:13.792] <ACME> -/- 2/0/0/164/164 200 1370 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/finalize/244976483/28924991343 HTTP/1.1" 0/0000000000000000/-/-/1 -/-/- -:- [22/Nov/2025:08:07:16.959] <ACME> -/- 2/0/0/158/158 200 776 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/order/244976483/28924991343 HTTP/1.1" 0/0000000000000000/-/-/1 -/-/-
acme: none.at.pem: Successful update of the certificate.
-:- [22/Nov/2025:08:07:17.117] <ACME> -/- 2/0/0/159/159 200 809 - - ---- 0/0/0/0/0 0/0 {2606:4700:60:0:f41b:d4fe:4325:6026} "POST https://acme-staging-v02.api.letsencrypt.org/acme/cert/2ce549f70ae8b3593435ff9c6bd6697b2b97 HTTP/1.1" 0/0000000000000000/-/-/1 -/-/-
```

Second shell
```shell
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:03:59_CET /datadisk/git-repos/haproxy $
# echo "acme challenge_ready none.at.pem domain none.at" | socat - 
/tmp/hap-stats
2 'none.at' challenge(s) ready! All challenges ready, starting challenges validation!

alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:07:07_CET /datadisk/git-repos/haproxy $
# echo "acme status" | socat - /tmp/hap-stats
# certificate section state expiration date (UTC) expires in scheduled date (UTC) scheduled in none.at.pem DNS1 Scheduled 2026-02-20T06:08:42Z 89d 23h01m05s 2026-02-12T18:08:43Z 82d 11h01m06s

alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:07:37_CET /datadisk/git-repos/haproxy $
# admin/cli/haproxy-dump-certs -v -s /tmp/hap-stats --path /tmp
name:none.at.pem
crt:/tmp/none.at.pem
key:/tmp/none.at.pem
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:08:09_CET /datadisk/git-repos/haproxy $
# cat /tmp/none.at.pem
-----BEGIN PRIVATE KEY-----
MIG...ESE=
-----END PRIVATE KEY-----
subject=CN = *.none.at
issuer=C = US, O = (STAGING) Let's Encrypt, CN = (STAGING) Puzzling Parsnip E7
-----BEGIN CERTIFICATE-----
MIID2zCCA2GgAwIBAgISLOVJ9wros1k0Nf+ca9ZpeyuXMAoGCCqGSM49BAMDMFcx
...
gl8zxSUj6kAte504jz6wV24bCU1J7ufbnMKlnEXfIA==
-----END CERTIFICATE-----

subject=C = US, O = (STAGING) Let's Encrypt, CN = (STAGING) Puzzling Parsnip E7
issuer=C = US, O = (STAGING) Internet Security Research Group, CN = (STAGING) Pretend Pear X1
-----BEGIN CERTIFICATE-----
MIIEmzCCAoOgAwIBAgIQR1zhS092VJ8XK2pNm/t1gDANBgkqhkiG9w0BAQsFADBm
MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
ZWFyIFgxMB4XDTI0MDMxMzAwMDAwMFoXDTI3MDMxMjIzNTk1OVowVzELMAkGA1UE
BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSYwJAYDVQQD
Ex0oU1RBR0lORykgUHV6emxpbmcgUGFyc25pcCBFNzB2MBAGByqGSM49AgEGBSuB
BAAiA2IABHu5ddBGjP6Ky/vtPVXikXyYxd8+ua+vISFBc3hJ1Iz/zme8T3C7BQsc
U3WslRgVeI6c2CpEn2pB+5xb2PRVY8u8RoyrtKV7Q0gcUbQ5bMHYJc1Zubn4tcWt
+tAkzx5JoqOCAQAwgf0wDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUF
BwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSkD5QL
RGNqmamg2YxmQ7FP3LAsRjAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXD
FDA2BggrBgEFBQcBAQQqMCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5s
ZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCsGA1UdHwQkMCIwIKAeoByG
Gmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBk
ws0hFFdRM6HYbbeSV+sAX3qiH0GSQCAS3le8ZdEDw0vdLQUqNA8dYd4t2P0tjFg5
3ZVr8MFDQvP0zMyTAROT7SB4/8yG9QTWV9uQ4fMjwRh474EWvdXDMPVIw1W9FhiF
NatXQD9o6Dg3Q91puWUxMOwiux+XkpMRHpFQ/6kHC9O4whjYqvZOYZaRwg0aiAg4
SOnorJMeo2215nAsFWidfJF7WzfUQHRWsmSdJumUf6SSYl2hhB11nFTSHQG75uaG
qz27J/XSP+QiF0BBBR5iK7x2W7vOFG1UTFAredh7SAkJehlHfnNcrFLHGPvkRLb1
gW6BZH7tl2DB3auMuP5MdFytEq88HG83eerp4WRBZ8RL+R3nXDo6fCv1SMr6mzA5
lsytrmDDuWSSRsn/rSkx78h+JtDfBrAz+QAVYa7I49nKRLyhc9RjOGTGpZh2LLbi
Q09bTBIgSN14ZiCBbet8vH5c+PeDRZnBbSZrJn9Ju14m43Z1rmOOcd4VoG1wjD2X
Q3DrM3K1TMn6DWq7Ks1sb+XkoMVKqi++M4bip3PUxdNNfj+ekovaaK1JJsjEDgCp
f6V+ThZrDT72tmOYrus7oQXDglKZ2rJWON5LB/kK5Z9Nn7/uMShxuwxp5rwHf5zb
AQlfAKgotEgPQfmzftRHvTab4vAx+D2u8+NHlzitJg==
-----END CERTIFICATE-----
```

I have also triggered a renew
```shell
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:18:26_CET /datadisk/git-repos/haproxy $
# echo "acme renew none.at.pem" | socat - /tmp/hap-stats

alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:18:35_CET /datadisk/git-repos/haproxy $
# echo "acme challenge_ready none.at.pem domain none.at" | socat - 
/tmp/hap-stats
2 'none.at' challenge(s) ready! All challenges ready, starting challenges validation!

alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:19:25_CET /datadisk/git-repos/haproxy $
# echo "acme status" | socat - /tmp/hap-stats
# certificate section state expiration date (UTC) expires in scheduled date (UTC) scheduled in none.at.pem DNS1 Scheduled 2026-02-20T06:21:00Z 89d 23h01m16s 2026-02-12T18:21:01Z 82d 11h01m17s
```

This curl shows that the TLS Certificate and Key works :-)
```
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:23:38_CET /datadisk/git-repos/haproxy $ # curl -vk --compressed --resolve test2.none.at:8443:127.0.0.1 --http2 --http2-prior-knowledge -H 'X-Forwarded-For: 10.1.1.1,20.2.2.2' https://test2.none.at:8443/
Warning: Overrides previous HTTP version option
* Added test2.none.at:8443:127.0.0.1 to DNS cache
* Hostname test2.none.at was found in DNS cache
*   Trying 127.0.0.1:8443...
* Connected to test2.none.at (127.0.0.1) port 8443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / 
id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=*.none.at
*  start date: Nov 22 06:21:01 2025 GMT
*  expire date: Feb 20 06:21:00 2026 GMT
*  issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Puzzling Parsnip E7
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. * Certificate level 0: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384 * Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://test2.none.at:8443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: test2.none.at:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.5.0]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [accept-encoding: deflate, gzip, br, zstd]
* [HTTP/2] [1] [x-forwarded-for: 10.1.1.1,20.2.2.2]
> GET / HTTP/2
> Host: test2.none.at:8443
> User-Agent: curl/8.5.0
> Accept: */*
> Accept-Encoding: deflate, gzip, br, zstd
> X-Forwarded-For: 10.1.1.1,20.2.2.2
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 503
< content-length: 107
< cache-control: no-cache
< content-type: text/html
<
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
* Connection #0 to host test2.none.at left intact
```

I have moved the pem to the haproxy directory and restarted HAProxy, the acme status is still active :-)

```shell
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:45:04_CET /datadisk/git-repos/haproxy $
# mv /tmp/none.at.pem .
# restart haproxy
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:45:19_CET /datadisk/git-repos/haproxy $
# echo "acme status" | socat - /tmp/hap-stats
# certificate section state expiration date (UTC) expires in scheduled date (UTC) scheduled in none.at.pem DNS1 Scheduled 2026-02-20T06:08:42Z 89d 22h23m05s 2026-02-12T18:08:43Z 82d 10h23m06s
```



After the successful creation of the Cert+Key here the feedback to the docs.

In https://docs.haproxy.org/dev/management.html#9.3-acme%20status

> - The state of the acme task, either "Running", "Scheduled" or "Stopped"

When is the Certificate Ready or usable?

As the state "Scheduled" can't be find in https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.6 , I expect this means 'Scheduled for renew and valid for usage' right?

Maybe the command "acme status none.at.pem" shows more detail about the acme state similar to "show ssl cert none.at.pem" to be able to automate the acme stuff like this.

```
echo "acme status none.at.pem" | socat - /tmp/hap-stats | grep -Ei invalid => trigger renew
```

or with json output.

Looks like in dpapi sink are the infos.

```shell
alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 08:39:47_CET /datadisk/git-repos/haproxy $
# echo "show events dpapi" | socat - /tmp/hap-stats
...
<0>2025-11-22T08:18:36.970272+01:00 acme deploy none.at.pem thumbprint KUPYKb-oN7x2ZsaWObc5_odROuGfkQgOdRpVQ9N_zWw
dns-01-record "StQiL5JrufnS8PrI1-zu2kpLm7O-Lo4qC7Yj3YBcQLQ"
{
  "identifier": {
    "type": "dns",
    "value": "none.at"
  },
  "status": "valid",
  "expires": "2025-12-22T07:07:09Z",
  "challenges": [
    {
      "type": "dns-01",
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691543/maH2Iw";,
      "status": "valid",
      "validated": "2025-11-22T07:07:08Z",
      "token": "aahPPGJXuCBB2A2dWILR8K6K5NcBjF0a0lglDtnMla8",
      "validationRecord": [
        {
          "hostname": "none.at",
          "addressUsed": ""
        }
      ]
    }
  ]
}

<0>2025-11-22T08:18:37.128883+01:00 acme deploy none.at.pem thumbprint KUPYKb-oN7x2ZsaWObc5_odROuGfkQgOdRpVQ9N_zWw
dns-01-record "_wcHgxxgc7UodVnjkroQknQSHZKrggzFVgkt7KAk320"
{
  "identifier": {
    "type": "dns",
    "value": "none.at"
  },
  "status": "valid",
  "expires": "2025-12-22T07:07:09Z",
  "challenges": [
    {
      "type": "dns-01",
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/chall/244976483/20362691533/RLZYJw";,
      "status": "valid",
      "validated": "2025-11-22T07:07:08Z",
      "token": "0SJwmK1NThNDHCxRu-wNQTTXOgIr8xfcXElJbGW-H5g",
      "validationRecord": [
        {
          "hostname": "none.at",
          "addressUsed": ""
        }
      ]
    }
  ],
  "wildcard": true
}

<0>2025-11-22T08:19:34.862874+01:00 acme newcert none.at.pem
```

I have seen that in the Dataplane API is the acme part on the way to be integrated ( https://github.com/haproxytech/dataplaneapi/commit/673f23c990c347a99ef66fdc37213acd471b0720 ) it would be nice to add the libdns/desec provider as asked in https://github.com/haproxytech/dataplaneapi/issues/395 so that it can be tried to test the dpapi with ACME DNS feature.

I like the https://github.com/haproxy/wiki/wiki/ACME:--native-haproxy how can I contribute to it?

A big thank you for the great work to all Humans which was involved to bring this Feature into HAProxy.

Some question not related to the ACME stuff.

What tell this output to the users?

```
Sharing caphdr with caphdr
Sharing caphdr with caphdr
Sharing ptrcap with ptrcap
Sharing ptrcap with ptrcap
```

When I start haproxy?
```alex@alex-tuxedoinfinitybooks1517gen7 on 22/11/2025 at 09:01:27_CET /datadisk/git-repos/haproxy $
# ./haproxy -W -db -f ../haproxy_acme.cfg
[NOTICE]   (14018) : Initializing new worker (14020)
Sharing caphdr with caphdr
Sharing caphdr with caphdr
Sharing ptrcap with ptrcap
Sharing ptrcap with ptrcap
[NOTICE]   (14020) : Automatically setting global.maxconn to 524263.
Sharing stk_ctr with caphdr
[NOTICE]   (14018) : Loading success.
```
It would be nice to add some log level to the message like "[NOTICE] : " so that log parsers can be used in generic way.

My global section.
```
global
  expose-experimental-directives
  log stdout format raw daemon info
  stats socket /tmp/hap-stats mode 660 level admin expose-fd listeners
```

I like the new SSL infos :-)

> 127.0.0.1:40140 [22/Nov/2025:08:23:38.291] in/2: SSL handshake failure (error:0A000418:SSL routines::tlsv1 alert unknown ca)


Regards
Aleks


Reply via email to