5.4 OpenSSH on Windows Server & PowerShell Remoting over SSH
Key Takeaways
- OpenSSH ships in-box from Windows Server 2019 and Windows 10 build 1809 and is installed as a Feature on Demand named OpenSSH.Server~~~~0.0.1.0.
- sshd reads %programdata%\ssh\sshd_config and generates that file plus host keys on first service start; configuration changes require a service restart.
- Windows OpenSSH supports only password and publickey authentication — Microsoft Entra account authentication is not supported.
- Keys for any member of the Administrators group are read from %programdata%\ssh\administrators_authorized_keys, which must be ACLed to SYSTEM and BUILTIN\Administrators only.
- GSSAPI (Kerberos) authentication is disabled by default and is available only on Windows Server 2022 and later.
OpenSSH on Windows Server & PowerShell Remoting over SSH
WinRM-based PowerShell remoting assumes a Windows-to-Windows relationship with Kerberos or an explicit TrustedHosts list behind it. In a hybrid estate that also runs Ubuntu and Red Hat Enterprise Linux — on-premises and as Azure IaaS virtual machines — that assumption breaks down. OpenSSH is Microsoft's answer: the same sshd daemon, key material and client tooling used across the Linux world, shipped in-box in Windows Server and usable as a PowerShell remoting transport.
1. OpenSSH as a Native Windows Server Role
Microsoft added OpenSSH to the operating system starting with Windows Server 2019 and Windows 10 build 1809. It is not a third-party port and needs no download: both the client and the server are Features on Demand already staged in the image.
+-----------------------------------------------------------------------------------------+
| OPENSSH HYBRID MANAGEMENT ARCHITECTURE |
| |
| [Admin Workstation] |
| - Runs: Enter-PSSession -HostName 10.0.1.5 -UserName azureadmin -KeyFilePath ~/.ssh/id_rsa
| | |
| | Standard SSH Protocol (TCP Port 22) - Asymmetric Key Authentication |
| v |
| +-----------------------------------------------------------------------------------+ |
| | TARGET WINDOWS SERVER 2025 (OpenSSH) | |
| | - sshd.exe Listening on TCP Port 22 | |
| | - Authenticates via %ProgramData%\ssh\administrators_authorized_keys | |
| | - Launches Subsystem: powershell.exe -sshs -NoLogo -NoProfile | |
| +-----------------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------------------+
Installing and Configuring OpenSSH Server on Windows Server:
# Install OpenSSH Server capability
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Start sshd service and set startup type to Automatic
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
# Configure firewall rule for SSH (TCP Port 22)
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' `
-Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
PowerShell Remoting over SSH Syntax:
# Interactive remoting over SSH to a Windows or Linux node
Enter-PSSession -HostName '10.10.1.20' -UserName 'secadmin' -KeyFilePath 'C:\Users\admin\.ssh\id_ed25519'
# Parallel execution across Linux and Windows instances using SSH
$SSHOptions = @{ HostName = 'ubuntu-srv01.corp.contoso.com'; UserName = 'azureuser'; KeyFilePath = '~/.ssh/id_rsa' }
$Session = New-PSSession @SSHOptions
Invoke-Command -Session $Session -ScriptBlock { uname -a; Get-Date }
2. Services, Configuration Files and Key Locations
Two Windows services back the implementation. sshd is the server daemon, and ssh-agent caches decrypted private keys for the client. Neither starts automatically after the capability is added, which is why Set-Service -StartupType Automatic belongs in every deployment script.
| Path or key | Purpose |
|---|---|
%programdata%\ssh\sshd_config | Server configuration. Generated with defaults on first service start if missing. |
%programdata%\ssh\ssh_config | System-wide client configuration. |
%userprofile%\.ssh\config | Per-user client configuration; takes precedence over the system-wide file. |
%userprofile%\.ssh\authorized_keys | Public keys for a standard user (the AuthorizedKeysFile default is .ssh/authorized_keys). |
%programdata%\ssh\administrators_authorized_keys | Public keys used instead for any member of the Administrators group. |
%programdata%\ssh\ssh_host_*_key | RSA, ECDSA and Ed25519 host keys, auto-generated on first start. |
HKLM:\SOFTWARE\OpenSSH → DefaultShell | String value naming the shell launched for an interactive session. |
%systemdrive%\Windows\System32\OpenSSH | Default binary location. |
[!WARNING] The
administrators_authorized_keysfile is the single most common cause of "key authentication works for a normal user but not for the administrator". sshd refuses to honour it unless its ACL is restricted toNT Authority\SYSTEMandBUILTIN\Administrators. Reset it explicitly:icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
# Make PowerShell 7 the interactive shell for incoming SSH sessions
New-ItemProperty -Path 'HKLM:\SOFTWARE\OpenSSH' -Name DefaultShell `
-Value 'C:\Program Files\PowerShell\7\pwsh.exe' -PropertyType String -Force
# sshd reads its configuration only at service start
Restart-Service sshd
3. Authentication and Access Control in sshd_config
Windows OpenSSH supports exactly two authentication methods: password and publickey. Microsoft Entra account authentication is not supported, and several directives familiar from Linux — X11Forwarding, HostbasedAuthentication, AuthorizedKeysCommand, PermitUserEnvironment — are not implemented at all. PermitRootLogin has no meaning on Windows; to block administrative sign-in you deny the group instead.
GSSAPIAuthentication (Kerberos) is available only from Windows Server 2022 onward and is disabled by default; enabling it also requires the client to specify the host with ssh -K or an equivalent GSSAPIAuthentication yes entry in the client config.
Access rules are processed in a fixed order — DenyUsers, AllowUsers, DenyGroups, then AllowGroups — and every principal name must be written in lower case. Domain principals resolve to domain_short_name\user_name, and because @ already means "from this host" in SSH syntax, Windows uses ? in its place when matching a domain:
# %programdata%\ssh\sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
DenyUsers contoso\legacysvc
AllowGroups contoso\sshadmins contoso\serveroperators
# Register PowerShell as an SSH subsystem so PowerShell remoting can use this host
Subsystem powershell C:/Program Files/PowerShell/7/pwsh.exe -sshs -NoLogo -NoProfile
For file-based troubleshooting set SyslogFacility LOCAL0, which writes to %programdata%\ssh\logs; any other value, including the default AUTH, sends logging to Event Tracing for Windows instead.
4. Choosing Between WinRM and SSH as the Remoting Transport
| WinRM transport | SSH transport | |
|---|---|---|
| PowerShell version | Windows PowerShell 5.1 and PowerShell 7 | PowerShell 7 (or 6) on both ends |
| Cross-platform | Windows only in practice | Windows, Linux, macOS |
| Authentication | Kerberos, NTLM, CredSSP, certificate | Password or public key |
| Default port | 5985 / 5986 | 22 |
| Double-hop | Requires CredSSP or resource-based constrained delegation | Handled by key forwarding or an agent |
| JEA support | Yes | No — JEA endpoints are a WinRM concept |
That last row is the exam-relevant boundary: a scenario that requires a constrained JEA endpoint rules out the SSH transport, while a scenario that requires managing Linux and Windows from one console rules out WinRM. They coexist happily on the same server, so the real design answer is usually "both, for different audiences".
A hybrid systems engineer wants to administer a heterogeneous fleet of Azure Linux VMs and Windows Server 2025 instances using PowerShell Remoting over OpenSSH. Which parameter set on Enter-PSSession correctly establishes an SSH-based remoting session using an asymmetric key pair?
An administrator adds the OpenSSH.Server capability to a Windows Server 2025 host, copies a public key into C:\ProgramData\ssh\administrators_authorized_keys, and attempts a key-based sign-in as a member of the Administrators group. The connection falls back to a password prompt. A standard user with a key in their own profile authenticates successfully. What is the most likely cause?