If you run an ASP.NET Core app directly on Kestrel, with no nginx or cloud load balancer in front, getting a real TLS certificate has always been the awkward part. For years the answer was LettuceEncrypt, which obtained and renewed a Let's Encrypt certificate inside your app. That project was archived in April 2025, and its last release targets .NET 6. So the question is open again: how do you do this now?
Two things have changed, and both matter.
Certificates are getting shorter
Let's Encrypt started issuing six-day certificates this year, and it is taking the default lifetime from 90 days down to 45. The motivation is security, since a leaked key is useful for less time, but the practical effect is that manual renewal is finished. A certificate you rotate by hand, or with a cron job on a fixed schedule, will not keep up. Renewal has to be automatic, and it has to be frequent.
Renewal timing is no longer a guess
Alongside the shorter lifetimes, the authority now tells you when to renew. ACME Renewal Information (RFC 9773, published September 2025) hands the client a suggested renewal window. Instead of picking an arbitrary threshold like "renew when 30 days are left," the client asks the CA and follows the window it returns. That also lets the CA spread renewals out so it is not hit by everyone at once.
What that means for a .NET app
You want a client that runs in process, answers the ACME challenge from your own pipeline, and renews on the CA's schedule with no restart. LettuceEncrypt did the first two but never implemented RFC 9773, and it is no longer maintained. FluffySpoon's EncryptWeMust is in a similar state.
I wrote one for this, AutoHttps (disclosure: I am the author, it is MIT on GitHub). Setup is one call:
builder.Services.AddAutoHttps(options =>
{
options.DomainNames.Add("example.com");
options.EmailAddress = "admin@example.com";
options.AcceptTermsOfService = true;
});
That gets a certificate on first start and keeps it renewed. It answers http-01 from your request pipeline, does dns-01 and wildcards, works with Let's Encrypt or any ACME authority, and has no NuGet dependencies, because the RFC 8555 client is written against the shared framework. For the short-lived certificates above, you opt into the profile:
options.Profile = CertificateProfiles.ShortLived;
The one catch
This only works if Kestrel is the thing terminating TLS. If nginx, IIS, or a load balancer in front holds the certificate, the cert belongs there and an in-process client cannot help. That is the honest boundary: in-process ACME is for the case where your app is the edge.
Coming from LettuceEncrypt
The APIs are close. DomainNames, EmailAddress, and AcceptTermsOfService keep the same names, so most of a migration is renaming the config section and deleting the UseLettuceEncrypt call. There is a short migration guide in the repo that maps the rest.
Repo: https://github.com/astralmaster/AutoHttps
NuGet: https://www.nuget.org/packages/AutoHttps
Top comments (0)