Featured image of post How-To Automate SSH Server Deployment on Windows by PowerShell

How-To Automate SSH Server Deployment on Windows by PowerShell

SSH protocol is de facto standard for command line remote access to servers, workstations etc. But Microsoft ignored this fact and technology for long time...

Windows word was pushed to complicated solutions with WinRM where (if you are not member of Active Directory Domain) you must provide many complicated settings to getting things works.

But times are changing. From Microsoft point of view Linux is no more “Evil”, but valuable friend. And then SSH server has arrived on Windows as optional feature. Due this is now possible to use the SSH to manage Windows workstation by Ansible or provide remote debugging or deployment by Visual Studio Code through RemoteDevelopment extensions. To unlock these great features, you must only deploy the SSH server on the Windows platform.

Core installation is as easy as select SSH server from Optional Features list or fire one PowerShell command:

Add-WindowsCapability -Online -Name OpenSSH.Server

Easy, right? But configure the SSH server, especially for access by Private/Public key pair (what is only one secure and useful option, by my opinion…) is something different. I configured SSH server manually onto two Windows computers and then I had to say: “No more”. I need to fall back to first Sys Admin golden rule:

Automate It!

Then I have written simple PowerShell script to do everything automatically. When the script finishes its work, you can immediately connect to the computer by SSH protocol without any other steps.

The script is available onto GitHub here: https://github.com/polachz/PowerShellScripts as enable-ssh-server.ps1 file.

The script has only two parameters, one mandatory, second optional:

  • SSHKey (Mandatory) - The public SSH Key (as string) to be used for authentication

  • Port (Optional) - Port where the SSH server will listen for connections. This port will be also enabled at the Windows Firewall and previously used port will be blocked by the Firewall.

The script must be run as Administrator so is necessary to fire it at elevated PowerShell prompt:

enable-ssh-server.ps1 "<place_SSH_Key_string_here>" -Port 2345

But wait. On typical Windows workstation you will get this error:

.\enable-ssh-server.ps1 : File C:\Tmp\enable-ssh-server.ps1 cannot be loaded 
because running scripts is disabled on this system. For more information, 
see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ .\\enable-ssh-server.ps1
+ ~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : SecurityError: (:) [], PSSecurityException
      + FullyQualifiedErrorId : UnauthorizedAccess

This is due default Windows restriction to PowerShell. Running script files is not allowed by default, because it can be potentially dangerous and 99% of Windows userbase doesn’t know anything about PowerShell or scripting.

So, now we have two possibilities:

  • Enable PowerShell scripts globally for whole computer
  • Use “Hack” to run the script only once and leave security settings as is.

Allow All Scripts Globally

To enable scripts globally, just type in elevated PowerShell prompt:

Set-ExecutionPolicy RemoteSigned

This allows to run scripts written on the computer (or copied here manually) without any restrictions. Scripts automatically downloaded from a remote location must have valid digital signature to be started.

Instead of RemoteSigned you can use Bypass parameter value. It disables all script restrictions even are local, remote, signed or unsigned. (REALLY NOT RECOMMENDED)

Bypass Restriction Only for Specific Script Run

Second possibility is to “Bypass” restrictions only for one script run. And it is easy. Just modify command to run the script by this way:

PowerShell.exe -ExecutionPolicy Bypass -File enable-ssh-server.ps1 <ssh_key>

And that’s it. The command fire new PowerShell process with disabled default restrictions and run the script passed here as -File parameter in context of this unrestricted PowerShell instance. Global OS setting will stay untouched.

And that’s it. The script saves my time each time when I use it. I believe that it will do same for you.

Built with Hugo
Theme Stack designed by Jimmy