Certbot renewal gives error during dns-01

Just a quick pre-amble: I have been running Nginx Proxy Manager as a reverse proxy for my systems for almost 2 years without any issues. Renewal was going fine until this month when it started giving a completely non descriptive error. So I tried renewing from the CLI, which gave the same error but allowed me to get some more details using the verbose flag.

A possibly relevant detail is that porkbun has changed their api endpoint from porkbun.com to api.porkbun.com during this period (1st of january I think). However I already ran updates on everything, including the porkbun plugin, it should be the lastest version therefore with updated endpoint. Also what I can understand from the error does not seem to point to that being the issue.
Also also: I succesfully use the same api credentials for other scripts that still work, and just to be sure I generated some new credentials and tried those, still the same problem.

My domain is: steenmeijer.top

I ran this command:

certbot certonly \
  --non-interactive \
  --agree-tos \
  --email ********@****.*** \
  --preferred-challenges dns \
  --authenticator dns-porkbun \
  --dns-porkbun-credentials /etc/letsencrypt/credentials/credentials-2 \
  --dns-porkbun-propagation-seconds 60 \
  -d "*.steenmeijer.top" -vv

It produced this output:

Root logging level set at 10
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requested authenticator dns-porkbun and installer None
Single candidate plugin: * dns-porkbun
Description: Obtain certificates using a DNS TXT record for Porkbun domains
Interfaces: Authenticator, Plugin
Entry point: dns-porkbun = certbot_dns_porkbun.cert.client:Authenticator
Initialized: <certbot_dns_porkbun.cert.client.Authenticator object at 0x713abb009640>
Prep: True
Selected authenticator <certbot_dns_porkbun.cert.client.Authenticator object at 0x713abb009640> and installer None
Plugins selected: Authenticator dns-porkbun, Installer None
Picked account: <Account(RegistrationResource(body=Registration(key=None, contact=(), agreement=None, status=None, terms_of_service_agreed=None, only_return_existing=None, external_account_binding=None), uri='https://acme-v02.api.letsencrypt.org/acme/acct/1093397987', new_authzr_uri=None, terms_of_service=None), 065e55982a50fbaffe30c8446e228d6c, Meta(creation_dt=datetime.datetime(2023, 5, 4, 14, 33, 1, tzinfo=<UTC>), creation_host='nginxproxymanager.steenmeijer.top', register_to_eff=None))>
Sending GET request to https://acme-v02.api.letsencrypt.org/directory.
Received response:
HTTP 200
Server: nginx
Date: Sun, 09 Feb 2025 15:55:05 GMT
Content-Type: application/json
Content-Length: 828
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "c7OGGOHY7ME": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "profiles": {
      "classic": "The same profile you're accustomed to"
    },
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf",
    "website": "https://letsencrypt.org"
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "renewalInfo": "https://acme-v02.api.letsencrypt.org/draft-ietf-acme-ari-03/renewalInfo",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
}
OCSP response for certificate /etc/letsencrypt/archive/npm-2/cert10.pem is signed by the certificate's issuer.
OCSP certificate status for /etc/letsencrypt/archive/npm-2/cert10.pem is: OCSPCertStatus.GOOD
Should renew, less than 30 days before certificate expiry 2025-02-15 11:10:37 UTC.
Certificate is due for renewal, auto-renewing...
Notifying user: Renewing an existing certificate for *.steenmeijer.top
Renewing an existing certificate for *.steenmeijer.top
Requested authenticator dns-porkbun and installer <certbot._internal.cli.cli_utils._Default object at 0x713abaf8bc40>
Requesting fresh nonce
Sending HEAD request to https://acme-v02.api.letsencrypt.org/acme/new-nonce.
Received response:
HTTP 200
Server: nginx
Date: Sun, 09 Feb 2025 15:55:06 GMT
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: ES_SC8yEl0-HnsOP0gPSARlSZfaxLzGDjNOHhy0J9ig-TwckyYU
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800


Storing nonce: ES_SC8yEl0-HnsOP0gPSARlSZfaxLzGDjNOHhy0J9ig-TwckyYU
JWS payload:
b'{\n  "identifiers": [\n    {\n      "type": "dns",\n      "value": "*.steenmeijer.top"\n    }\n  ]\n}'
Sending POST request to https://acme-v02.api.letsencrypt.org/acme/new-order:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMTA5MzM5Nzk4NyIsICJub25jZSI6ICJFU19TQzh5RWwwLUhuc09QMGdQU0FSbFNaZmF4THpHRGpOT0hoeTBKOWlnLVR3Y2t5WVUiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1vcmRlciJ9",
  "signature": "joRC2xBNKRHT0W0H2ibjOsq5hLzcBdS3fF-wOmjEdNdOfRMv0nlU7NyPmGL2ij_to1fvkB2CH3uupZd4LsxIypCyikignWFIp50Pk44qA2gqel7hb9hgRKAfVgFtQsDQZXRJVa21RAkAhjOoImguOqaWJt3RnzOk6LAvd3MJ522sDcqYMSQk3zAE0o_Q3nQh-BfcdZUIH9ihciQ0-wYzpeakmQPX0qaO5v5sR8Rv0j0FQc24oPzJoeOrokDzZyFHsiaGoFAiKcgSqCa7PYAGLWgGT3SApZuHC1RgMes0pzAXmABFbUOM3wlf4eBYguE2yH4I-4FJb03Q0xRE0dNssg",
  "payload": "ewogICJpZGVudGlmaWVycyI6IFsKICAgIHsKICAgICAgInR5cGUiOiAiZG5zIiwKICAgICAgInZhbHVlIjogIiouc3RlZW5tZWlqZXIudG9wIgogICAgfQogIF0KfQ"
}
Received response:
HTTP 201
Server: nginx
Date: Sun, 09 Feb 2025 15:55:06 GMT
Content-Type: application/json
Content-Length: 351
Connection: keep-alive
Boulder-Requester: 1093397987
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Location: https://acme-v02.api.letsencrypt.org/acme/order/1093397987/351768775165
Replay-Nonce: ES_SC8yEN5ePjnIiUouElQwSHJ38Khl46N0RAYkgSN2Vw8_CrLY
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "status": "pending",
  "expires": "2025-02-13T14:14:25Z",
  "identifiers": [
    {
      "type": "dns",
      "value": "*.steenmeijer.top"
    }
  ],
  "authorizations": [
    "https://acme-v02.api.letsencrypt.org/acme/authz/1093397987/471927485865"
  ],
  "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/1093397987/351768775165"
}
Storing nonce: ES_SC8yEN5ePjnIiUouElQwSHJ38Khl46N0RAYkgSN2Vw8_CrLY
JWS payload:
b''
Sending POST request to https://acme-v02.api.letsencrypt.org/acme/authz/1093397987/471927485865:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMTA5MzM5Nzk4NyIsICJub25jZSI6ICJFU19TQzh5RU41ZVBqbklpVW91RWxRd1NISjM4S2hsNDZOMFJBWWtnU04yVnc4X0NyTFkiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LzEwOTMzOTc5ODcvNDcxOTI3NDg1ODY1In0",
  "signature": "Rj9A60-sVDAh3gqH81FYGoU5sk-MyDRERnlSsTgSl5CkoUbjbK5uqZv9hgGSCfd8vANwptsap21kS160rAJK7glKgkST5PvBoCRzfyTOBNq4WNn6QcvMRxwCsmchxeXpkO5CxXF5gBlElXsU5EqRKg5jn_NrpEWXSaWBLSGQ-Wo43KNjM95Vt19n-76wpfOVzQ6rLHca4hwSaGHD2OpSyYSP7u8Ts6I9GgCzoBPi3L7C1iA2HTrTZ0xrY9oQkKf5DhSsIA0oKDZ2Tt7SEikbE8U7tD_tQNpMY3RsenyVHxqrzfEVe8BJbKcT_7cxR5dcJX9hlwtljur36d7mkmis8Q",
  "payload": ""
}
Received response:
HTTP 200
Server: nginx
Date: Sun, 09 Feb 2025 15:55:06 GMT
Content-Type: application/json
Content-Length: 397
Connection: keep-alive
Boulder-Requester: 1093397987
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: A-S0uJjSQe1O4yqfbLTKGGuMbGHSlZ_wi8BEmOqsS5VPhHZ-sXU
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "steenmeijer.top"
  },
  "status": "pending",
  "expires": "2025-02-13T14:14:25Z",
  "challenges": [
    {
      "type": "dns-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/1093397987/471927485865/kDCh1Q",
      "status": "pending",
      "token": "4nYLixR5oJDltFmW4sBnCZOR7C9Fr_LGt7MtUR97hUA"
    }
  ],
  "wildcard": true
}
Storing nonce: A-S0uJjSQe1O4yqfbLTKGGuMbGHSlZ_wi8BEmOqsS5VPhHZ-sXU
Performing the following challenges:
dns-01 challenge for steenmeijer.top
Encountered exception:
Traceback (most recent call last):
  File "/root/.local/lib/python3.9/site-packages/certbot_dns_porkbun/cert/client.py", line 109, in _perform
    self.record_ids[validation] = self._get_porkbun_client().dns_create(self._root_domain,
  File "/root/.local/lib/python3.9/site-packages/pkb_client/client.py", line 121, in dns_create
    "Message: {}".format(r.status_code, json.loads(r.text).get("message", "no message found")))
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/auth_handler.py", line 88, in handle_authorizations
    resps = self.auth.perform(achalls)
  File "/usr/local/lib/python3.9/dist-packages/certbot/plugins/dns_common.py", line 76, in perform
    self._perform(domain, validation_domain_name, validation)
  File "/root/.local/lib/python3.9/site-packages/certbot_dns_porkbun/cert/client.py", line 114, in _perform
    raise errors.PluginError(e)
certbot.errors.PluginError: Expecting value: line 1 column 1 (char 0)

Calling registered functions
Cleaning up challenges
Encountered exception during recovery: KeyError: 'zVXxUzJ7M5tZlW9xXzCUuhMLc2F8efxsarSKV681axA'
Exiting abnormally:
Traceback (most recent call last):
  File "/root/.local/lib/python3.9/site-packages/certbot_dns_porkbun/cert/client.py", line 109, in _perform
    self.record_ids[validation] = self._get_porkbun_client().dns_create(self._root_domain,
  File "/root/.local/lib/python3.9/site-packages/pkb_client/client.py", line 121, in dns_create
    "Message: {}".format(r.status_code, json.loads(r.text).get("message", "no message found")))
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/certbot", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.9/dist-packages/certbot/main.py", line 19, in main
    return internal_main.main(cli_args)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/main.py", line 1864, in main
    return config.func(config, plugins)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/main.py", line 1597, in certonly
    lineage = _get_and_save_cert(le_client, config, domains, certname, lineage)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/main.py", line 129, in _get_and_save_cert
    renewal.renew_cert(config, domains, le_client, lineage)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/renewal.py", line 395, in renew_cert
    new_cert, new_chain, new_key, _ = le_client.obtain_certificate(domains, new_key)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/client.py", line 428, in obtain_certificate
    orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/client.py", line 496, in _get_order_and_authorizations
    authzr = self.auth_handler.handle_authorizations(orderr, self.config, best_effort)
  File "/usr/local/lib/python3.9/dist-packages/certbot/_internal/auth_handler.py", line 88, in handle_authorizations
    resps = self.auth.perform(achalls)
  File "/usr/local/lib/python3.9/dist-packages/certbot/plugins/dns_common.py", line 76, in perform
    self._perform(domain, validation_domain_name, validation)
  File "/root/.local/lib/python3.9/site-packages/certbot_dns_porkbun/cert/client.py", line 114, in _perform
    raise errors.PluginError(e)
certbot.errors.PluginError: Expecting value: line 1 column 1 (char 0)
Expecting value: line 1 column 1 (char 0)
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.

My web server is (include version):

# nginx -v
nginx version: openresty/1.21.4.1

The operating system my web server runs on is (include version):

# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 11 (bullseye)
Release:        11
Codename:       bullseye

My hosting provider: not applicable

I can login to a root shell on my machine: yes

I'm using a control panel to manage my site: no (nginx proxy manager but this result is from running certbot from CLI)

The version of my client is:

# certbot --version
certbot 2.5.0

Update: while writing this post it occurred to me to manually check that everything had in fact updated properly as I used a helper script to do that. Turns out that the porkbun plugin was in fact still the old version (0.8) that did not have the updated api endpoint in it. This is obviously a flaw of the updater script and nothing to do with certbot.

After manually updating the plugin: pip3 install certbot_dns_porkbun -U it has gone back to auto renewing again. So this topic can be closed, hopefully it will help someone with similar issues.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.