Skip to content

SSL Certificates on Windows Server Without IIS

decerto edited this page Aug 11, 2026 · 1 revision

SSL certificates on Windows Server without IIS

You do not have to buy a certificate, and you do not have to renew one by hand. Let's Encrypt issues free certificates that last 90 days, and every tool below renews them automatically. What follows is how to do that on Windows when IIS is not in the picture.


The three ways

Tool Best for Renewal
Caddy You are already using it as your web server or reverse proxy Built in. Nothing to configure, nothing to schedule
win-acme You need a certificate in the Windows certificate store — for IIS, RDP, Exchange, a .NET service A scheduled task it creates for you
Posh-ACME Scripted or unusual cases, and DNS providers the others do not support Your own scheduled task

If your sites sit behind Caddy, stop reading after the next section.


Caddy: three lines, including HTTPS

example.com, www.example.com {
    reverse_proxy 127.0.0.1:3001
}

On first start Caddy obtains a certificate for both names, redirects HTTP to HTTPS, and renews at roughly two-thirds of the lifetime. Certificates are stored under %AppData%\Caddy (or the service account's equivalent) and no scheduled task is involved.

Requirements: the domain must resolve to the server, and inbound port 80 must be reachable — unless you use the DNS challenge below.


The DNS challenge, and why you want it

The default (HTTP-01) challenge proves you control the domain by answering a request on port 80. That fails if your host blocks 80, if you are behind a proxy that terminates TLS itself, or if the domain does not point at the server yet — which is exactly the moment you are trying to set the site up.

DNS-01 proves it by writing a TXT record instead. Nothing inbound is needed, and it is the only way to get a wildcard certificate.

With Cloudflare and a Caddy build that includes the module:

tls {
    dns cloudflare {env.CF_API_TOKEN}
}

The token needs Zone:DNS:Edit on the zones concerned. Keep it out of the config file itself — an environment variable on the service is safer, because Caddy rewrites its own config to a location a local account can read.

WinPanel does this per site: one Cloudflare token per website, held encrypted, injected as an environment variable, with a separate TLS policy per token so one customer's token never issues for another customer's domain.


win-acme, when the certificate must be in the Windows store

RDP, Exchange, a .NET service or IIS itself all read from the certificate store rather than from a PEM file. win-acme is the tool for that: run wacs.exe, follow the menu, pick the binding or enter the hostname, and it creates a scheduled task for renewal.

It can validate over HTTP or DNS, and it can run a script after each renewal — which is how you get a renewed certificate into a service that only reads its own copy at startup.


The Windows-specific traps

The clock. TLS is time-sensitive and ACME doubly so. If the Windows Time service is stopped — which happens on VMs and on machines that have been imaged — issuance fails with errors that blame everything except the clock. Start W32Time and set it to automatic.

Port 80 is not optional for HTTP-01. Not for the certificate, not even if your site is HTTPS-only. Use DNS-01 if you cannot open it.

Cloudflare's orange cloud. With the proxy on, your domain resolves to Cloudflare, not to you, so HTTP-01 validation never reaches your server. Either use DNS-01 or turn the proxy off while issuing.

Rate limits. Let's Encrypt allows 5 duplicate certificates per week. Debug against their staging endpoint, not production, or you will lock yourself out for days.

www is a separate name. A certificate for example.com does not cover www.example.com. Both names must be listed, or visitors to www get a browser warning — or, behind Cloudflare, a 525 handshake failed.


Related

Clone this wiki locally