PowerShell Remoting is a powerful feature that allows you to run commands on remote computers. While it traditionally used WinRM on Windows, modern PowerShell (pwsh) can now use SSH as its transport layer. This is a game-changer, as it provides a single, secure, and universal protocol to manage your entire fleet of servers, whether they are running Windows or Linux.
This guide will walk you through setting up and using PowerShell SSH remoting, from basic commands to a real-world example of deploying an application to multiple servers at once.
Why Use SSH for PowerShell Remoting?
- Cross-Platform: SSH is the industry standard for remote management on Linux. With OpenSSH now built into Windows, you can use the same protocol to manage all your servers.
- Firewall-Friendly: SSH uses a single, well-known port (TCP 22), which is often already open in firewalls, unlike the multiple ports required by WinRM.
- Secure and Reliable: SSH has a proven track record of security and is highly reliable, even over high-latency or unstable networks.
- Simple Authentication: It supports both password and public key authentication, the latter of which is ideal for automated scripts.
Part 1: Setting Up the Environment
Before you can use PowerShell SSH remoting, you need to ensure that both your client and server machines are properly configured.
On the Remote Server (Windows)
- Install OpenSSH Server:
# Run as Administrator Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 - Start and Configure the Service:
Start-Service sshd Set-Service sshd -StartupType Automatic - Configure the PowerShell Subsystem:
You need to tell the SSH server where to find the
pwsh.exeexecutable. Open thesshd_configfile (located at$env:ProgramData\ssh\sshd_config) and add or uncomment the following line:Subsystem powershell C:\Program Files\PowerShell\7\pwsh.exe -sshs -NoLogo -NoProfile - Open the Firewall Port:
New-NetFirewallRule -Name "SSH" -DisplayName "SSH" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Action Allow
On the Remote Server (Linux)
- Install OpenSSH Server:
sudo apt update sudo apt install openssh-server -y - Install PowerShell: Follow the official Microsoft guide to install PowerShell on Linux.
- Configure the PowerShell Subsystem:
Open
/etc/ssh/sshd_configand add the following line:Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile - Restart the SSH Service:
sudo systemctl restart sshd
Part 2: Basic Remoting Commands
Once your environment is set up, you can start running remote commands.
Interactive Sessions with Enter-PSSession
Enter-PSSession starts an interactive PowerShell session on the remote machine. It’s like being directly logged into the server’s PowerShell prompt.
# Connect to a Linux host using your username
Enter-PSSession -HostName "linux01" -UserName "admin" -SSHTransport
# Connect to a Windows host using key-based authentication
Enter-PSSession -HostName "win01" -UserName "Administrator" -KeyFilePath "C:\Users\Admin\.ssh\id_rsa" -SSHTransportRunning Single Commands with Invoke-Command
Invoke-Command runs a script block on one or more remote machines without starting an interactive session. This is perfect for automation.
# Get the kernel version from a Linux server
Invoke-Command -HostName "linux01" -UserName "admin" -SSHTransport -ScriptBlock { uname -a }
# Get the running services from a Windows server
Invoke-Command -HostName "win01" -UserName "Administrator" -SSHTransport -ScriptBlock { Get-Service | Where-Object Status -eq 'Running' }Part 3: A Practical, Real-World Example
Let’s say you need to deploy the 7-Zip installer to 100 Windows servers and install it silently.
1. Prepare Your Server List:
Create a file named servers.txt with the hostnames or IP addresses of your target servers, one per line.
2. Copy the Installer to All Servers:
You can use scp (which is available in modern PowerShell) to transfer the file to all servers in a loop.
$servers = Get-Content .\servers.txt
$localFile = "C:\Installers\7zip.msi"
$remotePath = "C:\Temp\7zip.msi"
foreach ($server in $servers) {
Write-Host "Copying installer to $server..."
# Note the backticks to escape the quotes for the remote path
scp $localFile "Administrator@$server`:`"$remotePath`""
}3. Install the Application Remotely:
Now, use Invoke-Command to run the installer silently on all servers.
$scriptBlock = {
# This code runs on each remote server
$installer = "C:\Temp\7zip.msi"
$arguments = "/i `"$installer`" /quiet /norestart"
Start-Process "msiexec.exe" -ArgumentList $arguments -Wait
}
foreach ($server in $servers) {
Write-Host "Installing 7-Zip on $server..."
Invoke-Command -HostName $server -UserName "Administrator" -SSHTransport -ScriptBlock $scriptBlock
Write-Host "Installation complete on $server."
}For even better performance, you can run these commands in parallel using ForEach-Object -Parallel or PowerShell jobs.
Conclusion
PowerShell’s SSH remoting is a powerful feature that unifies the management of Windows and Linux systems under a single, secure protocol. It combines the flexibility of PowerShell’s scripting language with the ubiquity and reliability of SSH.
By mastering PowerShell SSH remoting, you can build robust, cross-platform automation scripts that can scale to manage your entire infrastructure, no matter the operating system.