HTTP validation
Validate certificates over plain HTTP with no DNS provider access. The only requirement is that the ACME challenge path on each domain — /.well-known/acme-challenge/* — reaches CertAutoPilot's challenge endpoint. You wire that up once at your edge (gateway / ingress / reverse proxy) as a route; CertAutoPilot itself can stay internal. Issuance is immediate — there is no DNS propagation to wait for.
When to use
- You have no API access to the domain's DNS (unsupported provider, external registrar, another team owns DNS).
- You want the fastest issuance path — HTTP-01 validates in seconds, with no propagation delay.
- The domain is already fronted by a gateway / reverse proxy / load balancer you can add a route to.
Not for: wildcard certificates (*.example.com) — the ACME protocol only allows DNS-01 for wildcards; internal-only domains the CA cannot reach over HTTP.
Setup: route the challenge path to CertAutoPilot
At the edge each domain is served by, add one route that forwards the ACME challenge path to CertAutoPilot's challenge endpoint:
http://<domain>/.well-known/acme-challenge/* → <certautopilot>/.well-known/acme-challenge/*
CertAutoPilot does not need to be exposed to the internet — the edge (which the CA reaches on port 80) forwards the path to CertAutoPilot over your internal network, on whatever port CertAutoPilot listens on. Set the route once per site; it keeps working for every future issuance and renewal, for any number of certificates, with no per-issuance action. Preserve the path (the token is the last path segment).
Examples. A reverse-proxy route (nginx) that forwards, keeping CertAutoPilot internal:
location /.well-known/acme-challenge/ {
proxy_pass http://cap.internal:8181; # CertAutoPilot, not publicly exposed
}
If your edge can only rewrite, not route, a 301 redirect works too (the CA follows it):
location /.well-known/acme-challenge/ {
return 301 http://cap.example.com$request_uri; # must resolve to port 80/443
}
Which edge, which port. The CA's initial validation request always goes to your domain on port 80 — that is RFC 8555, not a CA quirk. So the edge the domain resolves to must accept :80 for this path (serve it directly, or redirect it). If you use a route/proxy, that's all — CertAutoPilot behind it can be on any internal port. If you use a 301 redirect, note the CA follows redirects only to ports 80 or 443, so the redirect target must be on 80/443 (redirecting to https:// is fine — during HTTP-01 the CA does not validate the target's TLS certificate, so a self-signed cert works).
How it works
- You issue a certificate with Validation Method → HTTP. No zone or DNS credential is selected.
- The worker starts the ACME order; for each domain the CA issues a unique, high-entropy token.
- The worker writes each token's key authorization to the shared token store (MongoDB) — this is lego's
Presentstep. - The CA requests
http://<domain>/.well-known/acme-challenge/<token>; your edge routes it to CertAutoPilot, whose endpoint answers with the key authorization astext/plain. - The order finalizes, artifacts are stored, distribution triggers — same as any other issuance.
- The tokens are deleted immediately after validation (
CleanUp); a 24-hour TTL index reaps any orphans left by a crash.
Because the response is looked up by token and every challenge gets its own CA-generated token, any number of certificates — and any number of domains per certificate — can validate concurrently with zero contention: there is no shared file, so nothing to race over.
Operational notes
- Which instances serve the endpoint: only
api/allmode instances serve/.well-known/acme-challenge/*;workermode presents tokens by writing MongoDB. In a split deployment, route the path to an API instance (or the service in front of them). - Bundled deployments already route it: the standalone installer, the Docker Compose stack, and the Helm chart all ship an nginx front-end that proxies
/.well-known/acme-challenge/straight to the backend (ahead of the SPA fallback). You do not need to touch CertAutoPilot's own reverse proxy — just route the path on the edge your domains resolve to.- Kubernetes (Helm): the frontend defaults to a
NodePortService, which a public CA cannot reach — front it with a LoadBalancer/Ingress (the same requirement as reaching the dashboard), or route the challenge path to the backend service from your existing gateway. If your pod network uses a CIDR outside RFC1918 (e.g. EKS's100.64.0.0/10secondary range, or IPv6), also setconfig.server.trustedProxiesin values so the real CA IP — not the proxy pod IP — is used for rate limiting; otherwise all challenge fetches share one bucket.
- Kubernetes (Helm): the frontend defaults to a
- The endpoint is unauthenticated by design (the CA cannot log in): it serves only live tokens, responds 404 to everything else, validates the token charset before touching the database, and is IP rate-limited.
- Auto-renew works — unlike manual DNS, HTTP validation is fully automatic, so scheduled renewals and ARI are both supported.
- Multi-domain certificates validate each SAN separately — every domain in the certificate needs the challenge path routed (or to resolve to an edge that has it).
Which host does the CA talk to? Each domain itself — the CA resolves that exact name's A/AAAA record and fetches port 80 there. The apex/parent domain plays no role: for aaa.example.com the CA connects to whatever aaa.example.com resolves to, and that is the edge that must route the challenge path.
Troubleshooting
- CA reports
NXDOMAIN looking up A/AAAA— the domain has no DNS record at all. HTTP-01 proves control of a live host, so the domain must publicly resolve to an edge (that routes the challenge path) before issuing. For a not-yet-live domain, use DNS validation instead — a TXT record doesn't require the host to exist. - CA reports "connection refused / timeout" — the domain's port 80 isn't reachable from the internet, or no edge answers on the IP the domain resolves to.
- CA reports 404 on the challenge — the challenge path isn't routed to CertAutoPilot (test:
curl -i http://<domain>/.well-known/acme-challenge/testshould reach CertAutoPilot, which then 404s — that proves the path is wired), or it's routed to aworker-only instance. - CA reports "invalid port in redirect" — you used a 301 redirect to a port other than 80/443; redirect to :80/:443, or route the path directly instead.
- Wildcard rejected at create — expected; use DNS validation for wildcards.