OpenSSH on Windows Server 2022
Windows Server 2022 ships with OpenSSH as an optional built-in feature, eliminating the need for third-party SSH servers like Bitvise or freeSSHd. The OpenSSH Server implementation is maintained by Microsoft and based on the open-source OpenSSH project, with Windows-specific adaptations. It provides a standards-compliant SSH server that supports key-based authentication, SFTP, port forwarding, and custom default shells. For administrators accustomed to managing Linux servers over SSH, OpenSSH on Windows Server 2022 significantly reduces the cognitive overhead of managing mixed environments — the same SSH client, keys, and tooling work regardless of the target OS.
OpenSSH on Windows Server 2022 is particularly valuable for Ansible automation (using the ansible_connection: ssh plugin), for developers connecting to Windows development servers, for secure file transfers via SFTP, and as an alternative to WinRM in environments where SSH is the established standard. The OpenSSH Server runs as a Windows service (sshd) and listens on TCP port 22 by default.
Installing OpenSSH Server
On Windows Server 2022, OpenSSH Server is an optional Windows capability. Check whether it is already installed:
Get-WindowsCapability -Online | Where-Object Name -like "OpenSSH*"
The output shows two capabilities: OpenSSH.Client and OpenSSH.Server. Install the server component:
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
The tilde-separated version suffix (~~~~0.0.1.0) is required for this capability. If you are in a disconnected environment without Windows Update access, use DISM with a mounted Windows Server 2022 ISO as the source:
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -Source D:sourcessxs
After installation, verify both components are present:
Get-WindowsCapability -Online | Where-Object Name -like "OpenSSH*" | Select-Object Name, State
Both should show State: Installed.
Starting and Configuring the sshd Service
After installation, the sshd service exists but is not started or set to automatic. Configure it to start automatically and start it immediately:
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
Verify the service is running:
Get-Service sshd | Select-Object Name, Status, StartType
The ssh-agent service (for key management) is also installed. Enable it if you plan to use SSH key forwarding or Pageant-style key storage:
Start-Service ssh-agent
Set-Service -Name ssh-agent -StartupType Automatic
Configuring the Windows Firewall Rule for Port 22
The installation process creates a firewall rule automatically, but verify it is configured correctly:
Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" | Select-Object Name, Enabled, Direction, Action, LocalPort
If the rule was not created (for example, if the firewall service was offline during installation), create it manually:
New-NetFirewallRule `
-Name "OpenSSH-Server-In-TCP" `
-DisplayName "OpenSSH Server (sshd)" `
-Enabled True `
-Direction Inbound `
-Protocol TCP `
-Action Allow `
-LocalPort 22
For tighter security, restrict inbound SSH to specific source IPs or subnets:
Set-NetFirewallRule `
-Name "OpenSSH-Server-In-TCP" `
-RemoteAddress 10.0.0.0/8, 192.168.1.0/24
The sshd_config File
The OpenSSH server configuration file on Windows is located at C:ProgramDatasshsshd_config. This directory and its files are created during installation. The sshd_config syntax is identical to OpenSSH on Linux, making it familiar to Unix administrators. To edit it, open an elevated PowerShell session:
notepad C:ProgramDatasshsshd_config
Or use PowerShell to modify specific directives programmatically. Key settings to review and configure:
# Disable password authentication (after setting up keys)
(Get-Content C:ProgramDatasshsshd_config) -replace '#PasswordAuthentication yes','PasswordAuthentication no' | Set-Content C:ProgramDatasshsshd_config
# Allow only specific users
Add-Content C:ProgramDatasshsshd_config "`nAllowUsers Administrator ansible-svc deploy-user"
# Change the listening port (optional)
(Get-Content C:ProgramDatasshsshd_config) -replace '#Port 22','Port 2222' | Set-Content C:ProgramDatasshsshd_config
After modifying sshd_config, always restart the sshd service for changes to take effect:
Restart-Service sshd
Configuring Key-Based Authentication
Key-based authentication is more secure than password authentication and is required for automation. On Windows Server 2022, the authorized_keys file location depends on the user:
For standard users, the authorized_keys file is at: C:Users<username>.sshauthorized_keys
For the Administrator account (and members of the Administrators group), the sshd_config default redirects to a centralized location: C:ProgramDatasshadministrators_authorized_keys
This is configured in sshd_config via the Match Group directive. Check these lines in sshd_config:
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
To set up key-based auth for the Administrator account, create the file and set correct ACLs:
# Create the authorized_keys file
$adminKeysPath = "C:ProgramDatasshadministrators_authorized_keys"
New-Item -ItemType File -Path $adminKeysPath -Force
# Add your public key
Add-Content $adminKeysPath "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@controlnode"
# Fix ACLs — only SYSTEM and Administrators should have access, not regular users
icacls $adminKeysPath /inheritance:r
icacls $adminKeysPath /grant "SYSTEM:F"
icacls $adminKeysPath /grant "BUILTINAdministrators:F"
For a non-admin user, place the key in their profile directory:
$userKeysPath = "C:Usersdeployuser.sshauthorized_keys"
New-Item -ItemType Directory -Path "C:Usersdeployuser.ssh" -Force
New-Item -ItemType File -Path $userKeysPath -Force
Add-Content $userKeysPath "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... deploy@controlnode"
icacls $userKeysPath /inheritance:r
icacls $userKeysPath /grant "SYSTEM:F"
icacls $userKeysPath /grant "deployuser:F"
Setting the Default Shell to PowerShell
By default, OpenSSH on Windows uses cmd.exe as the shell. For PowerShell 7 (recommended) or Windows PowerShell 5.1, configure the default shell via the registry:
# Set PowerShell 7 as the default shell
New-ItemProperty -Path "HKLM:SOFTWAREOpenSSH" `
-Name DefaultShell `
-Value "C:Program FilesPowerShell7pwsh.exe" `
-PropertyType String `
-Force
# Set the default shell arguments (optional)
New-ItemProperty -Path "HKLM:SOFTWAREOpenSSH" `
-Name DefaultShellCommandOption `
-Value "/c" `
-PropertyType String `
-Force
For Windows PowerShell 5.1:
New-ItemProperty -Path "HKLM:SOFTWAREOpenSSH" `
-Name DefaultShell `
-Value "C:WindowsSystem32WindowsPowerShellv1.0powershell.exe" `
-PropertyType String `
-Force
SFTP Configuration and the SSH Subsystem
The SFTP subsystem is enabled by default in Windows OpenSSH. The sftp-server binary is located at C:WindowsSystem32OpenSSHsftp-server.exe and is referenced in sshd_config:
Subsystem sftp sftp-server.exe
No additional configuration is needed to use SFTP. Connect from any SFTP client:
sftp [email protected]
Or use PowerShell 7’s built-in scp support to transfer files to Windows Server 2022:
scp -i ~/.ssh/id_ed25519 /local/path/file.zip [email protected]:"C:/Installers/file.zip"
Configuring a Login Banner (MOTD)
Display a legal warning or informational banner before authentication using the Banner directive in sshd_config:
# Create the banner file
Set-Content "C:ProgramDatasshbanner.txt" @"
**********************************************************************
WARNING: This system is restricted to authorized users only.
All activity is monitored and logged. Unauthorized access is prohibited.
**********************************************************************
"@
# Add to sshd_config
Add-Content C:ProgramDatasshsshd_config "`nBanner C:ProgramDatasshbanner.txt"
Restart-Service sshd
Testing SSH Login and Using OpenSSH with Ansible
Test the SSH connection from your control node or another machine:
ssh -i ~/.ssh/id_ed25519 -v [email protected]
The -v flag shows verbose connection details including authentication method negotiation and key exchange. For Ansible, configure the inventory to use SSH instead of WinRM:
[windows]
winserver2022.contoso.com
[windows:vars]
ansible_connection=ssh
ansible_shell_type=powershell
ansible_user=administrator
ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_become=false
Test Ansible connectivity using win_ping over SSH:
ansible windows -i inventory.ini -m win_ping
SSH-based Ansible on Windows Server 2022 eliminates the need for WinRM configuration and the pywinrm Python library, simplifying the automation stack considerably — especially in environments with existing SSH infrastructure and PKI.