How to Configure Windows Server 2016 PowerShell Remoting

PowerShell Remoting is one of the most powerful remote management capabilities in Windows Server 2016. It allows administrators to run PowerShell commands and scripts on remote computers as if they were sitting at the console of that machine. Built on the WS-Management protocol (WinRM), PowerShell Remoting enables interactive remote sessions, fan-out command execution across hundreds of servers simultaneously, and persistent persistent sessions for long-running administrative tasks. Mastering PowerShell Remoting transforms how you manage a Windows server infrastructure at scale.

How PowerShell Remoting Works

PowerShell Remoting uses the Windows Remote Management (WinRM) service, which implements the WS-Management protocol. By default, WinRM listens on HTTP port 5985 for unencrypted (but authenticated) connections and HTTPS port 5986 for encrypted connections. All PowerShell Remoting traffic uses HTTPS when available and falls back to HTTP with Kerberos authentication (which provides message-level encryption) in domain environments. In workgroup or cross-domain scenarios, additional configuration is required to establish trust.

Step 1: Enable PowerShell Remoting

On Windows Server 2016, WinRM is typically enabled by default. Verify and explicitly enable PowerShell Remoting using the Enable-PSRemoting cmdlet, which configures WinRM listeners, creates firewall rules, and sets the WinRM service to start automatically:

# Enable PowerShell Remoting (run as Administrator)
Enable-PSRemoting -Force

# Verify WinRM service status
Get-Service WinRM | Select Name, Status, StartType

# Check WinRM listeners
winrm enumerate winrm/config/listener

# View WinRM configuration
winrm get winrm/config

Verify the Windows Firewall rules were created for WinRM:

Get-NetFirewallRule | Where-Object { $_.DisplayName -like "*WinRM*" -or $_.DisplayName -like "*Windows Remote Management*" } | Select DisplayName, Enabled, Direction, Action | Format-Table

Step 2: Configure WinRM for HTTPS

For secure remoting over untrusted networks, configure WinRM to use HTTPS. This requires a server certificate with the server’s hostname in the Subject or SAN:

# Find the SSL certificate thumbprint for this server
$certThumbprint = (Get-ChildItem Cert:LocalMachineMy | Where-Object { $_.Subject -like "*$env:COMPUTERNAME*" }).Thumbprint

# Create an HTTPS WinRM listener
New-Item -Path WSMan:localhostListener -Transport HTTPS -Address * -CertificateThumbprint $certThumbprint -Force

# Verify HTTPS listener was created
Get-ChildItem WSMan:localhostListener | Select PSPath, Keys

# Add firewall rule for HTTPS WinRM
New-NetFirewallRule -DisplayName "WinRM HTTPS" -Direction Inbound -Protocol TCP -LocalPort 5986 -Action Allow

Test HTTPS connectivity to a remote server:

Test-WSMan -ComputerName server02.corp.local -UseSSL -Credential (Get-Credential)

Step 3: Connect to Remote Computers

Use Enter-PSSession for interactive one-on-one remote sessions:

# Connect to a remote server interactively
Enter-PSSession -ComputerName server02

# Connect with explicit credentials
$cred = Get-Credential -UserName "corpadministrator" -Message "Enter admin credentials"
Enter-PSSession -ComputerName server02.corp.local -Credential $cred

# Exit the remote session
Exit-PSSession

Use Invoke-Command for non-interactive command execution — the workhorse of bulk server management:

# Run a command on a single remote computer
Invoke-Command -ComputerName server02 -ScriptBlock { Get-Service | Where-Object { $_.Status -ne "Running" } | Select Name, Status }

# Run on multiple servers simultaneously (parallel by default)
$servers = @("server01", "server02", "server03", "server04", "server05")
Invoke-Command -ComputerName $servers -ScriptBlock {
    [PSCustomObject]@{
        Server     = $env:COMPUTERNAME
        OSVersion  = (Get-WmiObject Win32_OperatingSystem).Caption
        FreeMemGB  = [math]::Round((Get-WmiObject Win32_OperatingSystem).FreePhysicalMemory / 1MB, 2)
        DiskFreeGB = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
    }
} | Select Server, OSVersion, FreeMemGB, DiskFreeGB | Format-Table -AutoSize

Step 4: Use Persistent Sessions

Persistent sessions (PSSession objects) maintain state between commands. Variables defined in one command are available in subsequent commands, making them ideal for long-running administrative workflows:

# Create a persistent session
$session = New-PSSession -ComputerName server02

# Run multiple commands in the same session (variables persist)
Invoke-Command -Session $session -ScriptBlock { $x = Get-Process | Measure-Object | Select -ExpandProperty Count }
Invoke-Command -Session $session -ScriptBlock { Write-Host "Process count: $x" }

# Create sessions to multiple servers
$sessions = New-PSSession -ComputerName server01, server02, server03

# Run commands across all sessions
Invoke-Command -Session $sessions -ScriptBlock { hostname; Get-Date }

# Clean up sessions when done
Remove-PSSession -Session $sessions
Get-PSSession | Remove-PSSession  # Clean all orphaned sessions

Step 5: Import Remote Modules and Commands

Import commands from a remote session into the local session. This allows you to run remote commands as if they were local cmdlets, without needing the module installed locally:

# Import specific commands from a remote server
$session = New-PSSession -ComputerName dc01.corp.local
Import-PSSession -Session $session -Module ActiveDirectory -CommandName Get-ADUser, Set-ADUser, New-ADUser -Prefix Remote

# Now use the imported commands locally (they run on the remote server)
Get-RemoteADUser -Filter { Department -eq "IT" } | Select Name, SamAccountName

# Import an entire module remotely
Import-PSSession (New-PSSession -ComputerName dhcp01) -Module DhcpServer

Step 6: Configure PowerShell Remoting for Workgroup Computers

In workgroup or non-domain environments, Kerberos authentication is not available. Use NTLM by adding the remote computer to the TrustedHosts list, or use HTTPS with a valid certificate:

# Add specific computers to TrustedHosts (HTTP connections only)
Set-Item WSMan:localhostClientTrustedHosts -Value "server01,192.168.1.50,*.workgroup.local" -Force

# Add all hosts (use only in trusted, isolated environments)
Set-Item WSMan:localhostClientTrustedHosts -Value "*" -Force

# View current TrustedHosts
Get-Item WSMan:localhostClientTrustedHosts

# Connect to a workgroup computer with NTLM
$cred = Get-Credential
Enter-PSSession -ComputerName 192.168.1.50 -Credential $cred -Authentication Negotiate

Step 7: Create Custom Session Configurations (Constrained Endpoints)

Custom session configurations (also called JEA — Just Enough Administration) restrict what users can do in remote sessions. This allows delegating specific administrative tasks without granting full administrative rights:

# Create a role capability file defining allowed commands
New-PSRoleCapabilityFile -Path "C:JEADnsAdminRole.psrc" `
    -VisibleCmdlets @{ Name = "Get-DnsServerZone"; ValidateSet = $null }, "Get-DnsServerResourceRecord", "Add-DnsServerResourceRecord", "Remove-DnsServerResourceRecord" `
    -VisibleFunctions "Clear-Host"

# Create a session configuration file
New-PSSessionConfigurationFile -Path "C:JEADnsAdmin.pssc" `
    -SessionType RestrictedRemoteServer `
    -RoleDefinitions @{ "corpDNS-Admins" = @{ RoleCapabilityFiles = "C:JEADnsAdminRole.psrc" } } `
    -RunAsVirtualAccount

# Register the session configuration
Register-PSSessionConfiguration -Name "DnsAdmin" -Path "C:JEADnsAdmin.pssc" -Force

# Connect to the JEA endpoint
Enter-PSSession -ComputerName server01 -ConfigurationName DnsAdmin -Credential $cred

Step 8: Troubleshoot PowerShell Remoting

Use the built-in testing and diagnostic tools to troubleshoot connectivity issues:

# Test WinRM connectivity
Test-WSMan -ComputerName server02

# Verbose connection testing
$result = Test-NetConnection -ComputerName server02 -Port 5985
Write-Host "WinRM HTTP reachable: $($result.TcpTestSucceeded)"

# Check WinRM event log for errors
Get-WinEvent -LogName "Microsoft-Windows-WinRM/Operational" -MaxEvents 20 | Select TimeCreated, LevelDisplayName, Message | Format-List

# Run remoting with verbose output for diagnostics
Enter-PSSession -ComputerName server02 -Verbose

# Restart WinRM if needed
Restart-Service WinRM
winrm quickconfig -quiet

PowerShell Remoting is the cornerstone of modern Windows Server management at scale. By mastering Enter-PSSession for interactive work, Invoke-Command for bulk operations, persistent sessions for stateful workflows, and JEA for delegated administration, you build a comprehensive, secure, and efficient remote management capability that scales from managing a handful of servers to managing an enterprise infrastructure spanning thousands of systems across multiple data centers.