Starting with Windows 10 build 1709, Windows integrates a port of OpenSSH, client and server.
This note describes how to install and configure the OpenSSH server sshd and run PowerShell scripts on a remote Windows server, from a Unix system, using SSH and public key authentication (no password).
Note: The way OpenSSH has been integrated in Windows 10 has changed a lot between versions 1709 and 21H2 of Windows 10. The Gist was updated several times to reflect the changes. This version applies to Windows 10 21H2.
First, open a PowerShell window with administrator privileges.
Check if OpenSSH server is installed:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Name : OpenSSH.Client~~~~0.0.1.0
State : Installed
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
Here, the client is installed but not the server. This is the default configuration.
Install the server package (use the displayed name if a more recent version is available):
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start the sshd service:
Start-Service sshd
Enable sshd automatic startup:
Set-Service -Name sshd -StartupType 'Automatic'
Check if the firewall rule for SSH is configured:
Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP"
In case of error, add the firewall rule:
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
To allow public key authentication, each user has to create the same type of authorized_keys file as on any Unix system. On Windows, the name of the file is C:\Users\_user_name_\.ssh\authorized_keys.
Create the .ssh subdirectory and the authorized_keys file with the list of allowed public keys.
On Unix systems, the authorized_keys file must have the protection mask 0600 or -rw-------. Similarly, the protection of the authorized_keys file must be manually adjusted on Windows.
Open a PowerShell window using your own user account and run the following commands:
$acl = Get-Acl ${env:HOMEDRIVE}${env:HOMEPATH}\.ssh\authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$rule = New-Object system.security.accesscontrol.filesystemaccessrule($env:USERNAME,"FullControl","Allow")
$acl.SetAccessRule($rule)
$acl | Set-Acl
Important: It the user is an administrator user, you need to append the public key in C:\ProgramData\ssh\administrators_authorized_keys instead. Then, fix the protextion of the file from a PowerShell window with administrator privileges:
$acl = Get-Acl ${env:ProgramData}\ssh\administrators_authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$rule1 = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow")
$rule2 = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")
$acl.SetAccessRule($rule1)
$acl.SetAccessRule($rule2)
$acl | Set-Acl
Now you can log in from your remote Unix systems using public key authentication and no password. The default shell is cmd.exe. To set Powershell as default shell, run the following command from a PowerShell window with administrator privileges:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force