Repository navigation
AutoHttps 1.6.0
Two additions, both about deployments that were hard to get right rather than about the ACME protocol. The AutoHttps and AutoHttps.Redis packages changed; the Cloudflare, Route 53 and Azure packages are unchanged.
Answering http-01 from any replica
The instance that wins the certificate lock is not necessarily the one the authority's validation request reaches. Until now the answer to a challenge lived only in the process that ordered, so a request landing on any other replica got a 404 and that authorization failed. Measured with three replicas and the per-process store: eight failed validations to issue one certificate, repeated at every renewal, against a Let's Encrypt limit of five failed validations per account, per hostname, per hour.
The answer now lives behind IHttp01ChallengeStore. The default is still per-process, so a single instance behaves exactly as before. UseRedis registers a Redis-backed store alongside the certificate and account key stores, and UseHttp01ChallengeStore<T>() registers your own if you want to share only the challenges and keep certificates where they already are.
builder.Services
.AddAutoHttps(options => { /* ... */ })
.UseRedis("localhost:6379");A pending answer is written to autohttps:challenge:<token> and deleted when the order finishes. RedisStoreOptions.ChallengeTtl, 15 minutes by default, bounds how long one survives if an order is interrupted before it can clean up.
The failure message moved with it. A 404 on the challenge path no longer blames something in front of the application when the store is shared, because with a shared store that diagnosis is wrong.
Diagnosing a failure
An authority reports what it saw from outside, which is rarely enough to act on. After the first failed order AutoHttps now checks its own configuration and surroundings once and writes the result to the log as event 144, or 145 when it finds nothing wrong. Nothing runs while orders succeed, and DiagnoseOrderFailures = false turns it off.
The same report is available on demand, which is the output to paste into an issue:
var diagnostics = app.Services.GetRequiredService<IAutoHttpsDiagnostics>();
AutoHttpsDiagnosticsReport report = await diagnostics.RunAsync();
Console.WriteLine(report);Ten checks, every one read only: name count and IP address rules against the requested profile, whether the certificate can actually be written, whether anything is bound to port 80, whether the directory is reachable and offers renewal information, this host's clock against the authority's, external account binding required versus configured, the requested profile against the advertised ones, A and AAAA resolution including SERVFAIL as a broken DNSSEC signal, CAA on the closest ancestor that has a record set, and a token of its own published and fetched back over the public name.
The DNS and CAA checks need DnsPropagationResolver and are skipped without it, because AutoHttps makes no DNS queries unless you configure a resolver.
One thing no client can check for you: since 2025 an authority validates from several network perspectives at least 500km apart and does not publish where from, so a passing challenge-path check proves the path works from this host, not that the authority can reach it.
Upgrading
UseRedis now replaces the http-01 challenge store as well as the certificate and account key stores. That is what a multi-instance deployment wants, and it is why the package exists, but it is a behaviour change: if you had a reason to keep challenge answers per process, register your own store after UseRedis. Everything else is additive.
Packages
AutoHttps1.6.0AutoHttps.Redis1.1.0, which requiresAutoHttps1.6.0