--- title: "Windows Certificate Management: certlm, certmgr, and Automating IIS Renewal" canonical: "https://infisical.com/blog/windows-certificate-management" published: "2026-10-05" tags: ["Technical"] source-index: https://infisical.com/llms.txt ---

# Windows Certificate Management: certlm, certmgr, and Automating IIS Renewal

Most Windows certificate work starts when something is about to expire and you need to figure out what. On a server running Internet Information Services (IIS), finding the certificate is easy via the certificate console, but it’s a lot of manual work to get the renewed certificate onto every site and server before the expiry causes an outage.

The basics of Windows certificate management are the same as [managing certificates anywhere](https://infisical.com/blog/certificate-management): you want to keep track of certificates and renew them on time to avoid outages, and ideally automate the process so it stops being manual work. Windows adds a few wrinkles of its own.

## What is Windows certificate management?

Managing certificates on Windows means installing, storing, binding, renewing, and retiring the X.509 certificates that Windows machines and the services on them rely on. On a server, that means certificates for:

* IIS
* Remote Desktop
* Exchange
* SQL Server
* WinRM

It also means the root and intermediate certificates the machine trusts.

Windows offers a few built-in tools:

* The Certificates console (`certlm.msc` for the machine, `certmgr.msc` for the signed-in user)
* `certutil` on the command line
* The PowerShell `Cert:` drive
* IIS Manager for web bindings

Issuance usually happens somewhere else. If your organization strictly runs on Windows, that typically means Active Directory Certificate Services (ADCS) for internal names, a public certificate authority (CA) for anything internet-facing, or both.

For any organization that wants to automate certificate management, the gaps are the problem. Windows provides no inventory across machines, no renewal for certificates from a public CA, and no way to see which sites on which servers depend on a given certificate.

Company laptops and desktops managed through [Intune](https://infisical.com/docs/integrations/app-connections/microsoft-intune) or another MDM are a different job. Their certificates usually arrive through [Microsoft Cloud PKI](https://infisical.com/blog/microsoft-cloud-pki) or another certificate automation tool like [Infisical](https://infisical.com/platform/certificate-management), without anyone touching them.

Windows Server is different, and it is the more likely case for infrastructure and platform engineers who need to automate certificate management.

## What is the difference between certlm.msc and certmgr.msc?

`certmgr.msc` opens the certificate store of the current user. `certlm.msc` opens the store of the local machine, the computer account. Both are the same Certificates snap-in, pointed at different stores.

This difference sounds like a technicality, but services like IIS read only the machine store, not the user store. Running `certmgr.msc` as an administrator does not change this, since it shows the user store of whichever user ran it. If you are looking for a certificate a service uses, open `certlm.msc`.

This is the usual culprit when a freshly imported certificate doesn't show up in IIS. Double-clicking a `.pfx` opens the Certificate Import Wizard with the current user selected, and accepting that default puts the certificate somewhere IIS will never look.

### Which certificate stores matter on a server?

Four stores in the machine store do most of the work. You can reach each with a PowerShell path.

| Store | PowerShell path | What belongs there |
| :---- | :---- | :---- |
| Personal | `Cert:\LocalMachine\My` | Server certificates with their private keys. The default for IIS bindings |
| Web Hosting | `Cert:\LocalMachine\WebHosting` | The same role as Personal, but certificates load on demand rather than all at startup, which suits servers hosting many sites (IIS 8 and later) |
| Intermediate Certification Authorities | `Cert:\LocalMachine\CA` | Chain certificates between your server certificate and its root |
| Trusted Root Certification Authorities | `Cert:\LocalMachine\Root` | Roots the machine trusts, including your internal CA's root |

You can see what expires in the next 30 days on one server:

```
Get-ChildItem Cert:\LocalMachine\My, Cert:\LocalMachine\WebHosting |
  Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) } |
  Select-Object Subject, Thumbprint, NotAfter
```

That answers the question for one machine. Many organizations have dozens or hundreds, which means running it on each one just to find out what *exists*, before anyone renews anything or pushes it to where it needs to be.

## How does IIS use a certificate?

An HTTPS site in IIS requires three things:

* a certificate in the machine store
* the private key that belongs to it
* a binding that tells the web server which certificate to present

The first two are easy to find because you can open the certificate from `certlm.msc`. You can verify you have the private key because the General tab says "You have a private key that corresponds to this certificate" when it is present. Without it the certificate is useless to IIS.

The certificate association does not live in IIS configuration. IIS Manager writes it to `HTTP.sys`, the kernel-mode listener that terminates TLS. The binding exists as a certificate thumbprint and a store name registered against either an IP address and port (`0.0.0.0:443`) or a host name and port when Server Name Indication (SNI) is on (`www.example.com:443`). You can read the real bindings directly:

```
netsh http show sslcert
```

The binding names one specific certificate by its thumbprint, a hash of the certificate itself. A renewed certificate is a new certificate with a new thumbprint, and servers don’t automatically update the binding to point at it. Almost every IIS renewal problem traces back to that.

## How do you renew an SSL certificate in IIS manually?

Renewing by hand means issuing a new certificate and then moving every binding onto it:

1. In IIS Manager, select the server, open **Server Certificates**, and choose **Create Certificate Request**. This generates a new key pair and a certificate signing request (CSR).
2. Submit the CSR to your CA and download the issued certificate.
3. Back in **Server Certificates** on the same server, choose **Complete Certificate Request** and select the file. The private key has been waiting on that server since step 1, so completing anywhere else produces a certificate with no key.
4. For each site using the old certificate, open **Bindings**, edit the HTTPS binding, and select the new certificate.
5. Run `netsh http show sslcert` and confirm the hash matches the new thumbprint.
6. Export the certificate with its private key as a `.pfx` backup, and remove the old certificate once nothing uses it.

Steps 4 and 5 repeat for every site and every server. From PowerShell, the rebinding in step 4 looks like this for an SNI binding:

```
$cert = Get-ChildItem Cert:\LocalMachine\My |
  Where-Object { $_.Subject -eq "CN=www.example.com" } |
  Sort-Object NotAfter -Descending | Select-Object -First 1

netsh http update sslcert hostnameport=www.example.com:443 certhash=$($cert.Thumbprint) appid='{4dc3e181-e14b-4a21-b022-59fc669b0914}' certstorename=MY
```

The `appid` is the fixed identifier IIS registers its bindings under. For a binding without SNI, use `ipport=0.0.0.0:443` instead of `hostnameport`.

### Why not use the Renew button in IIS Manager?

**Server Certificates** offers **Renew**, which looks like the obvious choice but usually isn’t, because most public CAs won't accept what it produces. It builds a renewal request, a CSR signed with the old certificate's key and wrapped with the old certificate chain. ADCS accepts that format, and most public CAs reject it. For a certificate from a public CA, create a net-new request instead.

## What breaks during IIS certificate renewal?

Renewal on any infrastructure comes down to creating a new certificate and getting it to where it needs to be. The steps are simple, but every platform has its edge cases, and on IIS these are the ones that come up most.

### The certificate does not show up in IIS

IIS lists only certificates in the machine store that have a private key. A missing certificate could’ve been imported into the user store or have arrived without its key. The latter can happen when a request is completed on a different server from the one that created it, or when a `.cer` file is imported directly rather than through **Complete Certificate Request**.

If the key is on the machine but no longer linked to the certificate, `certutil -repairstore my <serial number>` reattaches it. If the key is gone, the only fix is a new request and a reissued certificate.

### The site still serves the old certificate

The new certificate is installed but browsers see the old one because the binding holds the old thumbprint. You need to move the binding of every site bound to the old certificate. On a web farm that is every site on every node. `netsh http show sslcert` shows which bindings exist.

### Windows auto-renewed the certificate and the site broke

ADCS autoenrollment lets Windows renew a certificate and archive the old one automatically. IIS will not serve an archived certificate, so the binding stops working even if there’s a valid replacement. IIS 8.5 added **Enable Automatic Rebind of Renewed Certificate** in **Server Certificates**, which moves bindings to the renewed certificate automatically. It only fires on renewals done through Windows certificate enrollment (e.g. autoenrollment or a manual renewal against ADCS). A replacement you import from a public CA is, as far as Windows can tell, just a new certificate, and the rebind never runs.

### Changing one binding removed another

When a server mixes IP-based bindings (`0.0.0.0:443`) and host-name bindings (`www.example.com:443`) on the same port, editing one in IIS Manager can remove an SSL binding you did not touch. After any change on a server like that, check `netsh http show sslcert` rather than trusting what IIS Manager shows.

### An application cannot read the private key

`HTTP.sys` uses the key on the web server's behalf. An ordinary HTTPS binding needs no extra permissions. An application that uses a certificate itself, to sign tokens or authenticate to another service, runs as its application pool identity, and that identity needs read access to the key. To grant this, in `certlm.msc`, right-click the certificate, choose **All Tasks** and then **Manage Private Keys**, and grant `IIS AppPool\<pool name>` access. A renewed certificate normally comes with a new key, so the grant has to be repeated on every renewal.

### Wildcard and multi-name certificates across a farm

A wildcard or multi-name (SAN) certificate usually covers many sites across many servers, which multiplies every step above. Importing the same `.pfx` everywhere gives every server the same thumbprint, which helps with checking, but each server's bindings still have to be moved separately.

## Do you need to restart IIS after changing a certificate?

No. The binding lives in `HTTP.sys`, and a changed binding applies to the next TLS handshake without an `iisreset` or an application pool recycle. Open connections finish on the old certificate. The exception is an application that loaded a certificate into its own process, which keeps using its copy until the pool recycles.

## Why does manual IIS renewal stop scaling?

It stops scaling because certificate lifetimes are getting shorter while the number of bindings stays the same. The [CA/Browser Forum](https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/) set the maximum lifetime of a public TLS certificate at 47 days by 2029, with lifetimes shortening in steps until then. At 47 days, every public certificate needs replacing at least eight times a year, and every replacement means rebinding. A wildcard bound on 20 servers comes to 160 rebinds a year for that one certificate, each one a chance to miss a site.

Internal certificates from ADCS or another private CA are not bound by those rules, but they carry the same manual steps, and many teams are shortening internal lifetimes too.

## How do you automate IIS certificate renewal?

The simplest automation is a script on each server that requests and installs its own certificate. It works, but it is one more thing to write and maintain on every machine, and it only covers Windows.

[ACME](https://infisical.com/blog/automated-certificate-management), the protocol behind most certificate automation, is the standard alternative, and it has clients for Windows too.

### A per-server ACME client

[win-acme](https://github.com/win-acme/win-acme) is an open-source ACME client for Windows. It requests a certificate, installs it into the machine store, updates the IIS bindings, and registers a scheduled task that renews it before expiry. This is great if you have a handful of servers with public certificates because it automates much of the manual work.

But most organizations manage certificates beyond Windows servers. They have workloads elsewhere, certificates in the cloud, a device fleet, or all three, and a per-server client only ever sees the machine it runs on. A centralized certificate management tool like Infisical can automate renewal across all of it.

### Central issuance with push delivery

Central issuance moves renewal off the servers entirely. Certificates are issued and renewed in one place, and a delivery step pushes each renewal to the servers that use it.

[Infisical](https://infisical.com/platform/certificate-management) discovers the certificates your servers already serve, and issues and automatically renews certificates from a public CA, a private CA, or your existing ADCS. A [Windows Server certificate sync](https://infisical.com/docs/documentation/platform/pki/applications/certificate-syncs/windows-server) delivers each renewed certificate as a `.pfx` bundle or PEM files over WinRM, through a Gateway running inside your network, so nothing has to be opened to the servers from outside it.

A PowerShell command runs on the server after each delivery to import the certificate and move the binding, so a renewal reaches the site without anyone logging in. Moving an HTTP.sys binding needs a local administrator, and that right cannot be delegated, so give the rebinding step its own clearly labeled sync rather than raising the privileges of one that only delivers files.

For a larger estate, four more details matter:

- **A health check** runs before delivery, for example confirming the `W3SVC` service is running, and again once a day. A host that stops being ready is reported when it happens rather than on the day the certificate expires.
- **One directory (LDAP) connection** serves the syncs for every server in the domain with a single service account, so 50 servers do not mean 50 stored credentials to rotate.
- **File permissions** on the delivered files restrict which accounts can read the private key.
- **The private key** is generated centrally and delivered with the certificate, rather than generated on the server. If your policy requires keys to be created where they are used, keep the ACME model for those hosts.

The two models also combine. Infisical exposes an [ACME endpoint that win-acme can use](https://infisical.com/docs/documentation/platform/pki/guides/applications/windows-server-acme), including for a profile backed by ADCS, which gives a per-server client access to internal certificates without adding ACME to the CA itself.

To get started with Infisical Certificate Management, [start a free trial](https://app.infisical.com/signup) or [talk to an expert](https://infisical.com/talk-to-us).

Human mode