Setting up SSH keys to work in Windows
I've typically connected to my servers via a WSL container in Windows. I wanted a cleaner way of getting to my machines without having to first install WSL and a Linux distribution. Here are the steps I took to set it up.
To connect from Windows to Linux or other SSH servers using keys instead of passwords, configure the built‑in OpenSSH client plus (optionally) the SSH agent. This guide walks through generating/using a key, configuring the Windows client, and troubleshooting common issues.
1. Enable OpenSSH client on Windows
On Windows 10/11, the OpenSSH client is usually installed, but you can verify it:
- Open Settings → Apps → Optional features.
- Look for OpenSSH Client under “Installed features”. If it is missing, click Add a feature, search for OpenSSH Client, and install it.
After installation, ssh, ssh-keygen, and ssh-add are available in PowerShell, Command Prompt, and Windows Terminal.
You can confirm with:
ssh -vYou should see an output similar to:
OpenSSH_for_Windows_9.xpY, LibreSSL 3.x.y2. Create or import your SSH key
All SSH keys live in a .ssh directory in your user profile:
C:\Users\<YourUser>\.ssh\
If the directory does not exist, create it.
Option A: Generate a new key
From PowerShell or Windows Terminal:
ssh-keygen -t ed25519 -C "[email protected]"- When prompted for the file, press Enter to accept the default
C:\Users\<YourUser>\.ssh\id_ed25519- Enter a passphrase for better security (recommended), or leave it empty if you understand the trade‑offs.
This creates:
id_ed25519– private key (keep this secret)id_ed25519.pub– public key (this goes to the server)
Option B: Import an existing key
If you already have a private key file (for example from a Linux or macOS machine):
- Copy the private key into
C:\Users\<YourUser>\.ssh\. - Make sure the file looks like an SSH private key, for example:text--—BEGIN OPENSSH PRIVATE KEY-----
...
--—END OPENSSH PRIVATE KEY----- - Give it a simple name, e.g.
personal.txtorid_rsa.
If your key is in PuTTY’s .ppk format, you must convert it to OpenSSH format with PuTTYgen (Conversions → Export OpenSSH key).
3. Install your public key on the server
On the Linux/Unix server, log in using whatever method you currently use (password or console) and add your public key to authorized_keys:
- On Windows, display the public key:powershell
type $env:USERPROFILE\.ssh\id_ed25519.pub - On the server, create the
.sshdirectory (if needed) and append the key:bashmkdir-p ~/.sshchmod 700~/.sshecho 'ssh-ed25519 AAAA... your-comment' >>~/.ssh/authorized_keyschmod 600~/.ssh/authorized_keys - Repeat per account or server as required.
From this point, the server will accept that key for logins to that user account.
4. Configure the SSH client on Windows
The per‑user SSH config file lives at:
text
C:\Users\<YourUser>\.ssh\config
If it does not exist, create it as a plain text file named config with no extension.
Here is a sample configuration for a host:
textHost checkpoint-bastion.coburgcrescent.lan
HostName checkpoint-bastion.coburgcrescent.lan
User kelvin
IdentityFile ~/.ssh/personal.txt
IdentitiesOnly yes
Explanation:
Host– shortcut name you will use with thesshcommand.HostName– DNS name or IP of the server.User– remote username.IdentityFile– path to the private key for this host. On Windows,~expands toC:\Users\<YourUser>. Using~avoids issues with spaces inC:\Users\First Last\....IdentitiesOnly yes– instructs SSH to use only the keys explicitly listed withIdentityFilefor this host instead of trying every default key.
You can add multiple host blocks:
Host bastion
HostName checkpoint-bastion.coburgcrescent.lan
User kelvin
IdentityFile ~/.ssh/personal.txt
IdentitiesOnly yes
Host db
HostName 10.10.1.20
User postgres
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Now you can connect simply with:
ssh bastion
5. Use the SSH agent (optional, for convenience)
The SSH agent stores decrypted keys in memory so you do not have to type your passphrase every time.
Start and enable the agent service
Run PowerShell as Administrator and execute:
Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service
This starts the agent and ensures it starts at boot.
Add your key to the agent
In a non‑admin PowerShell or Windows Terminal window:
ssh-add $env:USERPROFILE\.ssh\personal.txt
You will be prompted for the key’s passphrase once. After that, the agent holds the key.
Verify that the agent has the key:
ssh-add -l
You should see a line showing the fingerprint and comment (e.g. personal.txt ([email protected])).
With the agent running, plain ssh bastion will use your loaded key without requiring the path or passphrase again (until you log out or reboot, depending on your setup).
6. Troubleshooting common issues
“Permission denied (publickey)”
If you see:
Permission denied (publickey).
check the following:
- Config file is being read
Run:powershellssh -v bastion
In the output, you should see:textdebug1: Reading configuration data C:\\Users\\<YourUser>/.ssh/config
debug1: C:\\Users\\<YourUser>/.ssh/config line X: Applying options for bastion
If you do not see this, the config file is in the wrong place or named incorrectly. - IdentityFile is actually used
In verbose output you should see something like:textdebug1: identity file C:\\Users\\<YourUser>/.ssh/personal.txt type 0
debug1: Offering public key: C:\\Users\\<YourUser>/.ssh/personal.txt
If you only see attempts forid_rsa,id_ed25519, etc., and not your custom file, double‑check:- Spelling:
IdentityFile(notIdentifyFile). - Path: use
~/.ssh/filenameto avoid quoting and spaces. - The host block matches exactly the host you use on the command line.
- Spelling:
- Agent has no identities
If verbose output shows:get_agent_identities: agent contains no identities
then either:Fix by:ssh-add ~/.ssh/personal.txt
ssh-add -l- The agent is not running, or
- You have not run
ssh-addin this session.
- Server authorized_keysIf the client clearly offers the key but the server still denies access:
- Confirm
~/.ssh/authorized_keyson the server contains the correct public key (not the private key). - Check file permissions:bash
chmod 700~/.sshchmod 600~/.ssh/authorized_keys - Check server logs (
journalctl -u sshor/var/log/auth.log) to see why the key was rejected.
- Confirm
“Error loading key …: invalid format”
This error when running ssh-add means the file is not recognized as a private key. Typical causes:
- The file contains a password or random text.
- You used a
.pubfile (public key) instead of the private key. - The file is PuTTY
.ppkformat and needs conversion to OpenSSH.
Fix by:
- Ensuring you pass the private key (e.g.
personal.txtorid_ed25519) tossh-add. - Converting
.ppkwith PuTTYgen (Conversions → Export OpenSSH key).
7. Minimal working example
Given a private key stored as C:\Users\Kelvin Kang\.ssh\personal.txt and a Linux server at checkpoint-bastion.coburgcrescent.lan with your public key in ~kelvin/.ssh/authorized_keys, this minimal setup should work:
C:\Users\Kelvin Kang\.ssh\config
Host checkpoint-bastion.coburgcrescent.lan
HostName checkpoint-bastion.coburgcrescent.lan
User kelvin
IdentityFile ~/.ssh/personal.txt
IdentitiesOnly yes
Connection command
ssh checkpoint-bastion.coburgcrescent.lan
If you prefer using the agent:
ssh-add $env:USERPROFILE\.ssh\personal.lan
ssh checkpoint-bastion.coburgcrescent.lan
With this setup, Windows uses your SSH keys reliably to connect to your servers with minimal friction.