# win-acme: free Let's Encrypt certificates for IIS on Windows

> Use win-acme (wacs.exe) to get Let's Encrypt certificates for IIS: interactive and unattended setup, bindings, scheduled renewal, ARI, DNS validation.

Source: https://ssl.sh/guides/win-acme/
Last updated: 2026-11-10

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:

```powershell
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:

```powershell
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:

```powershell
.\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](https://ssl.sh/guides/iis-ssl-certificate/), 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](https://ssl.sh/tools/ssl-checker/), or from any terminal:

```bash
curl ssl.sh/example.com
```

On the server:

```powershell
.\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:

```powershell
.\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](https://ssl.sh/monitor/) (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](https://ssl.sh/errors/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](https://ssl.sh/errors/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](https://ssl.sh/errors/lets-encrypt-rate-limit/) and test with `--test` against staging.
