How to Set Up a PKI Infrastructure with AD CS on Windows Server 2025

A well-designed Public Key Infrastructure (PKI) is the foundation of enterprise security — it underpins HTTPS for internal web services, mutual TLS for application authentication, smart card logon, Wi-Fi 802.1X, VPN certificate authentication, S/MIME email signing, and BitLocker key escrow. Active Directory Certificate Services (AD CS) on Windows Server 2025 provides a deeply integrated, enterprise-class PKI that ties directly into Active Directory for auto-enrollment, Group Policy-driven certificate distribution, and LDAP-based CRL publication. The recommended architecture for any production deployment is a two-tier hierarchy: a standalone, offline root CA that signs a certificate for an online issuing CA, then is permanently powered off. The issuing CA handles all day-to-day certificate issuance while the root CA’s air-gapped status protects the trust anchor from compromise. This guide walks through the complete build of both tiers on Windows Server 2025.

Prerequisites

  • Two Windows Server 2025 servers: one for the offline root CA (can be a VM powered off after setup), one for the online enterprise issuing CA
  • The issuing CA server must be domain-joined; the root CA is standalone (workgroup)
  • Active Directory domain at Windows Server 2016 functional level or higher
  • Enterprise Admin and Domain Admin credentials (required to publish to AD and install the Enterprise CA role)
  • A plan for CDP (CRL Distribution Points) and AIA (Authority Information Access) HTTP URLs — these must be publicly or internally reachable by all certificate consumers
  • An IIS web server (can be on the issuing CA server) to host CRL and CA certificate files over HTTP

Step 1 — Build the Offline Standalone Root CA

The root CA is a standalone (non-domain-joined) Windows Server 2025 system. It will be online only during initial setup and whenever a subordinate CA certificate needs to be signed or renewed — typically once every few years. Choose a long validity period (10–20 years) for the root CA to avoid disrupting the entire hierarchy with a root renewal.

# On the OFFLINE ROOT CA server (standalone, NOT domain-joined)
# Install the AD CS role — no management tools needed; use core config
Install-WindowsFeature ADCS-Cert-Authority -IncludeManagementTools

# Configure the Standalone Root CA
Install-AdcsCertificationAuthority `
    -CAType StandaloneRootCA `
    -CACommonName "Corp Root CA" `
    -CADistinguishedNameSuffix "DC=contoso,DC=com" `
    -KeyLength 4096 `
    -HashAlgorithmName SHA256 `
    -ValidityPeriod Years `
    -ValidityPeriodUnits 20 `
    -CryptoProviderName "RSA#Microsoft Software Key Storage Provider" `
    -Force

# Verify installation
Get-CACertificate | Select-Object Subject, NotBefore, NotAfter, Thumbprint

Step 2 — Configure Root CA Validity and CRL Settings

Because the root CA will be offline most of the time, the CRL it publishes must have a long validity period — long enough to remain valid between the infrequent occasions when the root CA is powered on to publish a new CRL. A one-year CRL with a two-week overlap is common for an offline root.

# On the ROOT CA — configure CRL validity (1 year, with 2-week overlap)
certutil -setreg CACRLPeriodUnits 1
certutil -setreg CACRLPeriod "Years"
certutil -setreg CACRLOverlapPeriodUnits 2
certutil -setreg CACRLOverlapPeriod "Weeks"

# Configure Delta CRL — disable for offline root (it will never publish updates)
certutil -setreg CACRLDeltaPeriodUnits 0

# Set maximum certificate validity for subordinate CAs
certutil -setreg CAValidityPeriodUnits 10
certutil -setreg CAValidityPeriod "Years"

# Configure CDP and AIA extensions — add HTTP URLs that will be reachable
# These URLs are embedded in all certificates issued by this CA
$CdpUrl = "http://pki.contoso.com/CertEnroll/%7%8%9.crl"
$AiaUrl = "http://pki.contoso.com/CertEnroll/%1_%3%4.crt"

# Add HTTP CDP (clients download CRL from this URL)
certutil -setreg CACRLPublicationURLs "1:C:Windowssystem32CertSrvCertEnroll%7%8%9.crln2:ldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10n2:$CdpUrl"

# Add HTTP AIA (clients download issuer cert from this URL)
certutil -setreg CACACertPublicationURLs "1:C:Windowssystem32CertSrvCertEnroll%1_%3%4.crtn2:ldap:///CN=%7,CN=AIA,CN=Public Key Services,CN=Services,%6%11n2:$AiaUrl"

# Restart Certificate Services to apply all registry changes
Restart-Service certsvc

# Publish the CRL
certutil -crl

# List generated files to transfer to the issuing CA and web server
Get-ChildItem "C:WindowsSystem32CertSrvCertEnroll" | Select-Object Name, LastWriteTime

Step 3 — Publish Root CA Certificate and CRL to Active Directory

For domain-joined machines to automatically trust the root CA, the root certificate must be published to the AD configuration naming context. This is done from a domain-joined machine (such as the future issuing CA server) using certutil -dspublish. Copy the root CA’s .crt and .crl files from the root CA to the domain-joined server first.

# On the DOMAIN-JOINED ISSUING CA server (or any domain member with RSAT)
# Assumes root CA cert and CRL have been copied to C:RootCA

# Publish root CA certificate to the NTAuthCertificates and RootCA containers in AD
certutil -dspublish -f "C:RootCACorp Root CA.crt" RootCA

# Publish the root CA CRL to AD (for internal clients that use LDAP CDP)
certutil -dspublish -f "C:RootCACorp Root CA.crl" RootCA

# Copy the root CA cert and CRL to the IIS web server's CertEnroll virtual directory
Copy-Item "C:RootCACorp Root CA.crt" "C:inetpubwwwrootCertEnroll" -Force
Copy-Item "C:RootCACorp Root CA.crl" "C:inetpubwwwrootCertEnroll" -Force

# Force a Group Policy update to propagate the new root trust to all domain members
Invoke-GPUpdate -Force

Step 4 — Install the Enterprise Subordinate (Issuing) CA

The issuing CA is a domain-joined Windows Server 2025 system that handles all certificate requests from users, computers, and services in the organization. Because it is an Enterprise CA (rather than Standalone), it integrates with Active Directory for auto-enrollment, certificate template management, and permission assignment through Group Policy.

# On the ISSUING CA server (domain-joined Windows Server 2025)
Install-WindowsFeature ADCS-Cert-Authority, ADCS-Web-Enrollment, `
    ADCS-Online-Cert, Web-Server -IncludeManagementTools

# Begin Enterprise Subordinate CA setup — this generates a CSR
Install-AdcsCertificationAuthority `
    -CAType EnterpriseSubordinateCA `
    -CACommonName "Corp Issuing CA" `
    -CADistinguishedNameSuffix "DC=contoso,DC=com" `
    -KeyLength 2048 `
    -HashAlgorithmName SHA256 `
    -CryptoProviderName "RSA#Microsoft Software Key Storage Provider" `
    -OutputCertRequestFile "C:SubCASubCA.req" `
    -Force

# A CSR file is created at C:SubCASubCA.req
# Copy this file to the offline root CA for signing

Step 5 — Sign the Subordinate CA Certificate on the Root CA

# On the OFFLINE ROOT CA — sign the subordinate CA's CSR
# Copy SubCA.req from the issuing CA to C:Requests on the root CA

# Submit the CSR to the local (root) CA
certreq -submit -config "ROOTCACorp Root CA" "C:RequestsSubCA.req" "C:RequestsSubCA.crt"

# If you need to approve it manually (standalone CA requires manual approval):
# Check pending requests
certutil -view queue

# Approve the pending request (replace 2 with the actual request ID)
certutil -resubmit 2

# Retrieve the signed certificate
certreq -retrieve -config "ROOTCACorp Root CA" 2 "C:RequestsSubCA.crt"

# Publish an updated CRL that covers the newly issued sub CA certificate
certutil -crl

# Copy to issuing CA: SubCA.crt, Corp Root CA.crt, Corp Root CA.crl

Step 6 — Complete the Issuing CA Installation and Configure Templates

# On the ISSUING CA — install the signed subordinate certificate
certutil -installcert "C:SubCASubCA.crt"

# Start the Certificate Authority service
Start-Service certsvc
Set-Service certsvc -StartupType Automatic

# Verify the CA is operational
certutil -ping

# Configure CRL and AIA publication settings (same HTTP URLs as root CA config)
certutil -setreg CACRLPeriodUnits 1
certutil -setreg CACRLPeriod "Weeks"
certutil -setreg CACRLOverlapPeriodUnits 10
certutil -setreg CACRLOverlapPeriod "Hours"
certutil -setreg CACRLDeltaPeriodUnits 1
certutil -setreg CACRLDeltaPeriod "Days"

Restart-Service certsvc
certutil -crl

# Enable certificate templates for auto-enrollment
# Add the default templates: User, Computer, WebServer
Add-CATemplate -Name "User" -Force
Add-CATemplate -Name "Machine" -Force
Add-CATemplate -Name "WebServer" -Force

# List currently enabled templates
Get-CATemplate | Select-Object Name, DisplayName

Step 7 — Configure Auto-Enrollment via Group Policy

Auto-enrollment automatically issues and renews certificates for users and computers based on their AD group membership and the permissions set on certificate templates. Configure it through Group Policy to ensure all domain members receive the correct certificates without manual intervention.

# Create a GPO for certificate auto-enrollment
New-GPO -Name "PKI - Certificate Auto-Enrollment" -Comment "Configures auto-enrollment for users and computers"

# Link to the domain (or specific OU)
New-GPLink -Name "PKI - Certificate Auto-Enrollment" -Target "DC=contoso,DC=com"

# Auto-enrollment settings are configured in:
# Computer Configuration > Windows Settings > Security Settings > Public Key Policies >
#   Certificate Services Client - Auto-Enrollment
# User Configuration > Windows Settings > Security Settings > Public Key Policies >
#   Certificate Services Client - Auto-Enrollment

# PowerShell: force enrollment on a specific computer to test
gpupdate /force
certreq -enroll -machine "Machine"

# View certificates issued to this machine
Get-ChildItem Cert:LocalMachineMy | Select-Object Subject, Thumbprint, NotAfter, Issuer

# View certificates in the user's personal store
Get-ChildItem Cert:CurrentUserMy | Select-Object Subject, Thumbprint, NotAfter, Issuer

# Verify the issuing CA's certificate chain is complete and trusted
certutil -verify -urlfetch "C:SubCASubCA.crt"

Conclusion

Building a two-tier PKI hierarchy with AD CS on Windows Server 2025 is one of the most impactful infrastructure investments an enterprise IT team can make. The offline root CA protects the top-level trust anchor from network-based attacks, while the online enterprise issuing CA integrates seamlessly with Active Directory to deliver auto-enrollment, certificate template management, and LDAP-based CRL distribution to every domain member. By carefully planning your CDP and AIA HTTP URLs before deployment, setting appropriate validity periods for each CA tier, and configuring Group Policy auto-enrollment, you create a PKI that scales from dozens to tens of thousands of endpoints with minimal administrative overhead. Regular CRL publication monitoring, timely root CA CRL renewal, and periodic certificate inventory reviews round out the operational practices needed to keep your PKI trustworthy over its entire lifetime.