Skip to main content

    How to Automate SSL Certificate Renewal on Windows and IIS

    A Windows renewal has a third step Linux does not: every listener has to be re-pointed at a new thumbprint. Where that breaks, and how to automate it.

    MS
    My-SSL Team
    ·
    15 min read
    ·
    Published September 4, 2026
    ·
    Last updated September 4, 2026

    The short answer

    On Linux a renewal writes a file and reloads a service. On Windows there is a third step in between: every listener references the certificate by its SHA-1 thumbprint, and a renewed certificate always has a new one. An ACME client such as win-acme handles the request, the import into the machine store and the IIS binding, and a scheduled task repeats it. Remote Desktop, Exchange, SQL Server and any binding made directly through http.sys do not update themselves — they keep serving the old certificate, silently, until someone re-points them.

    A Linux certificate renewal has two steps and a Windows renewal has three, with the extra rebinding step being the one that fails silentlyTwo rows compared side by side. The top row shows Linux: step one writes new PEM files to a directory on disk, step two reloads the web server, which reads the same file path it always read. Nothing else has to change, because the path never changes. The bottom row shows Windows in three steps. Step one is the same acquisition over ACME. Step two imports the certificate into the LocalMachine Personal store, where the certificate and its private key are separate objects and the key carries its own access control list. Step three, highlighted in gold, is the rebinding: every consumer references the certificate by its forty character SHA-1 thumbprint, a renewed certificate always has a new thumbprint, so each listener has to be re-pointed at the new value. IIS rewrites its own bindings. Remote Desktop, Exchange, SQL Server and any binding created directly through http.sys do not, and they keep serving the old certificate without reporting an error. A footer notes that the third step is the one that is missing from most Windows automation.The same renewal, one extra step on WindowsLINUX — a path that never changes1 · AcquireNew PEM files land in the same directory.2 · ReloadThe service re-reads the path it already had.WINDOWS — an identifier that changes every time1 · AcquireACME client requestsand receives the chain.2 · Import to the storeLocalMachine\Personal. Thekey is a separate object.3 · RebindRe-point every listenerat the new thumbprint.Who performs step 3 for youIISRewrites its own site bindings. This is the part that usually works.RDP · ExchangeHold their own copy of the thumbprint. Nothing updates it for them.http.sys bindingsAnything registered with netsh outside IIS is invisible to IIS.Step 3 is where Windows automation is usually missing, and it never reports a failure.
    The renewal that "worked" and the site that still shows an expired certificate are the same event, seen from either side of step three.

    Why a Windows renewal has three steps

    A Linux renewal is two operations. New files land at a path, and the service that reads that path is told to read it again. The path is stable, so nothing else has to know a renewal happened. Windows breaks that assumption. A certificate is not a file on disk, it is an object in the machine store, and every consumer addresses it by a forty-character SHA-1 thumbprint that changes on every issuance.

    That single design difference is where most Windows automation goes wrong, and it goes wrong quietly. The client reports success. The certificate really is in LocalMachine\My, really is valid, really does have the right names on it. It is simply not the object your listeners are pointing at, and nothing in Windows raises a flag about that, because from each listener's point of view nothing changed at all.

    There is a second, less obvious consequence. The private key is not part of the certificate object. It lives in its own key container with its own access control list, which means a permission granted to an application pool identity applies to one key and not to its replacement. Both problems have the same shape: something outside the certificate holds a reference to it, and the renewal replaces the thing being referred to.

    Picking a renewal client

    Three clients cover almost every Windows deployment. win-acme is the command-line default and the one most guides assume: it requests the certificate, imports it, rewrites the IIS binding and registers the scheduled task in one pass. Certify The Web wraps the same job in a GUI and adds deployment tasks for non-IIS targets. Posh-ACME is a PowerShell module for people who would rather write the deployment themselves.

    ClientFits whenHandles the rebinding?
    win-acmeIIS is the only consumer, or you are comfortable adding a post-renewal scriptIIS bindings automatically; anything else through a script hook
    Certify The WebSeveral certificates on one box, or a team that wants a console rather than a config fileIIS plus configurable deployment tasks for other targets
    Posh-ACMENo IIS at all, or the deployment is genuinely bespokeNothing by default; you write the deployment step

    The choice matters less than the honest question underneath it: what else on this server presents a certificate? If the answer is only IIS, win-acme on its own is enough and you can stop reading after the next two sections. If the answer includes Remote Desktop or a mail role, the client is only doing part of the job whichever one you pick.

    One practical note on DNS validation. Wildcard names require DNS-01, and on Windows that means storing an API credential for your DNS provider somewhere a background task can read it months from now. That credential is a renewal dependency exactly like the certificate itself, and expired API keys are a common cause of renewals that ran perfectly for a year and then stopped. Which challenge your setup can realistically use is worth settling before the client is installed rather than after, and the constraints behind each challenge type is the shorter route to that decision.

    The scheduled task, and who it runs as

    Windows has no cron, so renewal runs from Task Scheduler. win-acme registers that task for you on first use and it fires daily, doing nothing on most days and renewing when a certificate crosses the threshold. The task normally runs as SYSTEM, which is the detail that decides whether the second cycle works, because you created the certificate as an elevated administrator and SYSTEM is not you.

    A certificate is installed by one Windows identity and renewed months later by a different one, which is why the second cycle failsTwo panels separated by a gold boundary line. The left panel is day zero: an administrator runs the ACME client interactively from an elevated prompt, with an interactive session available for prompts, the ability to write to the machine certificate store, permission to administer IIS, and whatever network access the console session has. Everything works. The right panel is day one hundred and forty five: the scheduled task fires as SYSTEM or as a service account, with no interactive session at all, so anything that prompts hangs instead of failing. It needs its own write access to the store, its own IIS administration rights, its own read access to the client configuration folder, its own DNS API credentials that have not since expired, and its own outbound access to the certificate authority. The gold boundary is labelled with the rule that every capability present on the left has to be present again on the right, because nothing carries across, and the mismatch does not appear until the first unattended run.You install it. Something else renews it.Day 0 — you, at an elevated promptInteractive session, so prompts get answered.Writes to the machine certificate store.Administers IIS as a member of Administrators.Uses your network path to the CA.Reads DNS API keys you just pasted in.Result: it works, first time, every time.nothing carries overDay 145 — the scheduled task, as SYSTEMNo session. A prompt hangs, it does not fail.Needs its own write access to the store.Needs its own IIS administration rights.Needs outbound HTTPS from the server itself.Needs DNS keys that have not expired since.Result: whatever you forgot, discovered here.Force one renewal on install day rather than finding this out five months later.
    Almost every "it worked when I ran it manually" report is this picture: two identities, and a permission that only ever existed for the left-hand one.

    Everything the interactive run had, the scheduled run needs again. Write access to the machine certificate store. Rights to administer IIS. Read access to the client's configuration folder. Outbound HTTPS from the server itself, which is not the same as outbound HTTPS from your workstation. On a domain-joined server that also has to reach a DNS API or a file share, a dedicated service account with the Log on as a batch job right is usually easier to reason about than SYSTEM, because you can grant it what it needs and see what you granted.

    There is also a subtlety with no interactive session: anything that would prompt does not fail, it hangs. A client waiting for confirmation at three in the morning leaves a task in the running state and a certificate that quietly does not renew. Run the client once with whatever unattended flag it offers before you trust the schedule.

    Check the renewal threshold while you are in there. win-acme has long defaulted to renewing at 55 days before expiry, which is sensible on a 398-day certificate and increasingly odd as the maximum lifetime falls. On a 47-day certificate, a threshold of 55 days is reached before the certificate exists. Any client that expresses its window as a fixed number of days rather than a proportion of lifetime has to be revisited each time the cap drops, so read the value your version actually uses rather than assuming the default still makes sense.

    The private key ACL problem

    A certificate in the Windows store is two objects, not one. The certificate itself is public and readable by anyone on the machine. The private key sits in a separate container with its own access control list, and a service can only use the certificate if its identity appears in that list. Renewal creates a new key, so it creates a new list, and every grant made against the old key ceases to exist.

    This is why so many Windows setups work for exactly one cycle. An administrator installs the certificate, notices that the application pool cannot read the key, opens certlm.msc, right-clicks the certificate and grants the pool identity read access through Manage Private Keys. It works. Nobody writes it down, because it felt like a one-time fix. Five months later the renewal succeeds, the binding updates, and the site returns an error nobody can trace to a certificate at all.

    win-acme addresses part of this by granting the local Administrators group full control over the private key of certificates it imports, precisely so that the identity which created the certificate interactively and the SYSTEM account that renews it later are not working against different permissions. That helps the client. It does nothing for an application pool running as a custom identity, or for a service account used by SQL Server, which still needs its own grant on every new key.

    There are two durable fixes and one that only looks durable. The durable ones are to have the renewal client re-apply the ACL as part of its deployment step, or to run the consuming service under an identity that is already covered by the grant the client makes. The one that only looks durable is granting the permission by hand and assuming it persists, which is the default behaviour of almost every Windows certificate deployment that has not been tested through a renewal.

    Everything on the box that is not IIS

    IIS updates its own bindings, and that is the part of Windows certificate automation that generally works. Every other listener on the server stores the thumbprint in its own place and reads it from there. None of them watch the certificate store, so none of them notice a renewal, and none of them log anything when the certificate they are pinned to expires underneath them.

    One renewed certificate, five Windows consumers that each store the thumbprint separately, and only one of them updates itselfA single certificate at the top, labelled as having a new SHA-1 thumbprint after renewal, fanning out to five consumers below it. IIS site bindings, highlighted in gold, are the only consumer that the ACME client updates on its own. The other four keep the old value: bindings registered directly with http.sys through netsh, which store an IP, port, certificate hash and application GUID; the Remote Desktop listener, which keeps its thumbprint in the Win32_TSGeneralSetting WMI class under the TerminalServices namespace; Exchange Server, where services are attached to a certificate with the Enable-ExchangeCertificate cmdlet; and other listeners such as SQL Server, WinRM, ADFS and Windows Admin Center, each of which reads a thumbprint from its own configuration. The footer states the practical rule: inventory the listeners before automating, because the client only fixes the one it owns.One new thumbprint, five places that remember the old oneRenewed certificatenew 40-character SHA-1 thumbprintIIS bindingsupdated by theACME clienthandledhttp.sysnetsh sslcertip:port + appidyours to fixRemote DesktopWMI, not a fileTSGeneralSettingyours to fixExchangeservices attachto a thumbprintyours to fixSQL · WinRMADFS, AdminCenter, agentsyours to fixThe symptom is always the sameThe website is fine. Mail clients warn. RDP throws a name-mismatch box. A monitoring agentstops reporting. Nothing logs an error, because from each listener's point of view nothing changed.Inventory the listeners before you automate. netsh http show sslcert is the honest starting point.
    The listeners nobody remembers are the ones with no web page to look at, which is why they are usually found by a user rather than by monitoring.

    Start with an inventory rather than a guess. netsh http show sslcert lists every certificate binding registered with http.sys, including the ones IIS did not create and does not know about, each with its IP and port, certificate hash and application GUID. Anything in that output that IIS did not put there is yours to re-point after every renewal.

    ListenerWhere the thumbprint livesHow to re-point it
    IIS sitesIIS configuration, surfaced through http.sysThe ACME client does it
    Non-IIS http.sys bindingsIP, port, certificate hash and application GUIDnetsh http delete sslcert then add sslcert with the new hash
    Remote DesktopWMI: Win32_TSGeneralSetting in Root\CimV2\TerminalServicesSet SSLCertificateSHA1Hash from PowerShell
    Exchange ServerPer-service attachment inside ExchangeEnable-ExchangeCertificate -Thumbprint with the services listed
    SQL Server, WinRM, ADFS, agentsRegistry or per-product configurationProduct-specific; each needs its own step in the script

    Remote Desktop is worth calling out because the format catches people. The value has to be exactly forty hexadecimal characters with no spaces, and a thumbprint copied out of the certificate MMC arrives with invisible spacing that Windows accepts into the field and then refuses to use. Strip it in the script rather than trusting the clipboard.

    Exchange has its own trap. Attaching a renewed certificate to the SMTP service prompts about replacing the default transport certificate, which is fine interactively and unhelpful in a scheduled task. That is one more reason the post-renewal script should be written and run once by hand before anything depends on it.

    None of these produce a helpful error. What you get instead is a user reporting that the mail client warns, or that RDP throws a name mismatch box, weeks after the website stopped having a problem. If your servers present certificates on more than one port, the shape of that problem is covered in more depth in which Remote Desktop role needs which certificate.

    Farms and the Centralized Certificate Store

    Running the same renewal on eight web servers means eight ACME accounts, eight scheduled tasks and eight opportunities for one of them to fail unnoticed. IIS has a better answer for farms. The Centralized Certificate Store keeps certificates as PFX files on a file share, loads them on demand using the name from the client's TLS handshake, and lets every node in the farm read from the same place.

    The mechanics are simple enough to be worth knowing before you commit to it. IIS matches a request to a file by name: a site at www.contoso.com is served from www.contoso.com.pfx, and a wildcard covering it is stored as _.contoso.com.pfx. Every PFX in the store is encrypted with the same password, which IIS holds as an encrypted value in its own configuration. Renewal then becomes one operation instead of eight: overwrite the file on the share.

    Two consequences follow from that design. The shared password is genuinely shared, so rotating it is a change to every server in the farm rather than to the store. And the naming convention is load-bearing: a certificate whose subject does not match the host name IIS is looking for will sit in the share being ignored, with no error beyond a failed handshake. Both are manageable. Neither is obvious from the setup wizard.

    What shorter lifetimes do to the arithmetic

    The CA/Browser Forum approved a schedule in April 2025 that takes the maximum public certificate lifetime from 398 days down to 47 in three steps: 200 days from March 15, 2026, 100 days from March 15, 2027, and 47 days from March 15, 2029. Most certificate authorities issue 199 days today to stay comfortably inside the current cap. Domain validation reuse falls on the same schedule, reaching 10 days in 2029.

    How many times a year each certificate has to be renewed and rebound as the maximum lifetime falls from 398 days to 47A timeline of four steps showing the CA/Browser Forum schedule and its operational cost. Before March 2026 the maximum lifetime was 398 days, so each certificate was renewed about once a year. From March 15, 2026 it is 200 days, which is roughly twice a year, and most certificate authorities issue 199 days to stay safely inside the cap. From March 15, 2027, highlighted in gold, it is 100 days, or about four times a year. From March 15, 2029 it is 47 days, close to eight times a year. Below the timeline, a worked example: ten Windows servers with three listeners each make thirty rebinding operations per renewal cycle, which is thirty a year today and roughly two hundred and forty a year by 2029. The conclusion is that the issuance is not what scales badly, the rebinding is, because it multiplies by listeners rather than by hosts.Renewals per certificate, per yearto Mar 2026398 daysabout 1× a year15 Mar 2026200 daysabout 2× a year15 Mar 2027100 daysabout 4× a year15 Mar 202947 daysabout 8× a yearTen servers, three listeners each30 rebinding operations per cycle · about 30 a year today · about 240 a year from 2029.Issuance scales by host. Rebinding scales by listener, which is why it hurts first.
    The number that decides whether manual renewal is still viable is not how many servers you run, it is how many listeners each one has.

    For a Windows estate the interesting number is not how often the certificate is issued. It is how many rebinding operations that implies. Ten servers with three listeners each produce thirty re-point operations per cycle, which is about thirty a year now and roughly two hundred and forty a year once 47-day certificates arrive. Issuance scales with hosts. Rebinding scales with listeners, and that is the one that stops being survivable by hand first.

    It also changes what a failed renewal costs. On a 398-day certificate a client that renews at 55 days leaves nearly two months to notice a problem. On a 47-day certificate there is no comparable buffer at all, and a renewal that fails twice in a row is an outage rather than an inconvenience. The practical conclusion is that the alerting matters as much as the automation, and it has to run somewhere other than the server it is watching, which is the subject of what to watch on a certificate and where to watch it from.

    Proving the first unattended renewal

    The gap between installing an ACME client and finding out whether it works is months, and that gap is where Windows automation fails. Close it on the day you install by forcing one renewal under the scheduled task's own identity, then checking the things that would have broken. It takes about ten minutes and it replaces a hope with a fact.

    CheckWhat proves it
    The task actually ran as its own identityLast run result of 0 in Task Scheduler, not a manual run from your console
    A new certificate existsGet-ChildItem Cert:\LocalMachine\My shows a new thumbprint and a later expiry
    Every listener movednetsh http show sslcert shows the new hash on every port, not just 443
    The consuming identity can still read the keyThe application pool or service starts and serves without a manual permission grant
    The old certificate is gone from the pathWhat the server presents from outside, checked from a machine that is not the server

    The last row is the one people skip, and it is the only one that reflects what a visitor sees. Everything above it describes the server's opinion of itself. A quick external check against each hostname and port closes that loop, and running it on a schedule is what turns a working automation into one you can stop thinking about.

    Keep the post-renewal script in source control with the rest of the server configuration rather than in a folder next to the client. It is the piece that encodes which listeners exist on that host, it changes when a role is added, and it is the first thing anyone will need when the person who set this up has moved on.

    FAQ

    Frequently Asked Questions

    Get instant answers to common questions about SSL certificates and our services.

    Still Have Questions?

    Our SSL experts are available 24/7 to help with any questions about certificates, installation, or technical issues.