Windows

How to use win-acme to get Let's Encrypt certificates for IIS

By · Last verified

win-acme (wacs.exe) reads the IIS bindings, obtains a Let's Encrypt certificate for the site, adds or updates its HTTPS binding, and creates a scheduled task that renews the certificate automatically.

The steps apply to win-acme 2.2.x (2.2.9.1 is the version offered on the project site as of November 2026; check win-acme.com for the current release) on Windows Server 2019, 2022 and 2025 with IIS 10.

Prerequisites

win-acme runs on the IIS server itself with administrator rights.

  • Windows Server with IIS and a site that has an HTTP binding with host name example.com (and www.example.com if needed).
  • DNS A/AAAA records for those names pointing at the server, for example 203.0.113.10.
  • Inbound TCP 80 and 443 open in Windows Firewall and any network firewall, unless you use DNS validation.
  • Outbound HTTPS to acme-v02.api.letsencrypt.org.

Step 1: Download win-acme

Download the x64 "trimmed" zip from win-acme.com (or the pluggable build if you need DNS plugins), and extract it to a permanent folder, because the scheduled task points there:

New-Item -ItemType Directory -Force C:\Tools\win-acme
Expand-Archive -Path $HOME\Downloads\win-acme.v2.2.9.1.x64.trimmed.zip -DestinationPath C:\Tools\win-acme

Adjust the zip file name to the version you downloaded.

Step 2: Create the certificate interactively

Start an elevated PowerShell and run:

cd C:\Tools\win-acme
.\wacs.exe

Choose N: Create certificate (default settings), pick the IIS site, select the bindings (host names) to include, accept the Let's Encrypt terms, and optionally enter an email address. win-acme validates each name over HTTP, stores the certificate, adds an HTTPS binding on port 443 with SNI for each host name, and creates the scheduled task.

Step 3 (alternative): Unattended setup

For scripted deployments use the same plugins from the command line:

.\wacs.exe --source iis --siteid 1 --host example.com,www.example.com `
  --installation iis --accepttos --emailaddress admin@example.com

Find the site ID with Get-Website | Select-Object ID, Name. For a wildcard or a server without inbound port 80, add a DNS validation plugin, for example --validation cloudflare --cloudflareapitoken <token> with the pluggable build; see the win-acme command-line reference for other providers.

Step 4: Redirect HTTP to HTTPS

win-acme does not add a redirect. Use the URL Rewrite rule from installing an SSL certificate on IIS, and keep the HTTP binding in place so the redirect and future HTTP-01 validations keep working.

Verify

The public site should present the Let's Encrypt certificate, and the server should list the renewal, the HTTPS binding and the win-acme scheduled task. Check the public site with the SSL checker, or from any terminal:

curl ssl.sh/example.com

On the server:

.\wacs.exe --list
Get-WebBinding -Name "Default Web Site" -Protocol https
Get-ScheduledTask | Where-Object TaskName -like "win-acme*"

Automatic renewal

The scheduled task runs wacs.exe --renew every day at 9:00 by default. A certificate is renewed 55 days after issuance (RenewalDays), earlier if Let's Encrypt's ARI response suggests it (unless RenewalDisableServerSchedule is set), and in any case when fewer than 7 days of validity remain. After renewal win-acme updates the IIS bindings to the new certificate.

Test the whole path without waiting:

.\wacs.exe --renew --force --test

--force spends a real certificate order, so use it sparingly and not in a loop. Settings live in settings.json next to wacs.exe. Add the site to ssl.sh monitoring (in development), since Let's Encrypt no longer emails expiry warnings.

Troubleshooting

  • Validation fails with a timeout or connection error: port 80 is blocked, DNS points elsewhere, or a redirect sends the challenge to another host; the causes match certbot timeout during connect.
  • Unauthorized (403) on the challenge URL: another IIS feature (authentication, URL rewrite to HTTPS on a different host) intercepts /.well-known/acme-challenge/; exclude that path.
  • CAA record prevents issuance: see CAA record prevents issuance.
  • Renewal task never runs: the task was created under a user that lost permissions, or the win-acme folder moved; recreate it from the main menu (More options → Manage scheduled task) and check Task Scheduler history.
  • Too many failed validations: you retried too quickly; see Let's Encrypt rate limits and test with --test against staging.

FAQ

Does win-acme need port 80 open?

For the default HTTP-01 validation, yes: Let's Encrypt connects to http://example.com/.well-known/acme-challenge/... on port 80. If port 80 is closed or you need a wildcard, choose a DNS validation plugin instead.

Will 55-day renewal still work when certificates get shorter?

Only with ARI enabled and RenewalDays reviewed. The fixed default was chosen for 90-day certificates. win-acme also honours ARI suggestions and renews when fewer than 7 days remain, but before Let's Encrypt's 64-day default arrives on February 10, 2027, review RenewalDays in settings.json and keep ARI enabled. Check the win-acme release notes for changes to these defaults.

Can win-acme use a CA other than Let's Encrypt?

Yes. Pass the CA's ACME directory with --baseuri (and External Account Binding credentials if the CA requires them). Make sure your CAA records allow that CA.

Sources

  1. win-acme
  2. win-acme: Getting started
  3. win-acme: Settings reference
  4. win-acme: Command line reference
  5. Let's Encrypt: Challenge Types