Apply a fix safely
pqdoctor fix prints the diff; --write writes it. --apply goes all the way, and undoes itself when it should:
sudo pqdoctor fix --config /etc/nginx/sites-enabled/default --apply --host www.example.org- Shows the diff, the commands it will run and the undo, then asks you to type
yes(--yesfor scripts). - Keeps the original as
PATH.bak— an older backup is never overwritten. - Writes the file (atomically: a temporary file, then a rename).
- Runs the stack’s config test (
nginx -t,apachectl configtest,haproxy -c, …). If it fails, the original goes back and nothing is reloaded. - Runs the reload (
systemctl reload nginx, …). - Re-checks
--hostfrom outside — every address — until it negotiates X25519MLKEM768, up to four tries 1.5 s apart (graceful reloads take a moment). - If the reload failed, the site stopped answering, or it still isn’t post-quantum: puts the original back, re-tests, reloads, and checks the site answers again.
--test-cmd and --reload-cmd replace the stack’s commands (repeat them for several).
Outcomes
Section titled “Outcomes”| Outcome | Means |
|---|---|
applied |
Post-quantum now; the original is in the backup |
partial |
This server is PQ, but other addresses behind the name aren’t — they’re different servers; apply the fix there too. The change is kept |
test-failed |
The config test refused it; the original is back, nothing was reloaded |
rolled-back |
Something after the write failed; the original is back, tested, reloaded and answering |
rollback-failed |
Even putting it back failed. pqdoctor says so in red and prints the commands to restore by hand — it never claims success |
When the library can’t
Section titled “When the library can’t”This is why --apply is safe to try: if the TLS library has no ML-KEM, the server’s config test rejects the new group list —
✘ test sudo nginx -t: nginx: [emerg] SSL_CTX_set1_curves_list("X25519MLKEM768:X25519:prime256v1") failed✔ restore original back in /etc/nginx/sites-enabled/defaultNot applied: the config test rejected the change. The original is back; nothing was reloaded.— and now you know it’s the library: a sidecar makes the server post-quantum without the upgrade.
Tested against real servers
Section titled “Tested against real servers”The same code runs in an apply lab against real TLS servers and real config files: OpenSSL 3.6 with a pinned list (applied, post-quantum), OpenSSL 3.0 (refused by the config test, restored), a config that doesn’t control the TLS terminator (rolled back), a reload that fails on the new config (rolled back) and a reload that always fails (rollback-failed, file still restored, manual steps printed). In every case where the fix wasn’t kept, the file ends byte-identical to the original.