NPM already answers which DNS providers it can drive

GET /nginx/certificates/dns-providers, authenticated, 86 entries on the 2.15.1
image here. verified against the live instance and against the file it reads
from, /app/certbot/dns-plugins.json in the container.

which settles how the provider picker gets built. the list is per install —
whatever certbot plugins that image carries — so curating one centrally and
shipping it as the truth would offer somebody a provider their NPM has never
heard of, take their API key, and fail at issue time with an error that does
not explain itself. ask the instance.

and NPM hands back each provider's credential TEMPLATE, carrying its own field
names. so the form is generated rather than written per provider, and it stays
right for providers we have never heard of. a curated list of ours is left with
the human half only: which we recommend, and how you actually get a key.

also noted: this endpoint answers 403 unauthenticated, not 404. the 404-means-
auth quirk is per route, not a property of the API. the client's heuristic
stays correct; the documentation of it was too broad.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-25 16:04:10 +00:00
co-authored by Claude Opus 5
parent dcb48be419
commit ca77a4507d
2 changed files with 48 additions and 4 deletions
+8 -4
View File
@@ -185,10 +185,14 @@ Verified against the live instance: a wrong credential comes back `likelyAuth =
- **All of the above.** No domain registry, no DNS provider credentials, no named networks, no agent,
no expose route. Everything from "What this is for" through "Private is a network the user names" is
agreed and entirely unbuilt.
- **Two things to check before building the DNS half.** NPM can only run the DNS proof for providers it
ships support for — a fixed list, not "any provider" — and if yours is missing, the proof has to be
done elsewhere and a finished certificate handed over, which is a much larger job. Neither the list
nor whether a given GoDaddy account still has DNS API access has been verified here.
- **One thing left to check before building the DNS half.** Whether a given GoDaddy account still has
DNS API access — they restricted it by account size at some point, and it is unverified here.
Cloudflare is the safer provider to build against first.
The other half of this is now answered: **NPM tells you which providers it can drive**, over
`GET /nginx/certificates/dns-providers`, and it hands back each one's credential field names as a
template. 86 providers on the 2.15.1 image. So the picker asks the instance rather than trusting a
list of ours, and the form is generated from what NPM says. See `docs/npm-api.md`.
- **Certificate expiry notifies nobody.** `daysUntilExpiry` is computed in `api/router.ts` and thrown
away when the panel closes. NPM renews at 30 days; inside 14 means renewal has actually failed and the
domain goes dark at zero. Nothing on the machine will say so.
+40
View File
@@ -125,6 +125,46 @@ a click.
`expires_on` is null for some uploaded certificates. The router computes `daysUntilExpiry` server-side
so the browser is not parsing dates and getting the timezone wrong.
### DNS providers — NPM tells you which it can drive
```
GET /api/nginx/certificates/dns-providers
```
Authenticated (`certificates.view`). Returns one entry per provider:
```jsonc
{
"id": "cloudflare",
"name": "Cloudflare",
"credentials": "dns_cloudflare_api_token = <token>" // a template, with the field names in it
}
```
**86 providers on the 2.15.1 image here**, verified 2026-08-25 against the live instance and against
`/app/certbot/dns-plugins.json` inside the container, which is where the endpoint reads from.
Two things follow, and they decide how the provider picker should be built:
- **The list is per install, not universal.** It is whatever certbot DNS plugins that NPM image carries,
so an older container genuinely cannot drive a provider a newer one can. Curating this list ourselves
and shipping it as the truth would offer somebody a provider their NPM has never heard of, take their
API key, and fail at issue time with an error that does not say why. **Ask the instance.**
- **NPM also describes the credential SHAPE.** `credentials` is a template carrying that provider's own
field names — one token for Cloudflare, key and secret for others. So the form can be generated rather
than hand-written per provider, and it stays right when NPM adds providers we have never heard of.
Which leaves a smaller job for any curated list of our own than it first appears: not which providers
exist or what fields they need — NPM answers both — but the human half. Which ones we recommend, and how
a person actually gets a key out of each one.
### The 404 rule is not universal
This endpoint answers **403 `Permission Denied`** unauthenticated, not the 404 documented above. So the
"NPM answers 404 when it means 401" quirk is per route rather than a property of the API, and
`npm-client.ts` treating 404 as probable-auth stays correct — it is a heuristic that fires on the routes
that need it, not a rule the whole API obeys.
---
## Reaching NPM from Officer