github fabriziosalmi/certmate v2.46.0
v2.46.0 (certbot 5.8, and Azure DNS without a plugin)

2 hours ago

v2.46.0 (certbot 5.8, and Azure DNS without a plugin)

A minor release that moves the ACME stack from certbot 2.10.0 to 5.8.0 (issue #103), and answers Azure DNS challenges with CertMate's own hook instead of a certbot plugin. Existing certificates keep renewing with nothing to do, and going back to the previous release is possible. The API contract stays at 2.34.


Read this before upgrading

Certificates: nothing to do, and you can go back

Existing certificates renew under certbot 5.8.0 without any action. The first renewal rewrites each certificate's renewal/<name>.conf (it now says version = 5.8.0 and gains an [acme_renewal_info] section). Both directions were measured with real certbot on Let's Encrypt staging: a certificate issued by certbot 2.10.0 renews under 5.8.0, and the certificate that 5.8.0 rewrote renews under 2.10.0. So if you upgrade and want to return to v2.45.2, your certificates come with you.

GET /health reports the new version in checks.certbot_version (certbot 5.8.0).

If you use Azure DNS

Azure DNS challenges are no longer answered by the certbot-dns-azure plugin. That plugin has no release for certbot 4 or later, and it had already broken once (see v2.45.2). CertMate now writes the challenge record itself with the Azure SDK, using the same service principal and the same zone configuration you already have. What the principal needs is unchanged: permission to read, write and delete TXT records in the zone (the DNS Zone Contributor role on the resource group covers it).

Certificates that the plugin issued renew through the new code with no action: certbot replaces the authenticator stored in a certificate's renewal config when the command line names the new one, and rewrites the file without the plugin's keys. The wait before validation is still the provider's propagation setting (180 seconds by default).

This is the part that was not run against a live Azure zone. The hook was run against the real Azure SDK with the network recorded, and through real certbot against a fake service principal, where it reaches the Azure authentication call and certbot shows its error. If you issue through Azure DNS and anything looks wrong after upgrading, please open an issue: it will be treated as a regression.

If you build or install CertMate yourself

  • certbot 5 needs Python 3.10 or later. Install from requirements.lock, which is what the image is built from.
  • certbot-dns-azure is removed from every requirements file, and requirements-azure.txt now installs only the two Azure SDK packages. The official plugins are at 5.8.0 with it; an older certbot-dns-* pin layered on top of certbot 5 is not something that was tested, so install from the lock rather than assembling the set by hand.
  • The optional storage sets (requirements-azure-storage.txt, requirements-storage-all.txt) now declare cryptography>=49,<51, the window the stack works in.
  • Proxmox VE container users (the community-scripts installer): the update rebuilds the virtual environment from this release's lock, so nothing carries over from the old plugin set.
  • Docker and Helm users: nothing to do.

Security

The four advisories that were open against cryptography 46.0.7, which could not be fixed on the old stack, do not apply to 50.0.2: pip-audit on the installed set reports four for 46.0.7 and none for 50.0.2, and the Dependabot alerts closed on their own when this reached main. SECURITY.md keeps its record of them and of why they were held.


Changed

before after
certbot, acme 2.10.0, 3.3.0 5.8.0
josepy 1.13.0 2.2.0
cryptography, pyopenssl 46.0.7, 26.0.0 50.0.2, 26.4.0
official certbot-dns-* plugins (Cloudflare, Route 53, DigitalOcean, Google, Linode, OVH, RFC 2136, DNS Made Easy, NS1) 2.10.0 5.8.0
certbot-dns-gandi 1.6.1 1.6.2
cloudflare SDK 2.19.4 5.8.0
certbot-dns-azure 2.5.0 removed (CertMate's own hook)

Every other plugin keeps the pin it had: each fits the new stack and behaved the same under the checks below. certbot-plugin-edgedns stays at 0.1.0 on purpose: 0.3.0 reads its credentials without the edgedns_ prefix, so it is not a pin bump (#1079).

  • Azure DNS answers its challenge through modules/core/azure_dns_hook.py. It keeps what the plugin did: the longest configured zone wins (a wildcard under a parent hosted zone lands in the parent); several values share one name (a wildcard and its apex), so a value is added and never written over the record, and cleanup removes only its own; writes carry the record's ETag, and a conflicting write is retried; a failed cleanup never fails the issuance.
  • Dependabot no longer holds cryptography and pyopenssl. They were held because a newer cryptography installed cleanly on the old stack and then killed certbot --version. Now pip refuses what does not fit (certbot and acme 5.8.0 need cryptography>=47, pyOpenSSL 26.4.0 needs >=49,<51) and the image build still runs certbot --version, so a bump is tested instead of held. certbot, acme, josepy, the plugin families, dns-lexicon and the Cloudflare SDK stay held.
  • Python 3.14 is back in the CI matrix, as a check that reports and does not gate (#1078). The image stays on 3.12; the decision, with what was measured and what would change it, is #1080.
  • The Helm chart's README links its Artifact Hub listing (#1081).

Fixed

  • On Python 3.13 and later, the probe never reported the chain a server sends. ssl returns that chain as DER bytes there; the code read each entry as an object, failed on every one, skipped it, and reported no chain for every server, silently. This does not affect the published image, which runs Python 3.12, nor the Proxmox container, which pins 3.12; it affected CertMate run directly on 3.13 or later. The reading now accepts both forms and has tests that exercise both on any interpreter.

Dependencies

  • sqlalchemy is now required as >=2.1.1,<3.0.0 in requirements.txt and requirements-minimal.txt; the lock already resolved 2.1.1, so the image does not change.
  • CI: the codeql-action steps 4.38.1 -> 4.38.2. The MCP server's @modelcontextprotocol/sdk 1.30.0 -> 1.30.1 and fast-uri 3.1.7 -> 3.1.8.

How it was checked

  • Real certificates, on the exact image. The image was built from the migration branch and the six files the release gate runs (Let's Encrypt staging, Cloudflare DNS-01, ARI early renewal included) passed 24 of 24. The release gate runs them again on the release commit.
  • Upgrade in place and rollback, on a private CA. On the bench (step-ca, http-01) the real scheduler renewed 8 certificates out of 8 under certbot 5.8.0 over certificates certbot 2.10.0 had last touched, and issued a new one in 3.4 seconds. In an earlier pass, after 5.8.0 had renewed the bench's certificates, the bench was put back on the previous release and certbot 2.10.0 renewed 8 of 8 again.
  • Every provider, through CertMate's own strategy. For each of the 23 providers, plus custom-script and http-01, CertMate's strategy builds the certbot arguments and certbot runs them with --dry-run against staging with fake credentials, on 2.10.0 and on 5.8.0. The outcome is the same on both: each plugin gets as far as its provider's API and fails there on the fake credential. This shows argument parsing and plugin loading, not that a real zone works.
  • The Azure hook. 57 tests against the installed SDK, with the network recorded: the request that would go to Azure is the one asserted on (method, path, body, the If-Match and If-None-Match headers). Nine behaviours were broken on purpose (the zone match on label boundaries, adding versus overwriting, cleanup deleting everything, cleanup failing the issuance, no retry on a conflict, no If-None-Match on a new record, no wait, the plugin name back, the wait not exported) and each turned at least one test red.
  • Python 3.14. The lock installs on 3.14 for both architectures (122 of its 123 packages from binary wheels, one from a pure-Python source distribution), and the full CI job passed with 7,534 tests. Running it found the chain defect above and fixtures in the test suite that Python 3.13's strict certificate verification refuses (39 tests); both fixed.

Not verified

  • No provider was exercised against a real zone other than Cloudflare (DNS-01) and the private CA (http-01).
  • The Azure hook was not run against a live Azure zone (see above).
  • certbot-plugin-edgedns 0.3.0 and whether CertMate's own ARI client should defer to certbot's are open questions, not changes in this release (#1079, #393).

Don't miss a new certmate release

NewReleases is sending notifications on new releases.