How-to guide · Automate renewal
How to automate certificates on Windows with win-acme
In one sentence
win-acme gets Let's Encrypt certificates for your IIS sites, binds them, and renews them every day from a scheduled task that follows the CA's renewal advice.
- Task
- Automate renewal
- Platforms
- Windows
- IIS
- Who it is for
- Level
- Practitioner · 6 steps
On this page
Before you start
- Windows Server with IIS, and an administrator account.
- Public DNS records for every name, pointing to this server, and port 80 reachable from the internet. win-acme answers the HTTP-01 challenge itself, next to IIS.
- IIS sites with host-name bindings for those names, so win-acme can find them.
- For wildcard names, a DNS validation plugin instead: see wildcard certificates with DNS-01.
Why it matters: Let’s Encrypt certificates last 90 days by default, and that drops to 64 days from 10 February 2027. Manual renewals on IIS do not keep up.
Steps
1. Download and unpack it to a permanent folder
Download the current release from win-acme.com; on 20 October 2026 that was version 2.2.9.1, and the “trimmed” build suits most servers. Unzip it to %ProgramFiles%\win-acme, as the getting-started guide recommends, not to Downloads or a temporary folder: the renewal task runs from there.
The scheduled task runs as SYSTEM and executes wacs.exe and any scripts in that folder, so only administrators may be able to change it. %ProgramFiles% has that protection by default.
2. Rehearse on the staging CA
Open an administrator PowerShell in that folder and start win-acme in test mode, which uses Let’s Encrypt’s staging server and its higher rate limits:
cd "$env:ProgramFiles\win-acme"
.\wacs.exe --test
Go through step 3 with staging first. Staging certificates are not trusted by browsers, which is expected. Remove the test renewal afterwards from the main menu’s renewal manager.
3. Create the certificate and binding
Run .\wacs.exe without --test and choose N (“create a new certificate with default settings”). win-acme then:
- lists the IIS sites and bindings, and asks which names to include;
- registers an ACME account (you accept the terms and give an email address);
- proves control of each name over HTTP with its own self-hosting plugin;
- stores the certificate in the computer’s
WebHostingstore (orMy, whereWebHostingdoes not exist), with a non-exportable key; - creates or updates the HTTPS bindings: port 443 on all IP addresses, per host name (IIS installation plugin);
- creates the scheduled renewal task, if it does not exist yet.
The same in one unattended command, built from the command-line reference and the IIS source plugin:
.\wacs.exe --source iis --siteid 1 --host www.example.com,example.com --installation iis --accepttos --emailaddress ops@example.com
Find the site ID with Get-IISSite.
4. Check the renewal task and its settings
Get-ScheduledTask | Where-Object TaskName -like 'win-acme*' | Format-List TaskName, State, Principal
The task runs once a day and renews what is due. Its timing comes from settings.json next to wacs.exe, which win-acme creates from settings_default.json on the first run. In the 2.2.9.1 download the defaults are:
{
"RenewalDays": 55,
"RenewalDaysRange": 0,
"RenewalMinimumValidDays": null,
"RenewalDisableServerSchedule": false,
"RandomDelay": "04:00:00",
"StartBoundary": "09:00:00",
"ExecutionTimeLimit": "02:00:00"
}
RenewalDays counts from issue: 55 days fits a 90-day certificate. RenewalMinimumValidDays (empty means 7 days) forces renewal when little time is left (settings reference). RenewalDisableServerSchedule: false means win-acme follows the CA’s suggested renewal time through ARI, RFC 9773, on the IETF standards track, when that is earlier than its own schedule; keep it that way. Version 2.2.9 moved to the ARI version Let’s Encrypt uses, and the release notes say 2.2.3 to 2.2.8 “are currently reporting non-fatal errors” for it (release notes), so upgrade older installations.
Plan for shorter lifetimes. With the default dropping to 64 days and then 45 days from 16 February 2028, a fixed 55 days leaves little or no margin whenever ARI gives no answer. Our advice, not win-acme’s documented default: lower RenewalDays to about two-thirds of the lifetime, and keep ARI on for earlier renewals.
5. Prove that renewal works
.\wacs.exe --renew --force --verbose
--force renews “disregarding the validity of the current certificates and the prefered schedule”. Each forced run against production issues a real certificate and counts towards the limit of up to 5 certificates for the exact same set of names every 7 days, so do this once, or rehearse it with --test.
6. Other services on Windows
The download’s Scripts folder contains installation scripts for Exchange, Remote Desktop Gateway, SQL Server, ADFS and Java keystores, among others. win-acme can also write PEM or PFX files for software that reads files, such as Apache or nginx on Windows.
Check it worked
On the server:
Get-ChildItem Cert:\LocalMachine\WebHosting, Cert:\LocalMachine\My -ErrorAction SilentlyContinue |
Where-Object Issuer -like '*Let''s Encrypt*' | Format-Table Subject, NotAfter, Thumbprint
Get-IISSiteBinding -Name "Default Web Site"
From another machine, check the chain the site sends:
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | grep -E '^ [0-9] s:|^ i:|Verify return code'
You want the server certificate, the Let’s Encrypt intermediate, and Verify return code: 0 (ok). The lifetime calendar shows when renewals fall:
If something goes wrong
- Validation fails. Check each name’s A and AAAA records, port 80 in the firewall and any load balancer in front, then rerun with
--verbose. The logs are in%ProgramData%\win-acme\, in aLogfolder under the ACME server’s name (for exampleacme-v02.api.letsencrypt.org). Let’s Encrypt allows only up to 5 failed validations per name, per account, per hour, so debug with--test. - The site still shows the old or an expired certificate,
NET::ERR_CERT_DATE_INVALID. The task did not run (check its last result in Task Scheduler), or the binding belongs to a site win-acme does not manage. Bindings that used the previous certificate are updated on renewal. - Some clients report
unable to verify the first certificateorThe remote certificate is invalid. Windows did not send the intermediate. See install a certificate in IIS, step 3. - The task fails although manual runs work. It runs as
SYSTEM: the folder must not be in a user profile, and scripts must not depend on a user’s drive mappings or credentials.
Why this works
win-acme is an ACME client. It proves control of each name by answering an ACME challenge on port 80, finalizes the order with a CSR, then puts the new certificate and key into the Windows store and points the IIS bindings at it. The daily task repeats this when a certificate is due or the CA asks for an earlier renewal. See ACME and the 47-day schedule, Proving you own the name and Inventory, expiry and renewal.
Go deeper
- win-acme: getting started: installation and the first certificate.
- win-acme: automatic renewal: the scheduled task and when it renews.
- win-acme: settings: every option in
settings.json. - Let’s Encrypt: rate limits: what each limit means.
- RFC 9773: ACME Renewal Information.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.