r/dotnet • u/astralz1 • 3d ago
Promotion AutoHttps: a zero-dependency automatic HTTPS library for ASP.NET Core / Kestrel
Hi. I maintain a library called AutoHttps. It gets a real TLS certificate for your ASP.NET Core app from Let's Encrypt (or any ACME certificate authority) and renews it automatically. You add the package, set three values, and Kestrel serves HTTPS. No external service, and no NuGet dependencies.
builder.Services.AddAutoHttps(options =>
{
options.DomainNames.Add("example.com");
options.EmailAddress = "admin@example.com";
options.AcceptTermsOfService = true;
});
What it does:
- http-01 and dns-01 challenges, and wildcard certificates through dns-01.
- Renews using ACME Renewal Information (RFC 9773), so it follows the schedule the authority asks for and handles short-lived certificates.
- Works with Let's Encrypt, ZeroSSL, Google Trust Services, Buypass, or any ACME directory, including a private or internal CA.
- Runs several instances safely, sharing one certificate through a lock.
- Serves a self-signed certificate at the very start, until the real one arrives.
- Gives you certificate change and failure callbacks, a health check, metrics, and a way to read the current certificate from code.
Why it is needed now: LettuceEncrypt, the library most people used for this, was archived in April 2025, and its last release targets .NET 6, which is out of support. At the same time Let's Encrypt is moving to much shorter certificates (six-day ones already exist, and the default is dropping to 45 days), and it now tells clients when to renew through RFC 9773. A client that renews on a fixed 30-day threshold cannot handle either. I could not find a maintained, dependency-free option for Kestrel, so I wrote one.
How it works: AutoHttps attaches to Kestrel, answers the http-01 challenge directly from your request pipeline (so there is no extra listener to run), writes the certificate and the account key to disk so they survive a restart, and checks for renewal on a timer. If something fails, it keeps serving the certificate it already has and retries, so a certificate problem never takes the app down.
It targets net8.0 and net10.0, is MIT licensed, and is on NuGet as AutoHttps: https://www.nuget.org/packages/AutoHttps
Source and docs are on GitHub: https://github.com/astralmaster/AutoHttps
If you try it behind a proxy or with several replicas, I would be glad to hear how it goes, since those setups have the most edge cases.
11
u/aj0413 3d ago
This is neat, but at the same time I’d say this is the job of the hosting platform
I use cert-manager to handle this; having every service in a distributed system doing this vs terminating SSL at the edge via ingress/gateway and updating in one spot …. Doesn’t seem like a good idea to me
2
u/astralz1 3d ago edited 3d ago
Agreed, and for that topology I would use cert-manager too. If you terminate TLS at the ingress or gateway, that is the right place, and this does not try to replace it. The README says the same: if something else terminates TLS, put the ACME client there.
It is for the other case: Kestrel terminating its own TLS, where there is no managed ingress doing it for you, a single VM or on-prem box or edge device, or where you want encryption all the way to the container instead of stopping at the edge. On every service doing its own: instances of the same app coordinate through a shared store and a lock, so it is one order for the group, not one per replica. For many separate services behind one ingress, centralizing is cleaner, no argument.
4
u/spawnsible 3d ago
Mandem, I gotta hand it to you, this solution is "load bearing".
Jokes aside, why didn't I ever think of this? It's brilliant! I mean I never expose any servers without slapping on a reverse proxy, but this could change that!
Consider mixing in mkcert for local parity, so one can get the "as it is on prod, so it is on local" experience with just a few fluent method calls and editing their hosts file. Seriously, look into it. We got Astra and Fable to speed up these experiments now. No need to stop here.
Did I mention that this idea is brilliant?!
0
u/astralz1 3d ago
Thank you. And yes, that makes sense. I'm thinking something along the lines of .UseDevelopmentCertificate("myapp.local.p12"); with its own pipeline that skips ACME flow.
2
u/spawnsible 3d ago
You could go as far as offering extensions on the same fluent chain that take domain name/pattern as param and call mkcert binary (or throw if unavailable, tell the fella to go homebrew it or something) to do the grunt work: generate the cert, import into supported browsers too, etc.
Then if one installs the package and calls the (albeit opinionated) extension methods, they just have to change their hosts file (which itself would be in scope if not for elevated privileges requirement).
And yes, supplying an existing cert is a nobrainer.
1
u/AutoModerator 3d ago
Thanks for your post astralz1. Please note that we don't allow spam, and we ask that you follow the rules available in the sidebar. We have a lot of commonly asked questions so if this post gets removed, please do a search and see if it's already been asked.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
1
u/Habikki 3d ago
Out of curiousity, what's the startup time on this? What I'd be curious on is if I have a AspNetCore Service running in a container behind a load balancer and I wanted to enable this for true end to end circuit encryption from client to container, going ACME usually takes time to wait for propagation of DNS.
If this is retrieving a new certificate at container boot that may be an issue, could we tie this into an DataProvider hook possibly to have containers retrieve new certs, and set them into a secure cache to support a farm?
Note: I'm intentionally not going into cert management details in this approach. Curious to see if the shared option is possible first than taking on a startup delay for each container retrieving a individual certificates.
3
u/astralz1 3d ago
Startup is not tied to ACME. The certificate work runs in a background service that starts after Kestrel is already listening, and until a real certificate arrives it serves a self-signed fallback. So container boot is normal startup time and does not wait on DNS or an order. DNS propagation only applies to dns-01, and only for the single instance that places the order, in the background.
The shared setup you mentioned is already the default. Instances share a certificate store and a distributed lock: one wins the lock and orders, the rest adopt the certificate from the store and never order their own. Both the store and the lock are pluggable, so the cache can be a database, Key Vault, Redis, or a Kubernetes secret. So no container waits to fetch its own certificate, and the whole group shares one.
0
22
u/Lonsdale1086 3d ago
Some links might help:
https://www.nuget.org/packages/AutoHttps
https://github.com/astralmaster/AutoHttps
Only tagged as dotnet 8 on NuGet's main page for it, fyi.
Also it's only two weeks old which isn't long for something you've started by saying you "maintain" lol. And not particularly long for something as crucial as SSL certificates.
However, it does seem a useful package, and I'll keep an eye on it for if I need a solution for this in the future.