Skip to content

TLS certificates on Windows: win-acme, IIS binding and renewal

Verified 2 min read

Request certificates with win-acme, bind them to IIS, export PEM for Nginx, and prove renewal works before the old certificate expires.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

On Windows/IIS, win-acme is the practical ACME client:

  1. Create/renew a certificate.
  2. Install it into the Windows store.
  3. Bind it to the IIS site.
  4. Schedule renewal.
  5. Test renewal before expiry.

For Nginx, export PEM (fullchain.pem + privkey.pem) and reload Nginx after renewal.

Download the x64 zip, extract to C:\win-acme, and run wacs.exe as Administrator. The interactive menu is the safest first run:

  • N new certificate;
  • choose Manual input or IIS site;
  • select the site/host;
  • choose HTTP-01 (port 80) or DNS-01 (wildcard/internal);
  • choose store: Windows store / PEM files;
  • install to IIS;
  • create the renewal task.

CLI shape (verify against wacs --help for your version):

Terminal window
C:\win-acme\wacs.exe --target iis --host lab.example `
--installation iis --store certificatestore

Do not paste a CLI from an old blog without checking the current version’s options.

If win-acme installs to IIS, it creates/updates the HTTPS binding. Verify:

Terminal window
Get-WebBinding -Name 'Lab' -Protocol https
netsh http show sslcert hostnameport=lab.example:443

For SNI, use a hostname:port binding and keep SslFlags 1. An IP-only binding cannot serve multiple certificates on one IP.

Nginx does not read the Windows store. Export:

  • certificate + intermediates as fullchain.pem;
  • private key as privkey.pem;
  • ACL the key to the service account + Administrators.

Then:

ssl_certificate C:/nginx/certs/fullchain.pem;
ssl_certificate_key C:/nginx/certs/privkey.pem;

Reload Nginx after every renewal (nginx -s reload); replacing files without reload keeps the old cert in memory.

Terminal window
Get-ChildItem Cert:\LocalMachine\My |
Where-Object Subject -like '*lab.example*' |
Select-Object Subject,NotAfter,Thumbprint

Check the renewal task exists and has run. Force a dry run/renewal in a maintenance window. A certificate that renews but does not rebind is still an outage.

  • Let’s Encrypt has rate limits; do not loop failed validations.
  • Wildcards require DNS-01; HTTP-01 cannot issue *.example.com.
  • DNS-01 credentials are powerful; store them with least privilege.
  • Internal names cannot get public certificates; use an internal CA or tls internal (Caddy lab).

E1. The lab used a self-signed certificate for WAC and did not run win-acme; the commands are the production path to validate on Server 2025.

Sources