We may earn a referral fee at no additional cost to you when you shop through the links on this page.
Password-only SSH is the easiest thing for brute-force scanners to target. This DevAnswers guide walks through replacing it with an SSH key pair generated by PuTTYgen on Windows, then hardening the server to refuse passwords. Tested on Ubuntu 22.04, 24.04, 26.04 and Debian 12, 13.
Prerequisites
- A Windows 10 or 11 PC with PuTTY 0.78 or newer installed (from chiark.greenend.org.uk/~sgtatham/putty/).
- A Linux server (VPS or dedicated) running Ubuntu 22.04 LTS, 24.04 LTS, 26.04 LTS, Debian 12 (Bookworm), or Debian 13 (Trixie).
- A sudo-enabled user account on the server with SSH access via password. If you don’t have one yet, walk through the Initial Server Setup guide for Ubuntu 26.04 (or the matching version for Debian 13 or Ubuntu 26.04) first.
- OpenSSH 6.5 or newer on the server. This is the default on every listed distro and is what makes Ed25519 keys work.
- Basic comfort with PuTTY Saved Sessions and editing a config file via
nanoorvimon Linux.
Download and Install PuTTY
Grab the official Windows installer from chiark.greenend.org.uk/~sgtatham/putty/. The MSI installer ships the full toolset: putty.exe (the SSH client), puttygen.exe (key generation), and pageant.exe (the SSH agent). Use the 0.78 release or newer. Earlier versions either lack Ed25519 support (pre-0.68) or default to the older PPK2 key format (pre-0.75), and the configuration UI moved the private-key field into a new sub-panel in 0.75, so screenshots and navigation steps in this guide assume current PuTTY.
If you have not connected to your server with PuTTY before, the basic password-based connection flow is covered in how to connect to a Linux server via SSH. Get that working first. If you already have a PuTTY Saved Session for the server, you’ll modify it later in the Configure section to point at your new key file; if you don’t have one yet, the Configure section creates one from scratch. If you don’t have a Linux server yet, you can spin up an unmanaged VPS in a few minutes on DigitalOcean; pick Ubuntu 24.04 LTS as the image and run through the linked Initial Server Setup guide before coming back here.
Generate an SSH Key Pair with PuTTYgen
A PuTTY-compatible key pair is two pieces of information: a private key that lives only on your Windows PC (in a .ppk file) and a public key that gets installed on the server. Generate them with PuTTYgen, which ships with the PuTTY installer.
- Launch PuTTYgen (Start menu, type “puttygen”).
- At the bottom of the window, set Key type to EdDSA, then leave the curve as Ed25519 (255 bits). Ed25519 has been the modern default since PuTTY added the algorithm and is what OpenSSH 6.5 and newer expect.
- Click Generate. Move the mouse pointer around in the empty area at the top of the window until the progress bar fills.
- Fill in Key comment with a memorable label like
billy@workstation. This is a local label that stays attached to the public key when you copy it intoauthorized_keys; it helps you identify which machine the key belongs to when reviewing the file later. - Set a strong Key passphrase and confirm it. Do not leave this blank.
- Click Save private key and store the
.ppkfile somewhere safe, likeC:\Users\you\Documents\ssh\. Do not save the public key with the Save button (it writes a PuTTY-specific format); instead, copy the entire text from the box at the top labeled “Public key for pasting into OpenSSH authorized_keys file” to your clipboard. You will paste this into the server in the next step.
For the passphrase, generate something long enough that a stolen laptop can’t crack it offline. A strong-passphrase generator set to 32 characters with symbols works well; paste the output into PuTTYgen’s Key passphrase field and save the passphrase itself in your password manager. You will need it whenever you load the key into Pageant.
You should now have a .ppk file on disk and the matching public key on your clipboard.
Install the Public Key on the Server
The public key needs to land in ~/.ssh/authorized_keys in the home directory of the user account you want to log in as on the server. The directory and file have strict permission requirements; sshd will silently refuse the key (and log a permission error) if they’re too open.
Open a normal password-based PuTTY session to the server. Once logged in, create the .ssh directory if it doesn’t exist, then append the public key text you copied:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "" >> ~/.ssh/authorized_keys
cat >> ~/.ssh/authorized_keys
The echo "" >> ~/.ssh/authorized_keys appends an empty line (and a newline) to the file. This is important if existing keys are present without a trailing newline; otherwise the pasted key would concatenate with the previous key line. Then cat >> reads from stdin and appends. Right-click in PuTTY to paste your clipboard (the public key text you copied), press Enter to make sure the key ends with a newline, then press Ctrl+D to finish input. The whole key must be a single line (it starts with ssh-ed25519 AAAA... and ends with the comment you set). Tighten the file permissions next:
chmod 600 ~/.ssh/authorized_keys
Per the sshd(8) man page, the authorized_keys file must be owned by the user and must not have write permissions for anyone else. Mode 600 (owner read-write, no group, no other) is the safe default. The parent ~/.ssh directory should be mode 700 for the same reason. If either is too open, sshd refuses the key entirely as a defensive measure.
Configure PuTTY to Use the Key
Back in Windows, open a new PuTTY session. The configuration UI shifted in PuTTY 0.75, and the private-key field now lives in a dedicated sub-panel under Auth:
- If you have an existing Saved Session for this server, select it in the list and click Load. Otherwise, leave the session list alone for now; you’ll fill in the host details at the end and save as a new session.
- In the left tree, expand Connection, then SSH, then Auth, then click Credentials.
- Click Browse… next to “Private key file for authentication” and select the
.ppkfile you saved earlier. - In the left tree, click back to Session.
- If you loaded an existing session, the Host Name is already populated; click Save to update it with the new key file path. If you’re creating from scratch, fill in Host Name with your server’s IP or hostname, type a Saved Sessions name, then click Save.
- Click Open to connect.
PuTTY should prompt for the key passphrase (the one you set in PuTTYgen), and then log you straight in with no password prompt. If you instead see a password prompt, scroll to the Troubleshooting section below.
Load Keys Automatically with Pageant
Typing the passphrase every connection gets old quickly. Pageant is PuTTY’s SSH agent: it holds your decrypted private key in memory and answers authentication challenges on PuTTY’s behalf for the rest of the Windows session.
- Launch Pageant. It runs as a system-tray icon (a computer monitor with a black hat).
- Right-click the tray icon and choose Add Key.
- Browse to your
.ppkfile and enter the passphrase when prompted.
Future PuTTY connections that reference this key skip the passphrase prompt and connect immediately. To make Pageant load your key automatically when you log into Windows, create a desktop or startup-folder shortcut pointing at pageant.exe with your key file as an argument:
"C:\Program Files\PuTTY\pageant.exe" "C:\Users\you\Documents\ssh\server.ppk"
The passphrase prompt still appears once when Pageant starts; this only avoids the prompt for individual PuTTY connections during the same session. To protect your configuration, you can back up PuTTY sessions by exporting the relevant registry keys.
Harden SSH Access (Optional but Recommended)
Once key-based login is working, you can disable password authentication entirely. This stops brute-force scanners from even trying. Edit the SSH daemon config:
Modern Ubuntu and Debian’s sshd_config reads drop-in files from /etc/ssh/sshd_config.d/ at the top of the main config. Ubuntu’s default 50-cloud-init.conf drop-in keeps password authentication enabled. Because sshd uses the first value it finds for each directive, edits made to the main sshd_config further down can be silently overridden by a drop-in. The safe path is to create your own drop-in that loads before the cloud-init defaults:
sudo nano /etc/ssh/sshd_config.d/10-ssh-key-only.conf
Add these four directives in the new file. The numeric prefix 10- ensures this file is read before Ubuntu’s 50-cloud-init.conf, so its values win:
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
KbdInteractiveAuthentication no is essential alongside PasswordAuthentication no: without it, PAM-based password prompts can still let someone in via the keyboard-interactive auth method, undoing the hardening.
Save the file, then validate syntax and reload SSH in one chained command. The && is critical: it stops the reload from running if sshd -t finds a syntax error, which would otherwise leave SSH refusing to start:
sudo sshd -t && sudo systemctl reload ssh
systemctl reload ssh is safer than restart: it re-reads the config without dropping existing SSH connections. On Debian and Ubuntu the unit is ssh.service; sshd.service is sometimes provided as an alias depending on the openssh-server version, but ssh works on both. sshd -t is silent on success and prints the offending line on failure.
With those four directives in place, anyone trying to log in with just a password gets refused, and keyboard-interactive prompts are also disabled. PermitRootLogin prohibit-password still lets root in via a key (useful for automation) but refuses root password attempts. If you want to block direct root login entirely, change that line to PermitRootLogin no and connect as your sudo user.
Troubleshooting Common Errors
The four errors below cover almost every key-auth problem readers actually hit. Click each to expand.
“Server refused our key” (wrong permissions on the server)
The most common cause: ~/.ssh or authorized_keys is owned by the wrong user (root instead of the account you log in as) or has loose permissions. Check on the server:
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
Expected: drwx------ on the directory and -rw------- on the file, both owned by your user (not root). Fix:
sudo chown -R $USER:$USER ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
“PuTTY Fatal Error: Unable to load key file” (PPK3 vs PPK2 format mismatch)
PuTTYgen 0.75 and newer write the PPK3 format by default. Older PuTTY clients, or tools that consume PPK files (some CI agents, build tools), only read PPK2. If you need to support an older consumer, open the .ppk in PuTTYgen and re-save as PPK2:
- Launch PuTTYgen, click Load, select the existing
.ppk. - Enter the passphrase when prompted.
- From the menu bar pick Key > Parameters for saving key files, set PPK file version to 2.
- Click Save private key and overwrite (or save alongside) the original.
“Disconnected: No supported authentication methods available” (server config refuses keys)
This error means the server has no authentication method it can offer you. Two situations produce it: (a) you’re trying to authenticate with a key but the server rejected the key auth method (commonly PubkeyAuthentication no in a drop-in under /etc/ssh/sshd_config.d/, or the server is running OpenSSH older than 6.5 and can’t accept Ed25519); (b) you’ve already disabled PasswordAuthentication + KbdInteractiveAuthentication per the Harden section and you’re connecting WITHOUT a key file. In this case the error is working as designed; load your key and try again. To diagnose (a), check the SSH server version:
dpkg -l openssh-server 2>/dev/null | grep '^ii' | awk '{print $2, $3}'
If the server reports OpenSSH older than 6.5 (very rare on modern distros, but possible on old VPS images), generate an RSA-4096 key in PuTTYgen instead (Key type: RSA, Key size: 4096) and install that. Otherwise, check ALL sshd config sources (main /etc/ssh/sshd_config AND every /etc/ssh/sshd_config.d/*.conf drop-in) for any PubkeyAuthentication no override. Per the Harden section, drop-ins loaded earlier (lower numeric prefix) win, so set PubkeyAuthentication yes in your own drop-in like /etc/ssh/sshd_config.d/10-ssh-key-only.conf. After editing, validate + reload with the same chained command: sudo sshd -t && sudo systemctl reload ssh.
Copy-paste line breaks corrupting the public key
The public key must be a single line in authorized_keys (starting with ssh-ed25519 and ending with your comment). Copying from PuTTYgen’s text box through Notepad can sometimes insert a line break in the middle of the long base64 string. The symptom is “Server refused our key” even though permissions look correct. Open authorized_keys with nano -w (no word wrap) and confirm the key is one unbroken line.
On Ubuntu and Debian, AppArmor is the default mandatory-access-control system and rarely produces this symptom on standard installs. If your server is actually a RHEL-family system (out of this guide’s primary scope) with SELinux enforcing, wrong SELinux context on ~/.ssh can produce the same “Server refused our key” symptom even with correct file permissions. Restore the default context with sudo restorecon -R ~/.ssh.
For connection-level errors (PuTTY can’t reach the server at all, connection drops, “Network error” dialogs), see the PuTTY network error troubleshooting guide.
Verify Your Key-Based Login
Confirm the setup end-to-end before closing your existing session. Open a brand-new PuTTY window (do not close the one you’re currently logged in through), load the saved session you created or updated above, and click Open. Depending on whether Pageant has your key loaded, you’ll see either a passphrase prompt followed by a shell prompt, or a shell prompt immediately. Tick each item below to confirm key-based authentication is working:
- A new PuTTY window connects to the server.
- No server password prompt appears (passphrase prompt is OK if Pageant isn’t running).
- You land at a shell prompt as your sudo user.
- If you also applied the Harden section, a connection from a different machine without your key file is refused with “No supported authentication methods available”. That’s the result you want; password attacks have nothing to land on.
You can now close the original session; the new one is your working setup.
Shoot, I should also note that I followed your reply with the line of code above with a sudo user who is not root.
When I log in it say “Server refused our key”
OK, so I have been scratching my head with this one for a while because I also got that error when going through the guide again.
It turns out the problem is that the ownership of both
/.sshand/.ssh/authorized_keyswas set toroot. You must make sure that the user owns these and not root.This command will recursively set the ownership of the directory. The
$(whoami)variable returns the currently logged in user.sudo chown -R $(whoami):$(whoami) ~/.ssh/More info: https://superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder
Hi, I’ve been stuck on this for awhile now.
Following these steps, I was getting the error of ‘Connection refused’. So, I found elsewhere to created a bridge connection with Ethernet & Wi-fi. Then, using that IP, I was able to get the ‘Using username: ‘ message, along with ‘Server refused our key’, and then asked for a password. The one I created with the original IP didn’t work, I get the message ‘Access denied’.
I’m also UNABLE to connect in this tutorial: https://devanswers.net/log-linux-windows-using-putty/ using the bridge connection IP – I get ‘Access denied’.
Please help!