From: Samuel Rufinatscha <s.rufinatscha@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] superseded: [PATCH proxmox{-backup, } v4 0/8] fix #6939: acme: support servers returning 204 for nonce requests
Date: Thu, 8 Jan 2026 12:48:43 +0100 [thread overview]
Message-ID: <9f94815f-0378-4181-b0cd-c64f05d6ccc7@proxmox.com> (raw)
In-Reply-To: <20251203102217.59923-1-s.rufinatscha@proxmox.com>
https://lore.proxmox.com/pbs-devel/20260108112629.189670-1-s.rufinatscha@proxmox.com/T/#t
On 12/3/25 11:21 AM, Samuel Rufinatscha wrote:
> Hi,
>
> this series fixes account registration for ACME providers that return
> HTTP 204 No Content to the newNonce request. Currently, both the PBS
> ACME client and the shared ACME client in proxmox-acme only accept
> HTTP 200 OK for this request. The issue was observed in PBS against a
> custom ACME deployment and reported as bug #6939 [1].
>
> ## Problem
>
> During ACME account registration, PBS first fetches an anti-replay
> nonce by sending a HEAD request to the CA’s newNonce URL.
> RFC 8555 §7.2 [2] states that:
>
> * the server MUST include a Replay-Nonce header with a fresh nonce,
> * the server SHOULD use status 200 OK for the HEAD request,
> * the server MUST also handle GET on the same resource and may return
> 204 No Content with an empty body.
>
> The reporter observed the following error message:
>
> *ACME server responded with unexpected status code: 204*
>
> and mentioned that the issue did not appear with PVE 9 [1]. Looking at
> PVE’s Perl ACME client [3], it uses a GET request instead of HEAD and
> accepts any 2xx success code when retrieving the nonce. This difference
> in behavior does not affect functionality but is worth noting for
> consistency across implementations.
>
> ## Approach
>
> To support ACME providers which return 204 No Content, the Rust ACME
> clients in proxmox-backup and proxmox need to treat both 200 OK and 204
> No Content as valid responses for the nonce request, as long as a
> Replay-Nonce header is present.
>
> This series changes the expected field of the internal Request type
> from a single u16 to a list of allowed status codes
> (e.g. &'static [u16]), so one request can explicitly accept multiple
> success codes.
>
> To avoid fixing the issue twice (once in PBS’ own ACME client and once
> in the shared Rust client), this series first refactors PBS to use the
> shared AcmeClient from proxmox-acme / proxmox-acme-api, similar to PDM,
> and then applies the bug fix in that shared implementation so that all
> consumers benefit from the more tolerant behavior.
>
> ## Testing
>
> *Testing the refactor*
>
> To test the refactor, I
> (1) installed latest stable PBS on a VM
> (2) created .deb package from latest PBS (master), containing the
> refactor
> (3) installed created .deb package
> (4) installed Pebble from Let's Encrypt [5] on the same VM
> (5) created an ACME account and ordered the new certificate for the
> host domain.
>
> Steps to reproduce:
>
> (1) install latest stable PBS on a VM, create .deb package from latest
> PBS (master) containing the refactor, install created .deb package
> (2) install Pebble from Let's Encrypt [5] on the same VM:
>
> cd
> apt update
> apt install -y golang git
> git clone https://github.com/letsencrypt/pebble
> cd pebble
> go build ./cmd/pebble
>
> then, download and trust the Pebble cert:
>
> wget https://raw.githubusercontent.com/letsencrypt/pebble/main/test/certs/pebble.minica.pem
> cp pebble.minica.pem /usr/local/share/ca-certificates/pebble.minica.crt
> update-ca-certificates
>
> We want Pebble to perform HTTP-01 validation against port 80, because
> PBS’s standalone plugin will bind port 80. Set httpPort to 80.
>
> nano ./test/config/pebble-config.json
>
> Start the Pebble server in the background:
>
> ./pebble -config ./test/config/pebble-config.json &
>
> Create a Pebble ACME account:
>
> proxmox-backup-manager acme account register default admin@example.com --directory 'https://127.0.0.1:14000/dir'
>
> To verify persistence of the account I checked
>
> ls /etc/proxmox-backup/acme/accounts
>
> Verified if update-account works
>
> proxmox-backup-manager acme account update default --contact "a@example.com,b@example.com"
> proxmox-backup-manager acme account info default
>
> In the PBS GUI, you can create a new domain. You can use your host
> domain name (see /etc/hosts). Select the created account and order the
> certificate.
>
> After a page reload, you might need to accept the new certificate in the browser.
> In the PBS dashboard, you should see the new Pebble certificate.
>
> *Note: on reboot, the created Pebble ACME account will be gone and you
> will need to create a new one. Pebble does not persist account info.
> In that case remove the previously created account in
> /etc/proxmox-backup/acme/accounts.
>
> *Testing the newNonce fix*
>
> To prove the ACME newNonce fix, I put nginx in front of Pebble, to
> intercept the newNonce request in order to return 204 No Content
> instead of 200 OK, all other requests are unchanged and forwarded to
> Pebble. Requires trusting the nginx CAs via
> /usr/local/share/ca-certificates + update-ca-certificates on the VM.
>
> Then I ran following command against nginx:
>
> proxmox-backup-manager acme account register proxytest root@backup.local --directory 'https://nginx-address/dir
>
> The account could be created successfully. When adjusting the nginx
> configuration to return any other non-expected success status code,
> PBS rejects as expected.
>
> ## Patch summary
>
> 0001 – acme: include proxmox-acme-api dependency
> Adds proxmox-acme-api as a new dependency for the ACME code. This
> prepares the codebase to use the shared ACME API instead of local
> implementations.
>
> 0002 – acme: drop local AcmeClient
> Removes the local AcmeClient implementation. Minimal changes
> required to support the removal.
>
> 0003 – acme: change API impls to use proxmox-acme-api handler
> Updates existing ACME API implementations to use the handlers provided
> by proxmox-acme-api.
>
> 0004 – acme: certificate ordering through proxmox-acme-api
> Perform certificate ordering through proxmox-acme-api instead of local
> logic.
>
> 0005 – acme api: add helper to load client for an account
> Introduces a helper function to load an ACME client instance for a
> given account. Required for the PBS refactor.
>
> 0006 – acme: reduce visibility of Request type
> Restricts the visibility of the internal Request type.
>
> 0007 – acme: introduce http_status module
> Adds a dedicated http_status module for handling common HTTP status
> codes.
>
> 0008 – fix #6939: acme: support servers returning 204 for nonce
> Adjusts nonce handling to support ACME servers that return HTTP 204
> (No Content) for new-nonce requests.
>
> Thanks for considering this patch series, I look forward to your
> feedback.
>
> Best,
> Samuel Rufinatscha
>
> ## Changelog
>
> Changes from v3 to v4:
>
> Removed: [PATCH proxmox-backup v3 1/1].
>
> Added:
>
> [PATCH proxmox-backup v4 1/4] acme: include proxmox-acme-api dependency
> * New: add proxmox-acme-api as a dependency and initialize it in
> PBS so PBS can use the shared ACME API instead.
>
> [PATCH proxmox-backup v4 2/4] acme: drop local AcmeClient
> * New: remove the PBS-local AcmeClient implementation and switch PBS
> over to the shared proxmox-acme async client.
>
> [PATCH proxmox-backup v4 3/4] acme: change API impls to use proxmox-acme-api
> handlers
> * New: rework PBS’ ACME API endpoints to delegate to
> proxmox-acme-api handlers instead of duplicating logic locally.
>
> [PATCH proxmox-backup v4 4/4] acme: certificate ordering through
> proxmox-acme-api
> * New: move PBS’ ACME certificate ordering logic over to
> proxmox-acme-api, keeping only certificate installation/reload in
> PBS.
>
> [PATCH proxmox v4 1/4] acme-api: add helper to load client for an account
> * New: add a load_client_with_account helper in proxmox-acme-api so
> PBS (and others) can construct an AcmeClient for a configured account
> without duplicating boilerplate.
>
> [PATCH proxmox v4 2/4] acme: reduce visibility of Request type
> * New: hide the low-level Request type and its fields behind
> constructors / reduced visibility so changes to “expected” no longer
> affect the public API as they did in v3.
>
> [PATCH proxmox v4 3/4] acme: introduce http_status module
> * New: split out the HTTP status constants into an internal
> http_status module as a separate preparatory cleanup before the bug
> fix, instead of doing this inline like in v3.
>
> Changed:
>
> [PATCH proxmox v3 1/1] -> [PATCH proxmox v4 4/4]
> fix #6939: acme: support server returning 204 for nonce requests
> * Rebased on top of the refactor: keep the same behavioural fix as in v3
> (accept 204 for newNonce with Replay-Nonce present), but implement it
> on top of the http_status module that is part of the refactor.
>
> Changes from v2 to v3:
>
> [PATCH proxmox v3 1/1] fix #6939: support providers returning 204 for nonce
> requests
> * Rename `http_success` module to `http_status`
>
> [PATCH proxmox-backup v3 1/1] acme: accept HTTP 204 from newNonce endpoint
> * Replace `http_success` usage
>
> Changes from v1 to v2:
>
> [PATCH proxmox v2 1/1] fix #6939: support providers returning 204 for nonce
> requests
> * Introduced `http_success` module to contain the http success codes
> * Replaced `Vec<u16>` with `&[u16]` for expected codes to avoid
> allocations.
> * Clarified the PVEs Perl ACME client behaviour in the commit message.
>
> [PATCH proxmox-backup v2 1/1] acme: accept HTTP 204 from newNonce endpoint
> * Integrated the `http_success` module, replacing `Vec<u16>` with `&[u16]`
> * Clarified the PVEs Perl ACME client behaviour in the commit message.
>
> [1] Bugzilla report #6939:
> [https://bugzilla.proxmox.com/show_bug.cgi?id=6939](https://bugzilla.proxmox.com/show_bug.cgi?id=6939)
> [2] RFC 8555 (ACME):
> [https://datatracker.ietf.org/doc/html/rfc8555/#section-7.2](https://datatracker.ietf.org/doc/html/rfc8555/#section-7.2)
> [3] PVE’s Perl ACME client (allow 2xx codes for nonce requests):
> [https://git.proxmox.com/?p=proxmox-acme.git;a=blob;f=src/PVE/ACME.pm;h=f1e9bb7d316e3cea1e376c610b0479119217aecc;hb=HEAD#l597](https://git.proxmox.com/?p=proxmox-acme.git;a=blob;f=src/PVE/ACME.pm;h=f1e9bb7d316e3cea1e376c610b0479119217aecc;hb=HEAD#l597)
> [4] Pebble ACME server:
> [https://github.com/letsencrypt/pebble](https://github.com/letsencrypt/pebble)
> [5] Pebble ACME server (perform GET request:
> [https://git.proxmox.com/?p=proxmox-acme.git;a=blob;f=src/PVE/ACME.pm;h=f1e9bb7d316e3cea1e376c610b0479119217aecc;hb=HEAD#l219](https://git.proxmox.com/?p=proxmox-acme.git;a=blob;f=src/PVE/ACME.pm;h=f1e9bb7d316e3cea1e376c610b0479119217aecc;hb=HEAD#l219)
>
> proxmox-backup:
>
> Samuel Rufinatscha (4):
> acme: include proxmox-acme-api dependency
> acme: drop local AcmeClient
> acme: change API impls to use proxmox-acme-api handlers
> acme: certificate ordering through proxmox-acme-api
>
> Cargo.toml | 3 +
> src/acme/client.rs | 691 -------------------------
> src/acme/mod.rs | 5 -
> src/acme/plugin.rs | 336 ------------
> src/api2/config/acme.rs | 407 ++-------------
> src/api2/node/certificates.rs | 240 ++-------
> src/api2/types/acme.rs | 98 ----
> src/api2/types/mod.rs | 3 -
> src/bin/proxmox-backup-api.rs | 2 +
> src/bin/proxmox-backup-manager.rs | 2 +
> src/bin/proxmox-backup-proxy.rs | 1 +
> src/bin/proxmox_backup_manager/acme.rs | 21 +-
> src/config/acme/mod.rs | 51 +-
> src/config/acme/plugin.rs | 99 +---
> src/config/node.rs | 29 +-
> src/lib.rs | 2 -
> 16 files changed, 103 insertions(+), 1887 deletions(-)
> delete mode 100644 src/acme/client.rs
> delete mode 100644 src/acme/mod.rs
> delete mode 100644 src/acme/plugin.rs
> delete mode 100644 src/api2/types/acme.rs
>
>
> proxmox:
>
> Samuel Rufinatscha (4):
> acme-api: add helper to load client for an account
> acme: reduce visibility of Request type
> acme: introduce http_status module
> fix #6939: acme: support servers returning 204 for nonce requests
>
> proxmox-acme-api/src/account_api_impl.rs | 5 +++++
> proxmox-acme-api/src/lib.rs | 3 ++-
> proxmox-acme/src/account.rs | 27 +++++++++++++-----------
> proxmox-acme/src/async_client.rs | 8 +++----
> proxmox-acme/src/authorization.rs | 2 +-
> proxmox-acme/src/client.rs | 8 +++----
> proxmox-acme/src/lib.rs | 6 ++----
> proxmox-acme/src/order.rs | 2 +-
> proxmox-acme/src/request.rs | 25 +++++++++++++++-------
> 9 files changed, 51 insertions(+), 35 deletions(-)
>
>
> Summary over all repositories:
> 25 files changed, 154 insertions(+), 1922 deletions(-)
>
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
prev parent reply other threads:[~2026-01-08 11:49 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-03 10:22 [pbs-devel] " Samuel Rufinatscha
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox-backup v4 1/4] acme: include proxmox-acme-api dependency Samuel Rufinatscha
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox-backup v4 2/4] acme: drop local AcmeClient Samuel Rufinatscha
2025-12-09 16:50 ` Max R. Carrara
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox-backup v4 3/4] acme: change API impls to use proxmox-acme-api handlers Samuel Rufinatscha
2025-12-09 16:50 ` Max R. Carrara
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox-backup v4 4/4] acme: certificate ordering through proxmox-acme-api Samuel Rufinatscha
2025-12-09 16:50 ` Max R. Carrara
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox v4 1/4] acme-api: add helper to load client for an account Samuel Rufinatscha
2025-12-09 16:51 ` Max R. Carrara
2025-12-10 10:08 ` Samuel Rufinatscha
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox v4 2/4] acme: reduce visibility of Request type Samuel Rufinatscha
2025-12-09 16:51 ` Max R. Carrara
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox v4 3/4] acme: introduce http_status module Samuel Rufinatscha
2025-12-03 10:22 ` [pbs-devel] [PATCH proxmox v4 4/4] fix #6939: acme: support servers returning 204 for nonce requests Samuel Rufinatscha
2025-12-09 16:50 ` [pbs-devel] [PATCH proxmox{-backup, } v4 0/8] " Max R. Carrara
2025-12-10 9:44 ` Samuel Rufinatscha
2026-01-08 11:48 ` Samuel Rufinatscha [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9f94815f-0378-4181-b0cd-c64f05d6ccc7@proxmox.com \
--to=s.rufinatscha@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.