How to Migrate an Issuing CA to a New Server – Step-by-Step with Rollback

Core365 banner titled How to Migrate an Issuing CA to a New Server with the same name and a new IP
Spread the love

Last Updated: October 2026

Short answer: To migrate an issuing CA to a new server that keeps its name but gets a new IP address, freeze issuance, take a final certutil -backup of the key, database and registry, and power off the old server. Then join the new server to the existing computer account, import the CA key, restore the database and registry, and publish fresh CRLs. A CA’s identity is its name and key pair, not its IP, so the only network work is DNS, firewall ports and CDP/AIA hosting.

In our environment, the enterprise issuing CA ran on Windows Server 2012 R2 in one cloud network. It had to move to a Windows Server 2016 VM in a different network and keep the same computer name. Therefore the IP, the subnet and every firewall path changed, while the CA name, its key and its published URLs could not.

This guide is the runbook we used, plus the traps we hit. It covers the ports to open, pre-tests, the migration phases with a rollback at every stage, and post-migration tests. All names, domains and IPs are sanitized examples.

How to migrate an issuing CA to a new server: the big picture

An issuing CA is the subordinate certification authority that signs end-entity certificates for computers, users and services. An enterprise issuing CA also integrates with Active Directory, so its templates, enrollment object and CDP/AIA containers live in AD rather than on the server.

That split is what makes the same-name approach work. The AD objects already match the CA name, so they stay valid. As a result, you only move what lives on the server itself.

ComponentWhere it livesHow it moves
CA private key and CA certificatesMachine store, in a key storage provider (KSP or CSP)certutil -backup exports a password-protected .p12; import it on the new server
CA database (requests, issued and revoked certificates)C:\Windows\System32\CertLog by default (.edb plus logs)certutil -backup and certutil -restoreDB
CA configuration (CDP/AIA, CRL periods, flags)HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configurationreg export and reg import
Published certificate templatesActive Directory (Enrollment Services object)Nothing to move; verify with certutil -catemplates
CA identity in ADEnrollment Services, AIA and CDP containersNothing to move while the CA name stays the same
CRL and CA certificate files for HTTPCertEnroll folder plus an IIS virtual directoryCopy files the new CA will not regenerate; recreate the virtual directory
CAPolicy.inf%windir%Copy it if it exists
OCSP, NDES, web enrollmentSeparate rolesMigrate or rebuild each one on its own

Microsoft documents the same backup-and-restore principle in its AD CS migration guide. It also says that if you keep the role on the source server, you must disable the CA service and shut that server down before the destination comes up.

We take that second path on purpose. The old server stays intact but offline, which gives you a clean rollback for 30 days.

Migrate issuing CA to new server: six migration phases with rollback points A, B and C Phases 1 to 3 run on the old server and phases 4 to 6 run on the new server. Rollback A covers phases 1 and 2, B covers phase 3, and C covers phases 4 to 6. Old server (stays intact, then offline) New server (same name, new IP) 1. Freeze Fresh CRLs Block RPC, then final backup 2. Stop old CA Disable certsvc Copy backup off the server 3. Old VM off Stop the VM Snapshot or image the disks 4. Join Reset account Rename, join with the same name 5. Restore CA Import key Restore DB and registry, IIS files 6. Validate Test certificate Revoke, CRL, pkiview, ports Rollback A: re-enable certsvc, remove the block rule Rollback B: start the old VM, then A Rollback C: stop the new VM, start the old VM, repair its secure channel, point DNS back to the old IP, then A Core365 Cloud | blog.core365.cloud
Figure 1: the six migration phases and the three rollback points used in this guide.

Lab scenario and naming used in this guide

Every name below is an example. The IP addresses come from the reserved documentation ranges 192.0.2.0/24 and 198.51.100.0/24, so none of them is a real address.

ItemExample valueNotes
AD domaincore365.cloudNetBIOS name CORE365
Issuing CA host (old and new)ISSCA01 (issca01.core365.cloud)Same name on both servers
CA common namecore365-ISSCA01-CAEnterprise subordinate CA
Old IP / new IP192.0.2.10 / 198.51.100.20Different networks
Offline root CACore365-RootCA on ROOTCA01Standalone, powered off
CDP/AIA aliaspki.core365.cloudCNAME to issca01.core365.cloud
Domain controllerDC01.core365.cloudUsed for all AD checks
Test member serverTESTVM01Disposable VM for the issuance test
Old OS / new OSWindows Server 2012 R2 / Windows Server 2016 DatacenterRestore works to the same or a newer OS
Backup folderC:\CABackup-FinalHolds the .p12, DataBase, .reg file and a CertEnroll copy

Pre-migration checks before you migrate the issuing CA

Run these read-only checks on the old CA first. They decide whether a plain backup and restore will work. They also give you a baseline to compare against later.

Check the key provider and exportability

The key location decides your whole plan. A software key storage provider (KSP) or legacy CSP exports with certutil -backup. A hardware security module (HSM) needs the vendor’s procedure instead.

certutil -store My
certutil -getreg CA\CSP\Provider
certutil -getreg CA\CSP\HashAlgorithm
certutil -cainfo type
certutil -cainfo

In our case the provider was Microsoft Software Key Storage Provider. The store showed Private key is NOT plain text exportable, which is normal for CA keys. The backup still exported the key, and we proved it later with certutil -dump.

Also read CA cert count. Our CA reported 8 CA certificates (V0.0 to V7.0) that share one key, because it had been renewed several times with the same key. CA cert[0]: Unavailable is normal when the first certificate has expired. Note the thumbprint of the newest certificate, because you will select it on the new server.

The hash algorithm also travels with the registry. Ours was SHA1. Therefore treat a move to SHA256 as a separate change, not part of this migration.

Stop here if the key cannot be exported. If certutil -backupKey fails with 0x80092004, the key is not exportable. You cannot move that key, so you would renew or re-key the CA instead.

Record the database paths and size

A common mistake I see is querying the database paths under the CA subkey. They live one level up, directly under Configuration, so certutil -getreg CA\DBDirectory fails with ERROR_FILE_NOT_FOUND.

certutil -getreg DBDirectory
certutil -getreg DBLogDirectory
certutil -getreg DBSystemDirectory
(Get-ChildItem C:\Windows\System32\CertLog | Measure-Object Length -Sum).Sum / 1MB

Our database folder was about 287 MB including logs, but the database file itself was only 35 MB. As a result, the backup and restore took seconds.

Review CRL and AIA publishing

certutil -getreg CA\CRLPublicationURLs
certutil -getreg CA\CACertPublicationURLs
certutil -getreg CA\CRLPeriod
certutil -getreg CA\CRLPeriodUnits
certutil -getreg CA\CRLDeltaPeriod
certutil -getreg CA\CRLDeltaPeriodUnits
certutil -getreg CA\CRLFlags
FlagNameMeaning
1CSURL_SERVERPUBLISHThe CA writes the CRL to this location
2CSURL_ADDTOCERTCDPAdd the URL to the CDP extension of issued certificates
4CSURL_ADDTOFRESHESTCRLAdd the URL to the delta CRL (freshest CRL) extension
8CSURL_ADDTOCRLCDPAdd the URL to the CRL itself
64CSURL_SERVERPUBLISHDELTAPublish delta CRLs to this location

The question that matters is whether any URL uses the server name or IP directly. Ours used the alias pki.core365.cloud plus LDAP, so nothing was tied to the old IP. A CNAME like this keeps the URL stable when the host changes; our guide to DNS record types explains how aliases behave.

If a URL with the old IP is already embedded in issued certificates, you cannot fix that afterwards. Keep that IP reachable or plan reissuance.

Two numbers set your outage budget: the base CRL period (ours was 2 weeks) and the delta CRL period (1 day plus overlap). Therefore a long outage can let the delta CRL expire. Keep the window to a few hours. Also check CRLFlags. Ours included CRLF_REVCHECK_IGNORE_OFFLINE, which later explained why the CA could start despite an expired root CRL.

Find dependent roles and consumers

Get-WindowsFeature | Where-Object Installed | Select-Object Name
Get-SmbShare
Get-ScheduledTask | Where-Object { $_.TaskPath -notlike '\Microsoft\*' } | Select-Object TaskName, State
Resolve-DnsName pki.core365.cloud

Our server also ran IIS for CDP/AIA over HTTP, plus CA Web Enrollment. Look for OCSP responders, NDES, scheduled tasks that copy CRLs, and firewall rules that reference the old IP. IIS is not part of the CA backup, so you rebuild it by hand.

Capture a baseline you can compare against

Record these before the change. After the migration, a pass means the numbers match or any difference is explained.

ItemHow to capture itWhy it matters
pkiview statepkiview.msc screenshotShows pre-existing red items, so you do not blame the migration
Request count(certutil -view -out RequestID | Select-String '^Row \d+:').CountProves the restored database matches
CA certificates and active thumbprintcertutil -cainfoExpect the same count and active certificate
Published templatescertutil -catemplatesExpect the same list
CRL numbers and NextUpdatecertutil -dump on the CRL filesConfirms publishing continues
Cert Publishers membershipGet-ADGroupMember "Cert Publishers"Confirms the computer account keeps its SID
Firewall rules for the old IPExport from firewalls and security groupsYou replicate them for the new IP

Choose the target operating system

Restore works to the same or a newer Windows Server version. The database upgrades on first start, and that upgrade is one-way, so keep the old disks for rollback. In our case the target was Windows Server 2016. However, the end of extended support for Windows Server 2016 is January 12, 2027. If you are free to choose, pick a release with a longer support runway.

Which ports must be open on the new CA server?

Clients need TCP 135 and the RPC dynamic range for enrollment, plus TCP 80 for CRL and AIA downloads. The CA itself needs the usual domain member ports to reach domain controllers. Open them on the host firewall, on cloud network security groups and on every firewall between client sites and the new IP.

Inbound ports to the CA

PortProtocolPurposeWho needs it
135TCPRPC endpoint mapper for DCOM/RPC enrollment and remote CA managementClients and admins
49152-65535TCPRPC dynamic ports where the CA service (certsvc) listensClients and admins, or your pinned range
80TCPCDP and AIA over HTTP: CRLs, delta CRLs and CA certificatesAll clients, including non-domain devices
443TCPOnly if you add HTTPS web enrollment, CES/CEP or NDESOptional
445TCPSMB for admin shares and file copyAdmin subnets only
3389TCPRDP managementAdmin subnets only
5985 / 5986TCPWinRM remotingOptional, admins only
ICMP echoICMPDiagnosticsOptional

Outbound ports from the CA

PortProtocolPurpose
53TCP/UDPDNS: resolve domain controllers and register the A record
88TCP/UDPKerberos authentication
135 and 49152-65535TCPRPC to domain controllers (Netlogon, SAM, AD operations)
389TCP/UDPLDAP: read templates, publish CRLs and AIA to AD
636TCPLDAPS, if your domain enforces it
3268 / 3269TCPGlobal catalog (3269 for TLS)
445TCPSMB for Netlogon and SYSVOL
464TCP/UDPKerberos password change (domain join and machine password)
123UDPNTP / Windows Time
80 / 443TCPOnly if you publish CRLs to a separate web server

Cloud and host firewall tips

  • Set a static private IP in the cloud portal. Setting it only inside Windows leaves the NIC open to reassignment. Point the virtual network’s DNS servers at your domain DNS, and add the new subnet to AD Sites and Services.
  • Inventory every rule that mentions the old IP. Security groups, NSGs, site firewalls and ACLs all need an equivalent for the new IP. In our migration this had the longest lead time.
  • Pin the RPC range if you must. Windows uses TCP 49152-65535 by default. If your firewall team refuses that range, restrict RPC with the HKLM\SOFTWARE\Microsoft\Rpc\Internet registry values and reboot. It affects every RPC service on the host, so allow 100 ports or more.
  • Check the Windows Firewall rules on the CA. Run Get-NetFirewallRule -Enabled True -Direction Inbound | Where-Object DisplayName -match 'World Wide Web|COM\+|RPC|Certificate' and confirm HTTP and DCOM/RPC are allowed.

To see which port the CA service actually uses, run this on the CA:

$svcPid = (Get-CimInstance Win32_Service -Filter "Name='certsvc'").ProcessId
Get-NetTCPConnection -State Listen -OwningProcess $svcPid | Select-Object LocalPort

Then test from a client network. Test-NetConnection proves single ports only. The definitive test is certutil -ping, because it exercises the dynamic RPC port as well.

Test-NetConnection 198.51.100.20 -Port 135
Test-NetConnection 198.51.100.20 -Port 80
certutil -config "issca01.core365.cloud\core365-ISSCA01-CA" -ping
A common mistake: testing only from the domain controller subnet. In our run the DC could reach the new CA, but that says nothing about other sites. Test from every network that has clients.

Pre-test the new server before cutover

Every test here has zero production impact. Run them days ahead, so the cutover window contains only the risky steps.

#TestCommand or actionPass criteria
1Reach a DC on AD ports53,88,135,389,445,464 | ForEach-Object { Test-NetConnection DC01.core365.cloud -Port $_ }Every result shows TcpTestSucceeded : True
2Resolve the domain and the aliasResolve-DnsName core365.cloud and Resolve-DnsName pki.core365.cloudDC addresses and the CNAME come back
3Check time syncw32tm /query /statusSmall offset, domain hierarchy as the source
4Client sites reach the new IPTest-NetConnection 198.51.100.20 -Port 135 and -Port 80 from each siteTrue from every site
5Install roles and IISInstall-WindowsFeature ADCS-Cert-Authority, Web-Server, Web-Static-Content, Web-Dir-Browsing, Web-Filtering -IncludeManagementToolsSuccess, no reboot, default IIS page loads on port 80
6Rehearse the backup on the old CAcertutil -backup, then certutil -dump on the .p12Dump lists CA certificates with Encryption test passed
7Rehearse the rollback toolsStop and start the old VM; take a snapshot or imageYou have console access and a restore point
8Check your rightsEnterprise Admin (or delegated) plus local admin on both serversYou can reset the computer account and install an enterprise CA
9Prepare DNSLower the A record TTL (for example to 300 seconds) and list the A, PTR and CNAME recordsThe new TTL is visible from a DC

Clock accuracy matters twice: for Kerberos on the new VM and for CRL validity dates. Cloud VMs can drift against the domain hierarchy, so see our time drift troubleshooting guide if w32tm reports a large offset.

If you have a lab, you can also restore the backup into an isolated copy of your AD, with no route to production. It is the only way to rehearse the full restore without risk. However, most teams rely on a solid rollback plan instead.

Step-by-step: migrate the issuing CA to the new server

Run every command in an elevated PowerShell window. In our run, Install-AdcsCertificationAuthority, Select-String and Resolve-DnsName failed in a cmd window because they are PowerShell-only. That cost us time inside the change window.

Each phase ends with its rollback. The labels A, B and C match the diagram in Figure 1.

Phase 1: freeze issuance and take the final backup (old server)

Publish fresh CRLs first, so clients have maximum validity during the outage. Then block remote enrollment while you back up, so no certificate is issued after the backup.

New-Item -ItemType Directory C:\CABackup-Final -Force | Out-Null
certutil -crl
New-NetFirewallRule -DisplayName "CA-CUTOVER-FREEZE" -Direction Inbound -Action Block -Protocol TCP -LocalPort 135,49152-65535
certutil -ping                                                      # must still work locally
(certutil -view -out RequestID | Select-String '^Row \d+:').Count   # row count A
certutil -backup C:\CABackup-Final                                  # enter and record a strong password
reg export HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration C:\CABackup-Final\CAConfig.reg
robocopy C:\Windows\System32\CertSrv\CertEnroll C:\CABackup-Final\CertEnroll /E
Copy-Item C:\Windows\CAPolicy.inf C:\CABackup-Final\ -ErrorAction SilentlyContinue
(certutil -view -out RequestID | Select-String '^Row \d+:').Count   # row count B, must equal A
certutil -dump C:\CABackup-Final\core365-ISSCA01-CA.p12             # prompts for the password

Block rules override allow rules in Windows Firewall, and local connections are normally unaffected. If your local -ping fails with the rule in place, delete the rule, run the backup quickly and stop the service straight away.

Row counts A and B must match. If they differ, a request slipped in, so take the backup again before moving on.

In the dump, every CA certificate should show its provider and Encryption test passed. The root certificate shows No key provider information, because its key is not on this server. That is expected.

Stop-Service certsvc
Set-Service certsvc -StartupType Disabled
icacls C:\CABackup-Final /inheritance:r /grant:r "Administrators:(OI)(CI)F" "SYSTEM:(OI)(CI)F"

Copy C:\CABackup-Final to two locations away from this server. It contains the CA private key, so protect it and store the password in a vault.

Rollback A: Set-Service certsvc -StartupType Automatic; Start-Service certsvc; Remove-NetFirewallRule -DisplayName CA-CUTOVER-FREEZE

Phase 2: take the old server offline

Stop the VM, but do not delete it. Then snapshot or image its disks. A snapshot is point-in-time as soon as it starts, so you can restart the VM while it completes. Keep both for at least 30 days.

While the old server is off, the HTTP CDP and AIA are unavailable until Phase 5. Domain clients fall back to LDAP and cached CRLs stay valid, so keep Phases 3 to 5 tight.

Rollback B: start the old VM, then run Rollback A. DNS and AD are untouched at this point.

Phase 3: join the new server to the existing computer account

Reuse the old computer account instead of deleting it. The SID stays the same, so Cert Publishers membership, DNS record ownership and other permissions carry over.

  1. On a DC, record the current state: Get-ADComputer ISSCA01 -Properties MemberOf | Select-Object Name, SID, MemberOf
  2. In Active Directory Users and Computers, right-click ISSCA01 and choose Reset Account. Do this immediately before the join, because it breaks the old server’s trust (Figure 4).
  3. On the new server, still in a workgroup, rename it and join the domain (commands below).
  4. After the reboot, verify the secure channel and DNS, and force replication.

Rename-Computer -NewName ISSCA01 -Restart
# after the reboot, still in the workgroup
Add-Computer -DomainName core365.cloud -Credential (Get-Credential) -Restart

# after the second reboot
nltest /sc_verify:core365.cloud
Resolve-DnsName issca01.core365.cloud                        # should now return the new IP
Get-ADGroupMember "Cert Publishers" | Select-Object Name     # run on a DC
repadmin /syncall /AdeP                                      # run on a DC

The join also updates the A record through secure dynamic DNS. As a result, clients start resolving the new IP immediately, before the CA is restored. If a stale record survives, run ipconfig /registerdns on the new server, and watch replication with our AD replication dashboard.

Rollback C starts here: from now on, rollback also needs a secure channel repair on the old server (see the rollback section).

Phase 4: restore the CA key, database and registry (new server)

Import the PFX first. Then confirm you can see the newest CA certificate and that the root is trusted.

certutil -f -csp "Microsoft Software Key Storage Provider" -importpfx C:\CABackup-Final\core365-ISSCA01-CA.p12
certutil -store My <thumbprint-of-newest-CA-cert>
certutil -store Root | findstr /i Core365-RootCA

Next, configure the CA with the existing certificate. Select the newest certificate by thumbprint, because all of them share one key and the wizard can list several.

Install-AdcsCertificationAuthority -CAType EnterpriseSubordinateCA -CertificateID <thumbprint-of-newest-CA-cert> -Force

You can use Server Manager instead: AD CS Configuration, then Use existing certificate and private key, then Import. If the cmdlet rejects the parameter combination, use the wizard.

The first start can fail with event 100 (CRYPT_E_REVOCATION_OFFLINE). In our run it did, before the registry import, because a default configuration does not tolerate an offline root CRL. The restored registry brought back the old CRLFlags with ignore-offline set, and then the CA started.

Stop-Service certsvc
reg export HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration C:\NewCA-AfterInstall.reg   # undo point
certutil -f -restoreDB C:\CABackup-Final
reg import C:\CABackup-Final\CAConfig.reg
Start-Service certsvc

The service must be stopped for -restoreDB, and the command reminds you to restart it to finish the restore. Because we moved to a newer OS, the first start upgraded the database (event 124). That upgrade is one-way.

Now verify the restore:

certutil -cainfo | Select-String 'CA name|CA cert count|CA cert\[7\]|CRL\[0\]'
certutil -ping
certutil -catemplates
(certutil -view -out RequestID | Select-String '^Row \d+:').Count   # compare with row count A
Get-ChildItem C:\Windows\System32\CertLog | Select-Object Name, Length, LastWriteTime
certutil -crl

In our case CA cert count: 8 came back, CA cert[0] was Unavailable as before, and the .edb matched the backup size to the byte. Use the row-count comparison as the second proof. Do not rely on one signal alone.

Phase 5: recreate CRL and AIA hosting (new server)

The CA role does not create the IIS virtual directory by itself. Recreate it, then copy only the files the new CA has not generated, such as the offline root CA’s CRL and certificate.

Import-Module WebAdministration
New-WebVirtualDirectory -Site "Default Web Site" -Name CertEnroll -PhysicalPath "C:\Windows\System32\CertSrv\CertEnroll"
robocopy C:\CABackup-Final\CertEnroll C:\Windows\System32\CertSrv\CertEnroll /E /XC /XN /XO /XF nsrev_*.asp
Invoke-WebRequest "http://pki.core365.cloud/CertEnroll/" -UseBasicParsing | Select-Object StatusCode

The /XC /XN /XO switches copy only files that do not exist yet, so robocopy never overwrites a CRL the new CA just published. The old web.config enables directory browsing, so install the Directory Browsing feature first. Otherwise IIS returns a 500.19 error for the folder.

Skip web enrollment unless someone needs it. Web enrollment over HTTP with Windows authentication is a known NTLM relay target (ESC8), so reinstall it only on demand, and then use HTTPS with Extended Protection.

Rollback C: stop or deallocate the new VM, start the old VM, repair its secure channel, restore the DNS record, then run Rollback A. Details follow in the next section.

Phase 6: let clients in and validate

Nothing needs to be reopened, because the freeze rule lived on the old server, which is now off. Move straight to the post-migration tests below, and stop at the first failure.

Rollback plan for every stage

The old server stays intact until you decommission it, so every stage has a way back. The table maps each stage to its rollback label from Figure 1.

StageRollback stepsNotes
A: after the freeze or after stopping the old CASet-Service certsvc -StartupType Automatic, then Start-Service certsvc, then Remove-NetFirewallRule -DisplayName CA-CUTOVER-FREEZENothing else has changed
B: old VM stopped, new server not yet joinedStart the old VM, then do ADNS and AD are unchanged
C: new server joined or CA restored1. Stop or deallocate the new VM. 2. Start the old VM and sign in with a local admin. 3. Test-ComputerSecureChannel -Repair -Credential (Get-Credential). 4. Do A. 5. ipconfig /registerdns and confirm the A record shows the old IP. 6. certutil -ping, certutil -crl, then compare pkiview.Certificates the new CA issued exist only in its database
Point of no returnWiping the old VM and its imageWait at least 30 days

Resetting the computer account breaks the old server’s AD trust, even if the join never finished. That is why step 3 of Rollback C exists. If you meet the classic error message, see our guide to the Active Directory trust relationship failed error.

Before you roll back after clients enrolled, list what the new CA issued. Those certificates stay valid but are unknown to the old CA, so you must reissue them or accept that the old CA cannot revoke them.

certutil -view -restrict "RequestID>=<first-new-request-id>" -out RequestID,CommonName

Post-migration tests: prove the new CA works

Run these in order. Stop at the first failure, because later tests depend on earlier ones.

#TestCommand or actionExpected result
1Service and databaseGet-Service certsvc; compare the .edb size and row count with the backupRunning; sizes and counts match
2Event logGet-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='Microsoft-Windows-CertificationAuthority'} -MaxEvents 15Event 26 (started), event 124 after an OS upgrade, no unexplained errors
3CA identitycertutil -cainfo and certutil -catemplatesSame name, certificate count, active certificate and templates as the baseline
4DNSResolve-DnsName issca01.core365.cloud and pki.core365.cloud from a DC and from each siteThe new IP everywhere
5RPC from other networkscertutil -config "issca01.core365.cloud\core365-ISSCA01-CA" -ping from a client in each siteInterface is alive
6HTTP CDP and AIAInvoke-WebRequest http://pki.core365.cloud/CertEnroll/ -UseBasicParsingStatus 200
7EnrollmentGet-Certificate -Template Machine -CertStoreLocation Cert:\LocalMachine\My on a disposable VMStatus Issued
8Chain and revocationExport the certificate, then certutil -verify -urlfetch test.cerLeaf revocation check passed through LDAP
9Revocationcertutil -revoke <serial> 5, certutil -crl, then verify againThe serial appears in the CRL and verify reports it revoked
10pkiviewpkiview.mscMatches the baseline from Figure 2
11Backupcertutil -backup of the new CACopied off the server and scheduled

Use a disposable VM for test 7. A common mistake I see is testing on a production member server. The Machine template then issues that server’s real certificate, and revoking it leaves a revoked certificate in its store. Delete the test certificate afterwards, and run certutil -pulse if the server must re-enroll.

In our test, the leaf certificate’s revocation check passed through LDAP. The HTTP base CRL URL returned a delta CRL, and the + delta URL returned 404. Both matched the old server’s baseline, and the next section explains them. For a broader view afterwards, run the AD CS health check script.

Keep the old VM and its image for 30 days, and decommission only after at least one full base CRL cycle. Meanwhile, put a calendar reminder on the first scheduled backup of the new CA.

Issues you may face and how to fix them

These are the problems we hit or verified. The table is the quick lookup. The sections after it cover the faults that need more than one line.

Symptom or errorLikely causeFix
certutil -getreg CA\DBDirectory returns ERROR_FILE_NOT_FOUNDDB paths are not under the CA subkeyUse certutil -getreg DBDirectory
certutil -backupKey fails with 0x80092004The key is not exportable (HSM or non-exportable key)Use the vendor procedure, or renew or re-key the CA
Install-AdcsCertificationAuthority or Select-String is not recognizedYou are in cmdUse an elevated PowerShell window
CA will not start; events 100 and 48; 0x80092013Revocation check of the CA chain is offline (expired root CRL)Restore CRLFlags or refresh the root CRL (see below)
Events 86 and 87; NTE_BAD_KEYSETCA exchange key was not found, so the CA creates a new oneBenign if certutil -cainfo xchg returns a certificate (see below)
certutil -catemplates shows Auto-Enroll: Access is deniedYour account cannot read template ACLsCosmetic; the template list is still correct
-restoreDB fails or the service will not start after restoreService was running, or %SystemRoot% and DB paths differ from the backupStop certsvc first and align the DB paths in the registry
Domain join reports that the account already existsThe old account was not reset, or you lack rightsReset the account in ADUC and use credentials that can reuse it
CRL publishing to AD fails with access deniedThe computer account was recreated, so its SID changed and it left Cert PublishersAdd it to Cert Publishers, or reuse the old account
Clients still reach the old IPDNS cache, high TTL, stale record or replication delayLower the TTL beforehand; ipconfig /flushdns; repadmin /syncall /AdeP
The RPC server is unavailable (0x800706BA) from some sitesThe dynamic RPC range is blocked on a firewall or NSGOpen or pin the range, then test certutil -ping per site
pkiview: HTTP CDP and delta show Unable to downloadThe delta CRL overwrote the base file; IIS blocks + (404.11)Fix the publish path and allowDoubleEscaping (see below)
pkiview: root CDP shows ExpiredThe offline root CRL lapsedRefresh the root CRL (see below)
IIS returns 500.19 for /CertEnrollweb.config enables directory browsing but the feature is missingInstall Web-Dir-Browsing or remove the web.config
Old server reports a failed trust after rollbackThe join reset its machine passwordTest-ComputerSecureChannel -Repair
CDP shows a literal <ServerName> in an LDAP URLA placeholder baked into the issuing CA certificateCosmetic while another CDP works; only a renewed CA certificate clears it

CA will not start: CRYPT_E_REVOCATION_OFFLINE (events 100 and 48)

At startup, the CA validates its own certificate chain. If the offline root CRL has expired or its URL is unreachable, the check fails with 0x80092013 and the service stops. In our run this happened on the first start, before the registry import.

The old CA had CRLFlags = 10, which includes CRLF_REVCHECK_IGNORE_OFFLINE (8). The import restored it, and the CA then started. Treat that flag as a crutch, not a fix.

certutil -getreg CA\CRLFlags
certutil -setreg CA\CRLFlags +CRLF_REVCHECK_IGNORE_OFFLINE
Restart-Service certsvc

Events 86 and 87 (NTE_BAD_KEYSET) after the restore

The CA logged that it could not use the provider for encryption keys. These events relate to the CA exchange certificate, a short-lived certificate (about a week) used for key archival. Its key container does not exist on a new server, so the CA creates a new one.

certutil -cainfo xchg
certutil -getreg CA\EncryptionCSP\*

In our case certutil -cainfo xchg returned a freshly generated -Xchg certificate created in the same minute as the events. The EncryptionCSP values also matched the old registry. Therefore we treated the events as benign and rechecked the log at the weekly renewal. If you use key archival with a configured KRA, investigate further instead of assuming.

HTTP CRL problems that migrate with you

Two faults travel with the registry. First, a local publish path without %9 makes the daily delta CRL overwrite the base CRL file. Second, IIS blocks the + character in the delta CRL file name.

You can recognize it in three places. certutil -dump on the base .crl shows a Delta CRL Indicator. certutil -verify -urlfetch expects a base CRL but receives a delta. And the + URL returns 404.11.

certutil -setreg CA\CRLPublicationURLs "65:C:\Windows\system32\CertSrv\CertEnroll\%3%8%9.crl\n6:http://pki.core365.cloud/CertEnroll/%3%8%9.crl\n79:ldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10"
Restart-Service certsvc
certutil -crl
& "$env:windir\system32\inetsrv\appcmd.exe" set config "Default Web Site/CertEnroll" -section:system.webServer/security/requestFiltering -allowDoubleEscaping:true -commit:apphost

Do this as a separate change after the migration is validated, so your pkiview baseline stays comparable during cutover. Issued certificates already carry the correct %9 URL, so only the published files change.

The offline root CRL has expired

pkiview builds the root’s AIA and CDP entries from the subordinate CA certificates it issued. Therefore the URLs are baked in, and you can only fix what exists at those locations. Power on the offline root, check its clock first, set a validity you can maintain, and publish.

certutil -getreg CA\CRLPeriod
certutil -getreg CA\CRLPeriodUnits
certutil -setreg CA\CRLPeriodUnits 12
certutil -setreg CA\CRLPeriod "Months"
Restart-Service certsvc
certutil -crl
Get-ChildItem C:\Windows\System32\CertSrv\CertEnroll\*.crl | Select-Object Name, LastWriteTime

Copy the new .crl files to the issuing CA’s CertEnroll folder with the exact file names from the CDP URL, for example Core365-RootCA(1).crl. Then verify the dates, clear the URL cache and refresh pkiview.

certutil -dump "C:\Windows\System32\CertSrv\CertEnroll\Core365-RootCA(1).crl" | Select-String 'ThisUpdate|NextUpdate'
certutil -urlcache * delete

To fix the AIA entry in AD, publish the root certificate from a DC with certutil -dspublish -f <root-cert>.cer RootCA. An LDAP CDP that shows a literal <ServerName> stays red. Clients ignore it as long as the HTTP CDP works, and only a renewed issuing CA certificate clears it.

Final checklist before you decommission the old CA

  1. The new CA runs, row counts match and the event log is clean.
  2. A test certificate was issued, revoked and published, and pkiview matches the baseline.
  3. Every client network passes certutil -ping and loads the HTTP CDP.
  4. A fresh backup of the new CA sits off the server and runs on a schedule.
  5. The DNS TTL is back to its normal value.
  6. The old VM and its image are kept for 30 days, with a calendar entry to review them.
  7. Follow-up changes are booked: the root CRL, the HTTP CDP fixes, SHA256 and the OS lifecycle.

A same-name, new-IP migration is mostly discipline: freeze, back up, prove the backup, and keep the old server for rollback. If you do those four things and test from every network, the CA move itself is the easy part.

Frequently Asked Questions

Can you migrate an issuing CA to a new server with a different IP address?

Yes. A CA’s identity is its name and key pair, not its IP. Keep the same computer name, restore the key, database and registry, then update DNS and firewall rules for the new IP. Clients keep trusting the CA because the CA certificate and the CDP/AIA URLs do not change.

Do I need to reissue certificates after migrating an issuing CA?

No. Certificates already issued stay valid because the CA key and name are unchanged and the database is restored. Only certificates issued between your backup and shutdown would be lost, which is why you freeze issuance and compare row counts before stopping the old CA.

Which ports must be open on the new CA server?

Clients need TCP 135 and the RPC dynamic range (49152-65535 by default) for enrollment, plus TCP 80 for CRL and AIA downloads. The CA needs DNS, Kerberos, LDAP, RPC, SMB and NTP access to domain controllers. Administrators also need RDP or WinRM from admin subnets.

Can the CA private key be backed up if it is not exportable?

Usually yes on a software key storage provider. certutil -backup exported our key even though certutil reported it as not plain text exportable. If certutil -backupKey fails with 0x80092004, the key cannot be exported. HSM keys follow the vendor’s procedure. Verify any backup with certutil -dump.

How long should the CA be offline during the migration?

Plan 2 to 3 hours and keep the outage far below the delta CRL validity, which is often one day plus overlap. Publish fresh CRLs right before shutdown. Domain clients fall back to LDAP and cached CRLs, so most users never notice a short outage.

Can I change the CA name or computer name during migration?

The CA common name cannot change. The computer name can change only if your CDP and AIA URLs use a DNS alias instead of the host name. Microsoft’s default CDP extensions include the host name, which is why keeping the same name is the simplest path.

Are certificate templates restored automatically?

Yes. Published templates are stored in Active Directory on the CA’s Enrollment Services object, so they reappear once the CA with the same name is running. Verify with certutil -catemplates. Access denied messages next to Auto-Enroll only mean the account cannot read template permissions.

Why does the CA fail to start after I import the key?

The usual cause is CRYPT_E_REVOCATION_OFFLINE (0x80092013, event 100). The CA checks revocation for its own chain, and an expired or unreachable root CRL makes that check fail. Refresh the offline root CRL, or restore the registry CRLFlags value that ignores offline revocation, then restart the service.

Should I uninstall AD CS from the old server first?

Not if you want a rollback path. Microsoft’s guidance allows either removing the role or disabling the CA service and shutting the old server down before the new one takes the name. Disabling and powering off keeps the old CA intact for 30 days.

How do I confirm the database restored correctly?

Compare the request count before and after with certutil -view -out RequestID, check that the .edb size matches the backup, and confirm event 26 in the Application log. After an OS upgrade you should also see event 124. Matching counts plus a clean start mean the restore is intact.

Do I need to copy CRL and AIA files to the new server?

Yes, but only files the new CA will not regenerate, mainly the offline root CA’s CRL and certificate. The new CA publishes its own CRLs and CA certificates. Recreate the IIS virtual directory and copy missing files with robocopy switches that never overwrite newer files.

What happens to OCSP, NDES and web enrollment?

They are separate roles and do not move with certutil -backup. Migrate or rebuild each one, then point it at the CA. Web enrollment over HTTP with Windows authentication is an NTLM relay risk (ESC8), so reinstall it only if users need it and protect it with HTTPS.

How do I roll back if the new CA fails validation?

Shut down the new server, start the old one, repair its AD trust with Test-ComputerSecureChannel -Repair, restore the DNS record, and re-enable the CA service. Certificates the new CA issued exist only in its database, so list them before rolling back.

Home » Security » Enterprise Security » PKI & Certificates » How to Migrate an Issuing CA to a New Server – Step-by-Step with Rollback

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top
×