Repository navigation
Conversation
DETERMINISTIC_TLS_KEY issued the first certificate and then stopped: - certbot `--csr` keeps no lineage, so `certbot renew` never renewed it (and with `--cert-name` it now fails outright); re-issuing failed too, since certbot will not overwrite an explicit --cert-path. - lego ignored the setting, so tls-alpn-01 rotated the key on every renewal. - under DELEGATION_ZONE the CSR was never passed, and the key written into live/ pushed certbot's lineage to <name>-0001. - turning it on for an existing deployment only ever renewed the old, randomly keyed lineage. certbot path: certificates for derived keys now live in /etc/letsencrypt/deterministic/<name>/, apart from certbot's lineages. certman.py renews them itself at certbot's thresholds (2/3 of the lifetime, or RENEW_DAYS_BEFORE), and re-issues whenever the served certificate does not carry the derived key. Issuance goes to a fresh staging directory and is moved into place after checking the key. lego path: `lego run --csr --private-key`, which keeps lego's own renewal decision (window + ARI). A certificate with a different key is renewed with --renew-force, and the .key file, which lego does not rewrite on CSR renewals, is kept in step. The CSR now carries a SAN, the key is written PKCS#8 like both clients do, and the README documents when the pinned SPKI changes. certificate_exists also looks at the lineage name now, so a wildcard no longer re-runs certonly on every pass. Signed-off-by: Kevin Wang <wy721@qq.com>
This was referenced Oct 14, 2026
With DETERMINISTIC_TLS_KEY, 2.4-2.6 issued with certbot --csr and wrote plain files into live/<name>/ with no renewal config. Those block certbot from creating the lineage there once the setting is off, so every pass failed and the stale certificate kept being served. certbot only ever links into live/, so a plain fullchain.pem there is the old --csr output. Move it to deterministic/<name>/ when the setting is on and nothing is there yet, otherwise remove it. Signed-off-by: Kevin Wang <wy721@qq.com>
…ewal configs Signed-off-by: Kevin Wang <wy721@qq.com>
…its base's With DETERMINISTIC_TLS_KEY, a base domain and its wildcard both used deterministic/<base>/, so each pass re-issued one over the other and one host was served the other's certificate. The wildcard now uses deterministic/_wildcard.<base>/, in certman.py and dns01.sh alike. 2.4-2.6 put both into live/<base>/ too, so adopt a certificate there into the directory of the name it carries, and only when the key next to it matches. Signed-off-by: Kevin Wang <wy721@qq.com>
kvinwang
added a commit
that referenced
this pull request
Oct 14, 2026
#132-only migration wildcard's certificate. Also check that replacing a wildcard keeps its lineage name. Signed-off-by: Kevin Wang <wy721@qq.com>
kvinwang
added a commit
that referenced
this pull request
Oct 14, 2026
#132-only migration wildcard's certificate. Also check that replacing a wildcard keeps its lineage name. Signed-off-by: Kevin Wang <wy721@qq.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DETERMINISTIC_TLS_KEYonly survived until the first renewal, so a pinned SPKI broke or the certificate expired:--csrkeeps no lineage, socertbot renewnever renewed the certificate, and re-issuing failed because certbot won't overwrite--cert-path.DELEGATION_ZONE: the CSR was never passed to certbot, and the key file pushed the lineage to<name>-0001.Changes:
/etc/letsencrypt/deterministic/<name>/(_wildcard.<base>/for a wildcard, so an apex and its wildcard don't share one). certman renews them at certbot's thresholds (2/3 of the lifetime, orRENEW_DAYS_BEFORE), and re-issues whenever the served certificate doesn't carry the derived key.lego run --csr --private-key, so lego's own renewal logic (including ARI) still decides when to renew.--renew-forceis used when the key differs, and.keyis kept in sync.live/<name>/with no renewal config, and 2.6 wroteprivkey.pembefore issuing, so a failed issuance (and the first pass of every 2.6DELEGATION_ZONEdeployment with the flag on) left only that file. From the second pass on, 2.6 underDELEGATION_ZONEalso left a real certbot<name>-0001lineage; fix(ingress): give wildcard certificates their own certbot lineage #142 migrates that. Since certbot only ever puts symlinks there, certman now treats a plainprivkey.pemas that old output. 2.4–2.6 put a wildcard's there under the base name too. If the flag is on, a plainfullchain.pemis there too, its key matches, and the deterministic directory for the name on the certificate is empty, it moves the files there. Otherwise it removes them, so certbot can create the lineage when the flag is off. An emptyrenewal/<name>.confleft by certbot failing over those files is removed as well; it would otherwise push the lineage to<name>-0001.Tested locally against Pebble (
PEBBLE_VA_ALWAYS_VALID=1) with a fake GetKey socket, running the 2.6 image with these scripts mounted:live/<name>/, no renewal config): flag turned off, then on, and on, then off, with 3 passes each. No-0001lineage appears, and after the first pass each later pass is a no-op.privkey.peminlive/<name>/, with and without an empty renewal config) and the full layout with a leftover empty renewal config, flag off and on, 3 passes each: no-0001, one issuance (or adoption) and then no-ops.--private-keyalone would be enough for the first issuance, but lego 5.3.1 ignores it on renewal, even with--renew-force, and generates a new key. That is why the CSR is kept.All passed.