Remote PowerShell Core session to a Linux host from Windows machine

Remote sessions using OpenSSH from Windows to Linux host

Starting from January 2018, Microsft has made PowerShell Core 6, a cross-platform tool available not only to Windows users which was the case so far with previous versions, but to Linux and Mac users as well.

Since it was tool for Windows only, it had it's own ways for remoting using WinRM unlike Linux operating systems which primarily rely on SSH. Windows is great for editing and development, I find it really comfortable to work on with so many tools and platform available. On the other hand, it is too robust, especially because of it's UI which makes it not so suitable for scaling. On the other hand, you can run Linux as a headless OS which makes is blazing fast, but it is not so comfortable for development because of the lack of UI.

For me winning combination is using Windows for development, but deploy to Linux machine. Now when there is PowerShell runing on both hosts it makes it a lot easier to automate stuff. Let's start with setting up new PowerShell on both host and finally connect from the development Windows machine to deployment Linux machine.

1. Setting up PowerShell on Linux

I will use Debian headless Linux VM for setting up PowerShell 6 Core for this demo, but you are free to use any other distro. If you are planning to install PowerShell 6 Core on any other distro other than Debian 9 Linux, follow the instructions from Microsoft documentation page https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-powershell-core-on-linux?view=powershell-6. Login to your Linux machine using SSH and execute following commands

sudo apt-get update
sudo apt-get install curl gnupg apt-transport-https
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list'
sudo apt-get update
# Install PowerShell
sudo apt-get install -y powershell
    

Now just verify the powershell is installed

pwsh -V
    

You should get the PowerShell version installed as an output of the command above

2. Configure OpenSSH on Linux host

First thing we need to do to enable OpenSSH connections for PowerShell is to modify OpenSSH config. Open the config using nano editor 

sudo nano /etc/ssh/sshd_config
    

In opened configuration file in nano editor, paste the following live below existing subsystem line

Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile
    

Save the file and exit nano editor with CTRL+O ENTER to save and CTRL+X key combination to close nano editor 

Restart the sshd service in order for it to pick up new configuration 

sudo service sshd restart
    

We have now setup out Linux machine for running PowerShell 6 Core and to accept remote PowerShell sessions over OpenSSH.

3. Setting up PowerShell 6 Core on Windows machine

Setting up PowerShell 6 Core on Windows is pretty straight forward, pretty much like any other application on Windows. Navigate to https://github.com/PowerShell/PowerShell#get-powershell in your browser and download the .msi installer for your Windows platform. Upon download, double click on .msi installation package and follow the wizard instructions.

Verify that PowerShell 6 Core is installed by running the following commands in Windows console

cd C:\Program Files\PowerShell\6.0.2
pwsh -V
    

You should get the PowerShell Core version installed on your Windows machine. Additionally you can update PATH environment variable from Windows UI. You can access environment variables direly from elevated Command Prompt window by executing the following command

rundll32 sysdm.cpl,EditEnvironmentVariables
    

Or by running the following command Windows command prompt which will append PowerShell 6 Core installation path folder to PATH environemnt varibale 

setx PATH "%PATH%;C:\Program Files\PowerShell\6.0.2" /M
    
Note

Before adding the PowerShell path to PATH Environment Variable, verify that PowerShell Core is installed at that location. Folder may vary depending on the release you installed

4. Setting up OpenSSH on Windows machine

Download OpenSSH binaries for Windows from https://github.com/PowerShell/Win32-OpenSSH/releases. Extract files from downloaded archive on the Windows machine. I picked C:\Program Files\OpenSSH folder. For the consistency with this sample, create same folder on your machine and extract archive to this folder.

Open Windows console as administrator and execute following command

PowerShell -ExecutionPolicy bypass -File "C:\Program Files\OpenSSH\install-sshd.ps1"
    

You should get the following output from the command above executed

Powershell Remote Openssh

From the elevated command prompt you can run the following command to get you directly to the Windows environment variables window 

rundll32 sysdm.cpl,EditEnvironmentVariables
    

In the System Variables section, locate Path variable and click Edit button

Path

Path list should already contain path to OpenSSH with value %SYSTEMROOT%\System32\OpenSSH\. If this value is not present in the Path list, add the path of OpenSSH installation which is in our case C:\Program Files\OpenSSH.

Environemt 

Open the firewall port for OpenSSH by running the following command from elevated (Run as Administrator) Windows console

netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22
    

Restart sshd service from Control Panel > Administrative Tools > Services of running PowerShell command from elevated Windows console

PowerShell -command "Restart-Service sshd -Force"
    

5. Connect to remote session from PowerShell 6 Core with OpenSSH

Now when we have PowerShell 6 Core setup on both Windows and Linux host we can try to connect and execute a command for remote session. You can use both Invoke-Command or Enter-Pssession. The command structure for both options is the following

Invoke-Command -Hostname "IP or Hostname" -UserName "Username" -ScriptBlock {PowerShell commands}
Enter-Pssession -Hostname "IP or Hostname" -UserName "Username" -ScriptBlock {PowerShell commands}
    

For and example, let's list the processes on the remote Linux host

Invoke-Command -Hostname 192.168.211.129 -UserName dejan -ScriptBlock {Get-Process}
    

The output of this command will be the table of all processes currently running on the remote Linux host

References

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform includion ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

.NET

read more

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

Comments for this article