← script library

Configure WinRM over HTTPS with a Domain Certificate

ServerEngine PlatformAugust 17, 2026

The same WinRM over HTTPS setup, but binding a certificate your own CA issued instead of a self-signed one. It looks up the newest matching certificate with a private key, warns when it is close to expiry and fails clearly when there is none. Connections must then use the DNS name the certificate covers.

powershell
# Configures Windows PowerShell Remoting and WinRM for ServerEngine management
# With Custom Domain Certificate works only with DNS Name and valid Certificate Authority (CA) association
#----------------------------------------------------------------
# Requires Administrator previlegues

$isadm = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isadm) {
    Write-Host "<WRITE-LOG = ""*Please run this script as Administrator.*"">"
    Write-Host "<WRITE-LOG = ""*If this was a remote execution please provide Administrator credentials.*"">"
    Write-Error "Warning: Not running as Administrator."
}

# Step 1 - Prepare Network Adapters
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private 2>$null

# Step 2 - Enable Windows PowerShell Remoting
Enable-PSRemoting -Force

# Step 3 - Configure WinRM SSL with Self-Signed Certificate

# Start WinRM service if not running
if ((Get-Service WinRM).Status -ne 'Running') {
    Start-Service WinRM -ErrorAction Stop
    Set-Service WinRM -StartupType Automatic -ErrorAction Stop
}

# Configure HTTPS listener
winrm quickconfig -transport:https -force 2>$null

# Load existing domain certificate
$hostname = "*.yourcompany.com" #REPLACE THIS WITH YOUR WILDCARD DOMAIN CERTIFICATE

$existingCert = Get-ChildItem "Cert:\LocalMachine\My" |
    Where-Object {
        $_.Subject -like "CN=$hostname*" -and  # Notice the * AFTER, not before
        $_.HasPrivateKey -eq $true
    } | Sort-Object NotBefore -Descending | Select-Object -First 1


# Create new certificate only if needed
if ($existingCert) {
    # Check if certificate is expired or expiring soon (within 30 days)
    $daysUntilExpiry = ($existingCert.NotAfter - (Get-Date)).Days

    if ($daysUntilExpiry -le 0) {
        Write-Warning "Existing certificate expired $([Math]::Abs($daysUntilExpiry)) days ago. Creating new certificate..."
    }
    elseif ($daysUntilExpiry -le 30) {
        Write-Warning "Existing certificate expires in $daysUntilExpiry days. Creating new certificate..."
    }
    else {
        Write-Host "Certificate found! (expires in $daysUntilExpiry days)"
        $cert = $existingCert
    }
} else {
    Write-Error "No existing certificate found. $hostname does not exist!"

}

# Remove any existing HTTPS listeners
winrm delete winrm/config/Listener?Address=*+Transport=HTTPS 2>$null

# Create HTTPS listener with the certificate
New-Item -Path "WSMan:\localhost\Listener" -Transport HTTPS -Address * -CertificateThumbprint $cert.Thumbprint -Force -ErrorAction Stop

# Configure firewall (skip if rule already exists)
if (-not (Get-NetFirewallRule -Name "WINRM-HTTPS-In-TCP" -ErrorAction SilentlyContinue)) {
    New-NetFirewallRule -Name "WINRM-HTTPS-In-TCP" -DisplayName "Windows Remote Management (HTTPS-In)" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5986 -Action Allow -ErrorAction Stop
}

Write-Host "WinRM HTTPS successfully configured"
Write-Host "Certificate Thumbprint: $($cert.Thumbprint)"
Write-Host "Certificate Expires: $($cert.NotAfter.ToString('yyyy-MM-dd'))"
Write-Host "<WRITE-LOG = ""*PowerShell Remoting successfully configured.*"">"

Run it across your fleet

This script runs as-is on a single host. Paste it into ServerEngine to schedule it, run it on a whole server group in parallel, and keep the credentials out of the file — see the scripts documentation and the credential store.

Ready when you are.

Try ServerEngine free for 7 days.