SSH Key Authentication & Disabling Password Login
Date: March 9, 2026 Environment: Windows 11 laptop → Proxmox lab → Ubuntu Server VM Status: Complete
Objective
Set up Ed25519 SSH key authentication from a Windows 11 client to an Ubuntu Server VM, then disable password login entirely and verify the lockdown. The goal is to replace password-based SSH with key-based auth as a baseline security practice for the lab.
Prerequisites and Safety
Before touching sshd_config, I kept the Proxmox console open as a fallback. If SSH broke and locked me out, the console gives direct VM access without needing the network. This turned out to be the right call.
Verifying OpenSSH on Windows
Confirmed OpenSSH client was installed on the Windows 11 machine. The first attempt failed because I copied the prompt prefix PS > into the command, and I was running an elevated session unnecessarily. I restarted in a normal session, removed the prefix, and ran the command correctly:
Get-WindowsCapability -Online -Name OpenSSH.Client*
Name : OpenSSH.Client~~~~0.0.1.0
State : Installed
Generating the Ed25519 Key Pair
I used Ed25519 because it is a modern elliptic curve algorithm and produces shorter keys with stronger security than RSA. The -C flag adds a comment to identify the key later.
The first attempt was run in that elevated session before I restarted. Elevated PowerShell opens in C:\WINDOWS\system32, and I did not change directory before running ssh-keygen, so the keys were written there instead of ~\.ssh. I also gave them a custom name (secure and secure.pub) instead of accepting the default.
My first instinct was to move them:
Move-Item -Path C:\WINDOWS\system32\secure -Destination C:\Users\user\.ssh\
Move-Item -Path C:\WINDOWS\system32\secure.pub -Destination C:\Users\user\.ssh\
After moving them I decided the custom name would cause confusion later, so I deleted them and started over rather than carry forward a mistake:
Remove-Item -Path C:\Users\user\.ssh\secure
Remove-Item -Path C:\Users\user\.ssh\secure.pub
Second attempt: navigated to the correct directory first, accepted the default filename.
cd C:\Users\user\.ssh\
ssh-keygen -t ed25519 -C "win11-laptop"
Your identification has been saved in C:\Users\user/.ssh/id_ed25519
Your public key has been saved in C:\Users\user/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:Tt1tcUtOf2PKMqykrb4SZqXafe6iRtSpD2askSj26Wc win11-laptop
Used a strong passphrase. Confirmed both files exist in the right place:
ls $env:USERPROFILE\.ssh\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/9/2026 7:38 AM 444 id_ed25519
-a---- 3/9/2026 7:38 AM 95 id_ed25519.pub
-a---- 3/5/2026 11:43 PM 1777 known_hosts
-a---- 3/5/2026 11:43 PM 1033 known_hosts.old
Deploying the Public Key to the Server
Windows does not have ssh-copy-id natively, so I used PowerShell to read the public key and write it to the server in one command:
$pubkey = Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub
$cmd = "mkdir -p ~/.ssh && echo '$pubkey' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh"
ssh joel@192.168.86.32 $cmd
This creates the .ssh directory if it does not exist, appends the public key to authorized_keys, and sets the required permissions. SSH requires authorized_keys to be 600 (owner read/write only) and the .ssh directory to be 700 (owner full access). The server will refuse the key if the permissions are too open.
Authenticated with password for this step since key auth was not yet configured.
There is also a fully manual method on the server side (copy-paste into authorized_keys directly), which I plan to practice separately. It is useful when the scripted method is not available.
Testing Key Login
ssh joel@192.168.86.32
Enter passphrase for key 'C:\Users\user/.ssh/id_ed25519':
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-101-generic x86_64)
Key-based login worked.
Disabling Password Authentication
Opened sshd_config with elevated permissions on the server:
sudo nano /etc/ssh/sshd_config
Added to the bottom of the file:
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
Validated the config before restarting:
sudo sshd -t
No output means no syntax errors. Restarted the service:
sudo systemctl restart ssh
Confirmed it came back up:
sudo systemctl status ssh
Active: active (running) since Mon 2026-03-09 13:15:35 UTC; 2min 17s ago
...
Mar 09 13:16:55 ubuntu-server sshd[11703]: Accepted publickey for joel from 192.168.86.34 port 64510 ssh2: ED25519 SHA2>
Problem: Password Login Still Worked After Disabling It
What happened
After editing sshd_config and restarting SSH, I tested that password login was blocked:
ssh -o PubkeyAuthentication=no joel@192.168.86.32
The server prompted for a password and let me in. The change did not take effect.
What was tried
Checked that the setting was present in sshd_config:
grep -i passwordauthentication /etc/ssh/sshd_config
#PasswordAuthentication yes
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication, then enable this but set PasswordAuthentication
PasswordAuthentication no
The directive was there and correct. The main config file was not the problem.
What actually fixed it
Ubuntu can load additional config files from /etc/ssh/sshd_config.d/. I checked that directory:
ls /etc/ssh/sshd_config.d/
Found 50-cloud-init.conf. Contents:
sudo cat /etc/ssh/sshd_config.d/50-cloud-init.conf
PasswordAuthentication yes
This file was overriding the main config. The .d directory is a drop-in pattern where files are loaded alongside the main configuration. The last value wins, and since 50-cloud-init.conf was being loaded after the main file, its yes was taking effect.
I edited the file rather than deleting it. The cloud-init name suggests the file is managed by cloud-init, which configures the VM on first boot. Deleting it risked having it recreated on reboot with the old value.
sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf
Changed PasswordAuthentication yes to PasswordAuthentication no, saved, restarted SSH, and tested again:
ssh -o PubkeyAuthentication=no joel@192.168.86.32
joel@192.168.86.32: Permission denied (publickey).
Password login was rejected.
Verifying the Failed Login in Auth Logs
sudo journalctl -u ssh --since '5 minutes ago' | grep -i 'auth'
Mar 09 13:39:12 ubuntu-server sshd[12047]: Connection reset by authenticating user joel 192.168.86.34 port 61758 [preauth]
The failed attempt is visible in the logs.
Configuration Reference
| Setting | Value | Reason |
|---|---|---|
PasswordAuthentication |
no |
Disable password login |
KbdInteractiveAuthentication |
no |
Disable PAM keyboard-interactive (covers secondary password prompts) |
PubkeyAuthentication |
yes |
Explicitly allow key-based auth |
PermitRootLogin |
no |
Prevent direct root login over SSH |
Quick Reference Commands
| Task | Command |
|---|---|
| Generate Ed25519 key pair | ssh-keygen -t ed25519 -C "label" |
| Deploy public key (Windows) | See PowerShell one-liner above |
| Validate sshd config | sudo sshd -t |
| Restart SSH service | sudo systemctl restart ssh |
| Check SSH status | sudo systemctl status ssh |
| Check drop-in configs | ls /etc/ssh/sshd_config.d/ |
| View recent auth log | sudo journalctl -u ssh --since '5 minutes ago' |
| Test with password only | ssh -o PubkeyAuthentication=no user@host |
Result
The Ubuntu Server VM now requires key-based authentication. Password login is rejected. I can SSH in from the Windows 11 client using the Ed25519 key and passphrase. The main thing learned beyond the basic process was that Ubuntu cloud images ship with a drop-in config in sshd_config.d/ that overrides the main file. That directory is worth checking any time an SSH config change does not seem to take effect.
Next: Configure and Test UFW Firewall Rules on Ubuntu Server