Introduction

OpenSSH Server is available for Windows Server 2016 as an optional Windows feature (from Windows 10 1809 / Server 2019 onward it is built-in; for Server 2016 it is installed as a standalone package). Installing OpenSSH on Windows Server 2016 enables SSH-based remote access — the same client tools used on Linux — giving administrators a secure, encrypted alternative to RDP and WinRM for remote shell access, file transfer (SFTP), and key-based authentication.

Checking Windows Server 2016 Build Version

OpenSSH availability depends on the Windows Server 2016 build:

# Check the exact build number
[System.Environment]::OSVersion.Version
Get-ItemProperty 'HKLM:SOFTWAREMicrosoftWindows NTCurrentVersion' |
    Select-Object CurrentBuild,UBR,ReleaseId

# Windows Server 2016 is build 14393
# OpenSSH must be downloaded manually for Server 2016

Downloading and Installing OpenSSH for Windows Server 2016

Download the latest OpenSSH for Windows release from the official GitHub repository and install it:

# Download latest OpenSSH for Windows
$url = 'https://github.com/PowerShell/Win32-OpenSSH/releases/latest/download/OpenSSH-Win64.zip'
Invoke-WebRequest -Uri $url -OutFile C:OpenSSH-Win64.zip

# Extract to system directory
Expand-Archive -Path C:OpenSSH-Win64.zip -DestinationPath 'C:Program Files'
Rename-Item -Path 'C:Program FilesOpenSSH-Win64' -NewName 'OpenSSH'

# Install sshd and ssh-agent as services
& 'C:Program FilesOpenSSHinstall-sshd.ps1'

# Set services to auto-start
Set-Service -Name sshd -StartupType Automatic
Set-Service -Name ssh-agent -StartupType Automatic

# Start the services
Start-Service sshd
Start-Service ssh-agent

# Verify
Get-Service sshd,ssh-agent | Select-Object Name,Status,StartType

Configuring the Windows Firewall

Open port 22 to allow SSH connections from authorised networks:

# Allow SSH from management network only
New-NetFirewallRule -DisplayName 'OpenSSH Server (sshd)' `
    -Direction Inbound -Protocol TCP -LocalPort 22 `
    -RemoteAddress '10.0.0.0/8' -Action Allow -Profile Any

# Verify the rule was created
Get-NetFirewallRule -DisplayName 'OpenSSH Server*' | 
    Select-Object DisplayName,Direction,Action,Enabled

Configuring sshd_config for Security

Harden the SSH server configuration file at C:ProgramDatasshsshd_config:

# Edit sshd_config
$sshd_config = 'C:ProgramDatasshsshd_config'

# Key security settings to configure
@"
Port 22
ListenAddress 0.0.0.0
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitEmptyPasswords no
MaxAuthTries 4
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups ssh-users
LogLevel VERBOSE
Subsystem sftp sftp-server.exe
"@ | Set-Content $sshd_config

# Create an ssh-users AD group for access control
New-ADGroup -Name 'ssh-users' -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity 'ssh-users' -Members 'Administrator'

# Restart sshd to apply changes
Restart-Service sshd

Configuring Key-Based Authentication

Set up SSH public key authentication for password-less secure logins:

# On the client machine, generate an SSH key pair
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/ws2016_admin

# Copy the public key to Windows Server
# Option 1: Use ssh-copy-id (from Linux client)
ssh-copy-id -i ~/.ssh/ws2016_admin.pub [email protected]

# Option 2: Manually create authorized_keys on Windows
# Create the .ssh directory in the user's profile
New-Item -Path 'C:UsersAdministrator.ssh' -ItemType Directory -Force

# Add the public key content
$pubKey = 'ssh-ed25519 AAAAC3... [email protected]'
$pubKey | Set-Content 'C:UsersAdministrator.sshauthorized_keys'

# For administrators, the authorised_keys file must be in a system location
# Set the correct permissions (OpenSSH requires strict permissions)
icacls 'C:UsersAdministrator.sshauthorized_keys' /inheritance:r
icacls 'C:UsersAdministrator.sshauthorized_keys' /grant 'SYSTEM:F'
icacls 'C:UsersAdministrator.sshauthorized_keys' /grant 'Administrators:F'

Configuring the Default Shell

Set PowerShell as the default shell for SSH sessions instead of cmd.exe:

# Set PowerShell 5.1 as the default SSH shell
New-ItemProperty -Path 'HKLM:SOFTWAREOpenSSH' `
    -Name DefaultShell `
    -Value 'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe' `
    -PropertyType String -Force

# Verify
Get-ItemProperty 'HKLM:SOFTWAREOpenSSH' -Name DefaultShell

Testing SSH Connectivity

Validate that OpenSSH is working correctly from both Windows and Linux clients:

# From Linux client
ssh [email protected]
ssh -i ~/.ssh/ws2016_admin [email protected]

# From Windows PowerShell client
ssh [email protected]

# SFTP file transfer
sftp [email protected]
# > put localfile.txt /C:/Temp/
# > get /C:/Temp/report.csv ./

# Check sshd event logs on Windows
Get-EventLog -LogName Security -Source 'OpenSSH' -Newest 20 |
    Select-Object TimeGenerated,EntryType,Message

Adding SSH to PowerShell Remoting

Configure PowerShell SSH remoting so that Enter-PSSession and Invoke-Command work over SSH:

# Register the PowerShell SSH subsystem in sshd_config
Add-Content 'C:ProgramDatasshsshd_config' `
    "`nSubsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo"

# Install PowerShell 7 for best SSH remoting support
Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI -Quiet"

# Test PowerShell remoting over SSH
Enter-PSSession -HostName ws2016-01 -UserName Administrator -SSHTransport
Invoke-Command -HostName ws2016-01 -UserName Administrator -SSHTransport -ScriptBlock {$PSVersionTable}

Summary

OpenSSH on Windows Server 2016 provides a modern, secure, cross-platform remote access solution that complements or replaces legacy WinRM and RDP for administrative tasks. With key-based authentication, PowerShell as the default shell, and SFTP file transfer support, OpenSSH transforms Windows Server 2016 into a first-class SSH target that integrates seamlessly into Linux-centric automation and DevOps toolchains including Ansible, Terraform, and CI/CD pipelines.