Hybrid Cloud PowerShell Windows Server 2019 Windows Server 2022 Windows Server 2025

How to install OpenSSH on a Windows Server 2019/2022/2025 using a PowerShell script


In this blog post, I’ll walk you through installing OpenSSH on Windows Server 2019, 2022, or 2025 using a PowerShell script.

Chances are you’re already familiar with OpenSSH (Open Secure Shell), the open-source implementation of the SSH protocol. It’s the standard for secure remote access, encrypted communication, and file transfers, and has long been a go-to for Linux administrators. Today, it’s also a powerful tool for Windows administrators for cross-platform remote management.

Starting with Windows Server 2019, OpenSSH became available as an optional feature. In Windows Server 2025, it is even pre-installed by default, though not enabled out of the box.

To automate the installation of OpenSSH on Windows Server 2019 or Windows Server 2022, or to enable it on a Windows Server 2025, I’ve written a PowerShell script. In this blog post, I’ll explain how to use it and walk you through the process.


Table of Contents


Prerequisites

  • A server (either physical or virtual) running Windows Server 2019, 2022, or 2025.
  • An account that is a member of the built-in Administrators group, which is required to log in to the server and run the script.



PowerShell script

First, let me explain what this PowerShell script does:

  • Check if PowerShell is running as Administrator, otherwise exit the script.
  • Check if the OS is Windows Server 2025 and set a flag to control script execution.
  • Install OpenSSH Server if OS is Windows Server 2019 or Windows Server 2022.
  • Install OpenSSH Client if OS is Windows Server 2019 or Windows Server 2022.
  • Start and enable the SSH service.  
  • Allow OpenSSH through the Windows Firewall.


To use the script, start by saving a copy as “Install-OpenSSH-on-a-Windows-Server-2019-2022-2025.ps1” or download it directly from GitHub. Adjust the variables to suit your specific needs, and then run the script using Windows PowerShell (as Administrator) on the server.

💡 I usually save the script locally in the C:\Temp folder on the server and run it from there.




<#
.SYNOPSIS

A script used to install and configure OpenSHH on a Windows Server 2019, 2022, or 2025.

.DESCRIPTION

A script used to install and configure OpenSHH on a Windows Server 2019, 2022, or 2025.
This script will do all of the following:

Check if PowerShell is running as Administrator, otherwise exit the script.
Check if the OS is Windows Server 2025 and set a flag to control script execution.
Install OpenSSH Server if OS is Windows Server 2019 or Windows Server 2022.
Install OpenSSH Client if OS is Windows Server 2019 or Windows Server 2022. 
Start and enable the SSH service.   
Allow OpenSSH through the Windows Firewall.

.NOTES

Filename:       Install-OpenSSH-on-a-Windows-Server-2019-2022-2025.ps1
Created:        02/04/2025
Last modified:  02/04/2025
Author:         Wim Matthyssen
Version:        1.0
PowerShell:     Windows PowerShell (v5.1 or above)
OS:             Windows Server 2019, Windows Server 2022, or Windows Server 2025
Action:         Update variables if needed to fit your environment.
Disclaimer:     This script is provided "As Is" with no warranties.

.EXAMPLE

.\Install-OpenSSH-on-a-Windows-Server-2019-2022-2025.ps1 

.LINK

https://wmatthyssen.com/2025/04/10/how-to-install-openssh-on-a-windows-server-2019-2022-2025-using-a-powershell-script/
#>

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Variables

# Dynamic variables - Please change the values if needed to fit your environment.
$firewallRuleName = "OpenSSH-Server-In"  # Variable for the firewall rule name

Set-PSBreakpoint -Variable currenttime -Mode Read -Action {$global:currenttime = Get-Date -Format "dddd MM/dd/yyyy HH:mm"} | Out-Null
$foregroundColor1 = "Green"
$foregroundColor2 = "Yellow"
$foregroundColor3 = "Red"
$writeEmptyLine = "`n"
$writeSeperatorSpaces = " - "

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Write script started.

Write-Host ($writeEmptyLine + "# Script started. Without errors, it can take up to 2 minutes to complete" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine 

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Check if PowerShell is running as Administrator, otherwise exit the script.

$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdministrator = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if ($isAdministrator -eq $false) 
{
    Write-Host ($writeEmptyLine + "# Please run PowerShell as Administrator" + $writeSeperatorSpaces + $currentTime)`
    -foregroundcolor $foregroundColor3 $writeEmptyLine
    exit
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Check if the OS is Windows Server 2025 and set a flag to control script execution.

try {
    $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
    if ($osInfo.Caption -like "*Windows Server 2025*") {
        Write-Host ($writeEmptyLine + "# OS is Windows Server 2025. Continuing script execution" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
        $isWindowsServer2025 = $true
    } else {
        # OS is not Windows Server 2025, continue with the script
        Write-Host ($writeEmptyLine + "# OS is not Windows Server 2025. Continuing script execution" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
        $isWindowsServer2025 = $false
    }
} catch {
    Write-Host ($writeEmptyLine + "# Failed to retrieve OS information: $($_.Exception.Message)" + $writeSeperatorSpaces + $global:currenttime)`
    -foregroundcolor $foregroundColor3 $writeEmptyLine
    exit
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Install OpenSSH Server if OS is Windows Server 2019 or Windows Server 2022.

if (-not $isWindowsServer2025) {
    try {
        Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 -ErrorAction Stop | Out-Null 
        Write-Host ($writeEmptyLine + "# OpenSSH Server installed" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
    } catch {
        Write-Host ($writeEmptyLine + "# Failed to install OpenSSH Server: $($_.Exception.Message)" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor3 $writeEmptyLine
        exit
    }
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Install OpenSSH Client if OS is Windows Server 2019 or Windows Server 2022.

if (-not $isWindowsServer2025) {
    try {
        Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 -ErrorAction Stop | Out-Null 
        Write-Host ($writeEmptyLine + "# OpenSSH Client installed" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
    } catch {
        Write-Host ($writeEmptyLine + "# Failed to install OpenSSH Client: $($_.Exception.Message)" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor3 $writeEmptyLine
        exit
    }
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Start and enable the SSH service.

try {
    # Start the SSH service
    Start-Service sshd
    # Set the SSH service to start automatically with Windows
    Set-Service -Name sshd -StartupType Automatic
    Write-Host ($writeEmptyLine + "# SSH service started and set to automatic" + $writeSeperatorSpaces + $global:currenttime)`
    -foregroundcolor $foregroundColor2 $writeEmptyLine
} catch {
    Write-Host ($writeEmptyLine + "# Failed to start or configure SSH service: $($_.Exception.Message)" + $writeSeperatorSpaces + $global:currenttime)`
    -foregroundcolor $foregroundColor3 $writeEmptyLine
    exit
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Allow OpenSSH through the Windows Firewall.

try {
    # Check if the firewall rule already exists
    $firewallRule = Get-NetFirewallRule -Name $firewallRuleName -ErrorAction SilentlyContinue

    if ($null -eq $firewallRule) {
        # Rule does not exist, create it
        New-NetFirewallRule -Name $firewallRuleName -DisplayName "OpenSSH Server (sshd)" -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 | Out-Null
        Write-Host ($writeEmptyLine + "# Windows Firewall rule created and configured for OpenSSH" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
    } else {
        # Rule already exists
        Write-Host ($writeEmptyLine + "# Windows Firewall rule already exists and is configured for OpenSSH" + $writeSeperatorSpaces + $global:currenttime)`
        -foregroundcolor $foregroundColor2 $writeEmptyLine
    }
} catch {
    Write-Host ($writeEmptyLine + "# Failed to configure Windows Firewall for OpenSSH: $($_.Exception.Message)" + $writeSeperatorSpaces + $global:currenttime)`
    -foregroundcolor $foregroundColor3 $writeEmptyLine
    exit
}

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Write script completed.

Write-Host ($writeEmptyLine + "# Script completed" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine 

## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Using the script on supported Windows Server OSes

Windows Server 2019


After running the script, you can check if OpenSSH was successfully installed by running the following command in PowerShell:

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'


You can also check the Services panel (press Win + R, type services.msc, and hit Enter) to see if the OpenSSH SSH Server service is running and has its Startup Type set to Automatic.



Windows Server 2022


After running the script, you can check if OpenSSH was successfully installed by running the following command in PowerShell:

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'



You can also check the Services panel (press Win + R, type services.msc, and hit Enter) to see if the OpenSSH SSH Server service is running and has its Startup Type set to Automatic.



Windows Server 2025


After running the script, you can verify that OpenSSH was successfully installed by opening Server Manager and checking that Remote SSH Access is marked as Enabled, or by running the PowerShell command mentioned earlier in the Windows Server 2019 or 2022 section.



Connecting to an OpenSSH Server on Windows Server

To connect to an OpenSSH server running on a Windows Server that is part of a domain, you can use any SSH client, such as PowerShell, Windows Terminal, PuTTY, or KiTTY.

If you’re using Windows Terminal or PowerShell, use the following command format:

ssh domain\username@servername


Select Yes if you’re connecting for the first time. This adds the server to the list of known SSH hosts on your Windows client.

The service will then prompt you for your password. As a security precaution, your password characters won’t be displayed as you type.

Once connected, you should see the standard Windows command shell prompt, where you can run commands to manage the server, install new features, troubleshoot issues, or perform other operational tasks.



When connecting to an OpenSSH server running on a standalone Windows Server (i.e., not joined to a domain), the simplest approach is to use a client like PuTTY or KiTTY.

Simply connect using the server’s IP address and a local user account. To allow SSH access, the user must be in the local OpenSSH Users group, or alternatively, be a member of the local Administrators group, which also grants the necessary access.


💡 For domain-joined Windows servers with OpenSSH, you can log in using a domain user account. Make sure the user is in the OpenSSH Users group. Most people use a domain admin account, as it’s already part of the local Administrators group and has the required access.




💡 The first time you connect, PuTTY will prompt you to verify the server’s host key. Click Accept if you trust the connection.



Next, PuTTY will prompt you to enter the username and password for the server. Simply log in with the correct credentials. Once connected, you’ll be able to interact with the server directly through the PuTTY terminal window.




Conclusion

In this blog post, I showed how you can use a PowerShell script to install OpenSSH on Windows Server 2019, 2022, or 2025.

I hope the script comes in handy when setting up OpenSSH on any of your servers. If you have any questions or suggestions, feel free to reach out on X (@wmatthyssen) or leave a comment below.


Unknown's avatar

Wim is an Azure Technical Advisor and Trainer with over fifteen years of Microsoft technology experience. As a Microsoft Certified Trainer (MCT), his strength is assisting companies in the transformation of their businesses to the Cloud by implementing the latest features, services, and solutions. Currently, his main focus is on the Microsoft Hybrid Cloud Platform, and especially on Microsoft Azure and the Azure hybrid services.   Wim is also a Microsoft MVP in the Azure category and a founding board member of the MC2MC user group. As a passionate community member, he regularly writes blogs and speaks about his daily experiences with Azure and other Microsoft technologies.