Independent tools and practical guides. · Free app downloads with an account.
NeuroDynamic.TechAccount

Set up SSH key login on Ubuntu

Getting started

Tested setup: I ran every command in this guide top-to-bottom on a fresh Ubuntu 24.04 virtual machine (4 CPUs, 8 GB RAM) on 13 August 2026. Versions at test time: Ubuntu 24.04.4 LTS, OpenSSH 9.6p1 (Ubuntu 3ubuntu13.18), OpenSSL 3.0.13.

Found a problem? Tell me via the contact page.

Placeholders: anything in CAPS-WITH-DASHES, like YOUR-SERVER-IP, is a placeholder for your own value. Replace it before running the command.

What you'll end up with

Your laptop will hold a pair of files called an SSH key. Your server will trust the private half without ever receiving it. Once that works, we turn server-password login off, so a guessed password is no longer enough to get in.

There are two separate jobs here: make key login work, then disable password login. We test between them. That order matters because doing both at once is how people lock themselves out.

The finished state looks like this. A password login attempt gets refused, and your key login still works:

$ ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password tester@YOUR-SERVER-IP
tester@YOUR-SERVER-IP: Permission denied (publickey).

$ ssh tester@YOUR-SERVER-IP 'echo key still works'
key still works

Who this is for

Getting started. You have an Ubuntu server you can already reach with a password and a laptop with a terminal. The main path is macOS, Linux or Windows Subsystem for Linux. Windows PowerShell gets one clearly marked alternative in Step 3.

Time and cost

The commands took me 9 minutes on the test machine, measured. Allow 20 minutes for a careful first run. Cost: nothing.

Words you'll meet

  • SSH — Secure Shell, the standard way to get a command line on a remote machine. More on the back-to-basics page.
  • Key pair — two matching files. The public key goes on the server; anyone may see it. The private key stays on your laptop and is the actual secret.
  • Passphrase — a password that protects the private key file itself. It is separate from your server password.
  • Fingerprint — a short code that identifies a key, so you can compare keys without reading the whole thing.
  • sudo — "do this as the administrator". Ubuntu asks for your password when you use it.
  • Drop-in file — a small extra config file in a .d folder that adjusts a main config file without editing it.

Before you start

  • An Ubuntu server (any recent version; I tested 24.04) you can log into with a username and password.
  • Your server's address. Everywhere below, replace YOUR-SERVER-IP with it, and YOUR-SERVER-USER with your username on the server.
  • A terminal on your laptop or desktop: Terminal on macOS or Linux, Windows Subsystem for Linux, or PowerShell on Windows 10/11.
  • If you rent the server from a cloud company, know where their web console is. It is the spare door if a mistake locks you out. We should not need it.

Do not close your working server session until Step 8 passes. It is your way back in if the new key does not work.

The steps

Step 1 — check whether your laptop already has a key

This caught me during testing. If a key already exists, the next step offers to overwrite it, and answering carelessly could destroy a key you rely on. So we look first.

Run this on your laptop:

ls ~/.ssh

Your output will vary, but look for:

known_hosts

If you see id_ed25519 and id_ed25519.pub, a key already exists at the standard location. Do not overwrite it. If it is your key, skip to Step 3 and use it. If you do not know what created it, stop and find out before changing anything.

Check it worked: you now know whether the standard key files exist. An error like No such file or directory means "no SSH folder yet", which is fine.

Step 2 — generate your key pair

One command creates both halves of the key. When it asks where to save them, press Enter to accept the offered path.

I recommend setting a passphrase, especially on a laptop. It protects the private key if the device or file is stolen. Your operating system can remember it for the session, so it does not have to become a new prompt every minute.

ssh-keygen -t ed25519

You should see something like:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/YOUR-NAME/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/YOUR-NAME/.ssh/id_ed25519
Your public key has been saved in /home/YOUR-NAME/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:[YOUR-NEW-KEY-FINGERPRINT] YOUR-NAME@YOUR-LAPTOP
The key's randomart image is:
+--[ED25519 256]--+
|          o o o  |
[...snipped...]
+----[SHA256]-----+

Your fingerprint will differ — it is unique to your new key. The strange picture is the same fingerprint drawn as art; you can ignore it.

Check it worked:

ls ~/.ssh

A passing run includes:

id_ed25519
id_ed25519.pub
known_hosts

The two id_ed25519 files are the pair. The .pub one is the shareable half.

Step 3 — copy the public key to the server

On macOS, Linux or Windows Subsystem for Linux, ssh-copy-id logs in with your password one last time. It puts the public key in the right place with the right permissions.

ssh-copy-id YOUR-SERVER-USER@YOUR-SERVER-IP

You should see something like:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/YOUR-NAME/.ssh/id_ed25519.pub"
The authenticity of host 'YOUR-SERVER-IP (YOUR-SERVER-IP)' can't be established.
ED25519 key fingerprint is SHA256:[YOUR-SERVER-FINGERPRINT].
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
YOUR-SERVER-USER@YOUR-SERVER-IP's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'YOUR-SERVER-USER@YOUR-SERVER-IP'"
and check to make sure that only the key(s) you wanted were added.

The authenticity question appears the first time any machine meets a new server; type yes. The fingerprint it shows belongs to the server, not to your new key.

Using Windows PowerShell without Windows Subsystem for Linux? Windows includes ssh, but normally not ssh-copy-id. Use this instead:

Get-Content $HOME\.ssh\id_ed25519.pub | ssh YOUR-SERVER-USER@YOUR-SERVER-IP "umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys"

It sends only the public .pub file. You should be asked for the server password once, then returned to the PowerShell prompt.

Check it worked: the line Number of key(s) added: 1 appeared.

Step 4 — log in with the key

Now log in normally. You may be asked for the key passphrase. You should not be asked for the server account password.

ssh YOUR-SERVER-USER@YOUR-SERVER-IP

Your output will vary, but look for:

Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-136-generic x86_64)
[...snipped...]
tester@ubuntu-testbed:~$

Check it worked: you are at the server's prompt and no server account password was asked. A prompt that says Enter passphrase for key is correct.

Stay logged in. Steps 5 to 7 all happen on the server.

Step 5 — find out what actually controls password logins

Ubuntu 24.04 cloud images may add SSH settings in drop-in files. Check those as well as /etc/ssh/sshd_config: an earlier setting can take precedence over the line you expected to control password login.

Run this on the server:

sudo grep -r 'PasswordAuthentication' /etc/ssh/sshd_config.d/

Your output will vary, but look for:

/etc/ssh/sshd_config.d/50-cloud-init.conf:PasswordAuthentication yes
/etc/ssh/sshd_config.d/60-cloudimg-settings.conf:PasswordAuthentication no

Two files disagree. SSH resolves arguments in an unusual way: the first value it reads wins. This is different from many config files. Files are read in name order, so 50-cloud-init.conf beats 60-cloudimg-settings.conf, and passwords stay on. Editing the main config file below them would change nothing, which is why so many people "turn off" passwords and find them still working.

Check it worked: you can see which files mention PasswordAuthentication. No output is also possible on a server without a cloud-image override; continue to Step 6.

Step 6 — add a drop-in that wins

Since first-read wins, we add our own drop-in with a name starting 00, so it sorts before everything else. It turns off passwords and the related "keyboard-interactive" method. We do not edit or delete the cloud files — they may be rewritten by the system later, and our 00 file will still outrank them.

printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-lock-the-door.conf

You should see something like:

PasswordAuthentication no
KbdInteractiveAuthentication no

(tee echoes what it wrote — that is your confirmation, not an error.)

Now ask the SSH server to proof-read its own config before we apply anything:

sudo sshd -t

Expected result: no output. Silence is the expected result here. Any message means a typo, so stop and fix it before continuing.

Check it worked: sudo sshd -t printed nothing.

Step 7 — restart SSH the Ubuntu 24.04 way

Second trap. On Ubuntu 24.04 the SSH service is "socket-activated": a listener called ssh.socket owns the port and wakes the real service per connection. Old guides say to restart sshd; on 24.04 the unit to restart is ssh. And if you ever change the port, the socket, not the config file, has the final say. We are not changing ports today, so one restart of ssh is enough.

First see the setup for yourself:

systemctl is-active ssh.socket ssh.service

A socket-activated Ubuntu 24.04 server normally shows:

active
active

If ssh.socket says inactive but your current SSH connection works, your server is using the traditional always-running service. The next command is still the right one.

Now restart:

sudo systemctl restart ssh

Expected result: no output. Your current connection survives a restart because SSH applies the new rules to new connections.

Now confirm the running server really has passwords off. sshd -T prints the effective settings after all files are merged, so it is the recorded result:

sudo sshd -T | grep -i '^passwordauthentication'

The important line is:

passwordauthentication no

Check it worked: the line says passwordauthentication no.

Step 8 — prove it from the outside

Keep your current server session open while testing. In a second terminal on your laptop, deliberately request password login:

ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password YOUR-SERVER-USER@YOUR-SERVER-IP

The important line is:

YOUR-SERVER-USER@YOUR-SERVER-IP: Permission denied (publickey).

The refusal shows that the server did not offer password login for this test. The methods in brackets show what it accepts.

Check it worked: you got Permission denied (publickey), and a plain ssh YOUR-SERVER-USER@YOUR-SERVER-IP in the same terminal still logs you in.

Something went wrong?

  • You see Permission denied when running the grep in Step 5 → it means you forgot sudo; 50-cloud-init.conf is readable by root only → add sudo and run it again.
  • You set PasswordAuthentication no somewhere but passwords still work → it means a drop-in file earlier in name order says yes, and first-read wins → do Steps 5–7 exactly; the 00- file wins by sorting first, then restart ssh.
  • You see the Overwrite (y/n)? question in Step 2 → it means a key already exists at that path → answer n, then go back to Step 1: you probably already have a usable key.
  • PowerShell says ssh-copy-id is not recognised → that tool is not included with Windows OpenSSH → use the PowerShell command directly below the main Step 3 command.
  • You see Permission denied (publickey) from your own laptop after Step 7 → the server is keys-only and your key was not offered → use the original session you kept open, undo the Step 6 file, restart ssh, and redo Step 3.

Undo all of this

Tested, in this order. On the server:

sudo rm /etc/ssh/sshd_config.d/00-lock-the-door.conf
sudo systemctl restart ssh
sudo sshd -T | grep -i '^passwordauthentication'

The important line is:

passwordauthentication yes

Then remove your public key from the server. Every key in authorized_keys occupies one long line, normally ending with a label such as YOUR-NAME@YOUR-LAPTOP.

nano ~/.ssh/authorized_keys

Delete only your key's line. In nano, save with Ctrl+O, press Enter, then leave with Ctrl+X.

Finally, on your laptop, delete the pair:

Only do this if you created the key for this guide. If Step 1 found an existing key and you reused it, skip this — deleting it would lock you out of every server that trusts it. Check first: a key you made today shows today's date with ls -l ~/.ssh/id_ed25519.

rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub

When I tested this undo, password login worked again and the deleted key was refused with Permission denied (publickey,password). The server was back to offering both, trusting neither of mine.

Final thoughts

The private key never left your laptop. The server received only the public half, and a password guess is no longer a valid way in.

Keep the private key backed up somewhere encrypted. Do not email it, paste it into a ticket, or copy it onto the server. If you lose the only copy, the server cannot reconstruct it for you.

Where to go next


Last tested: 13 August 2026 on Ubuntu 24.04.4 LTS. Versions: OpenSSH 9.6p1-3ubuntu13.18, OpenSSL 3.0.13.

Display settings

Changes apply immediately and stay in this browser.

Colour theme