Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

How to Create an SSH Key in Windows: OpenSSH Client and PowerShell

Sean

Platform Writer

Jul 06, 2026
6 min read

Windows 10 (1809+) and Windows 11 ship with an OpenSSH client that includes ssh-keygen. The right way to create a key on Windows is ssh-keygen -t ed25519 in PowerShell, then ssh-add to load it into the agent. The team that has this set up has a working SSH key on Windows without installing PuTTY or any third-party tool.

How to Create an SSH Key in Windows: OpenSSH Client and PowerShell

Table of contents

The Windows OpenSSH client

Microsoft added the OpenSSH client to Windows in 2018. It is available on Windows 10 1809 and later, Windows 11, and Windows Server 2019 and later. The right way to check if it is installed:

Get-WindowsCapability -Online | Where-Object {$_.Name -like 'OpenSSH.Client*'}

If the State is Installed, the client is ready. If it is NotPresent, install it:

Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

The OpenSSH client includes ssh, scp, sftp, ssh-keygen, ssh-agent, and ssh-add. The right answer for a developer who needs SSH on Windows is the built-in client. The wrong answer is to install PuTTY, which is a separate tool that requires its own key format (.ppk) and does not interoperate with the standard OpenSSH keys without a conversion step.

Creating the key

The right command in PowerShell to create an Ed25519 key is:

ssh-keygen -t ed25519 -C "alice@workstation"

The -C flag is a comment that identifies the key. The right comment is your email or a description of the workstation. The right answer is to use a comment that helps you identify the key when you see it in authorized_keys on the server.

The command will prompt for a file location (default is C:\Users\<you>\.ssh\id_ed25519) and a passphrase. The right answer is to set a passphrase. The passphrase is what protects the key if your laptop is stolen. Without a passphrase, anyone with the file can use the key.

The output:

Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\alice\.ssh\id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\alice\.ssh\id_ed25519
Your public key has been saved in C:\Users\alice\.ssh\id_ed25519.pub
The key fingerprint is:
SHA256:abc123... alice@workstation

The private key is id_ed25519. The public key is id_ed25519.pub. The right answer for copying the public key to a server is to read the .pub file and paste it into ~/.ssh/authorized_keys on the server. PowerShell can read the file:

Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub

The wrong answer is to copy the private key. The public key is the one that goes to the server. The private key never leaves your workstation.

Using ssh-agent so you do not retype the passphrase

The right answer for a key with a passphrase is to use ssh-agent so you do not have to retype the passphrase every time you connect. Windows OpenSSH includes a built-in ssh-agent service that you can enable:

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent

Then add the key to the agent:

ssh-add $env:USERPROFILE\.ssh\id_ed25519

You will be prompted for the passphrase once. After that, every SSH connection that uses this key will succeed without prompting. The right answer is to add the key to the agent on every reboot (the agent forgets the keys when it restarts). The wrong answer is to disable the passphrase and skip the agent — the right answer for security is to keep the passphrase and use the agent.

The right verification is ssh-add -l, which lists the keys currently loaded. The output is the fingerprint and comment of each key.

Adding the public key to a server

The right way to add the public key to a Linux server is the ssh-copy-id command, which does the work for you:

ssh-copy-id [email protected]

This prompts for the server password one last time, then appends your public key to ~/.ssh/authorized_keys on the server. The right answer is to use this command, not to manually copy and paste the public key. The right answer if ssh-copy-id is not available is to manually append:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "$(cat /path/to/public/key)" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

The mode is important. The wrong answer is to leave the directory or file world-readable, which causes sshd to refuse to use the key with a confusing permission error.

Connecting with the new key

The right command to connect:

ssh [email protected]

The first connection will prompt to verify the server’s host key fingerprint. The right answer is to verify the fingerprint through an out-of-band channel (your hosting provider’s console, a phone call to the admin, the cloud provider’s dashboard). The wrong answer is to blindly type yes and accept whatever fingerprint the server presents — that is a man-in-the-middle attack vector.

After accepting the host key, the agent provides the private key, the server verifies it against the public key in authorized_keys, and the connection completes. The right answer is to see something like:

Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-31-generic x86_64)
...
alice@server:~

The wrong answer is to see Permission denied (publickey) — that means the public key is not in authorized_keys on the server, the file mode is wrong, or the sshd config is wrong.

Using the config file for daily connections

The right way to manage multiple SSH connections on Windows is ~/.ssh/config. The file is the same format as on Linux. Example:

Host bastion
  HostName bastion.example.com
  User alice
  Port 22
  IdentityFile ~/.ssh/id_ed25519

Host prod
  HostName 10.0.0.5
  User deploy
  ProxyJump bastion
  IdentityFile ~/.ssh/id_ed25519

The right command is ssh prod, and the client resolves the hostname through the bastion. The ProxyJump directive is the modern equivalent of the old ProxyCommand. The right answer is to use ProxyJump because it is the standard in OpenSSH 7.3+.

The wrong answer is to use PuTTY-style saved sessions. The OpenSSH config file is the canonical way, and it works on Windows, macOS, and Linux the same way.

FAQ

Why is the Windows OpenSSH client slower than macOS/Linux?

It is not. The Windows OpenSSH client is the same code as the macOS and Linux versions, compiled for Windows. The slowness people report is usually due to Windows Defender scanning the SSH process, or to the agent being slow. The right answer is to exclude C:\Windows\System32\OpenSSH\ from Defender’s real-time scan if you have a lot of SSH traffic.

Can I use my existing PuTTY .ppk key?

Yes, but the wrong answer is to keep using PuTTY. The right answer is to convert the .ppk to the OpenSSH format using PuTTYgen (File → Load private key → Conversions → Export OpenSSH key), then save it to ~/.ssh/id_ed25519. After that, you can delete PuTTY entirely.

What if ssh-agent is not starting?

The right answer is to check the service state. Get-Service ssh-agent shows the status. If it is Stopped, Start-Service ssh-agent. If it fails to start, check the Windows event log (eventvwr.msc) for the OpenSSH logs. The common cause is that the service is disabled in the registry. The right answer for a permanent fix is Set-Service ssh-agent -StartupType Automatic.

How do I add a key to GitHub from Windows?

The right answer is to copy the public key and paste it into the GitHub SSH settings. PowerShell:

Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard

Then go to GitHub → Settings → SSH and GPG keys → New SSH key, paste, and save. The right answer is to use this approach rather than emailing the key or storing it in a password manager.

Can I use Windows Hello (fingerprint, face) to unlock the SSH key?

Yes, on Windows 10 1903+ with the OpenSSH client 8.1+. The right answer is to add the key to the Windows Hello-backed credential store. The implementation is complex enough that the typical user should use the passphrase + ssh-agent approach instead. The right answer for a developer who wants this is the ssh-keygen -O no-touch-required flag and the matching config in ~/.ssh/config.

What if my key is in the legacy RSA format?

The right answer for new keys is Ed25519. The right answer for an existing RSA key is to keep using it — RSA keys are still valid, just larger and slower than Ed25519. The wrong answer is to convert an RSA key to Ed25519 in place; the right answer is to generate a new Ed25519 key, deploy the public key, and remove the RSA key. The key is just a file; rotating keys is normal.

Why does my SSH connection work in PowerShell but not in VS Code?

VS Code uses its own SSH client by default and may not be reading ~/.ssh/config. The right answer is to set the remote.SSH.path setting in VS Code to the path of the OpenSSH ssh.exe. On Windows, that is usually C:\Windows\System32\OpenSSH\ssh.exe.

Is WSL2 better for SSH than native Windows?

For SSH usage, WSL2 is the same as native Windows — both use the OpenSSH client, both have an agent, both have the config file. The right answer for a developer who is comfortable in WSL2 is to use the WSL2 SSH client, because the key file can be shared with Linux servers and the workflow is identical. The wrong answer is to think WSL2 has a different SSH implementation — it is the same OpenSSH code.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#ssh#create#dev-infra#tutorial