NeuroDynamic.Tech
Sign inJoin

SSH keys, properly: never type a server password again

Your laptop will hold a small pair of files called an SSH key. Your server will trust it, so logging in never asks for a password — then we turn password logins off completely.

The founder · 12 min read ·

BASIC

Tested for real: 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 small pair of files called an SSH key. Your server will trust that key, so logging in never asks for a password. Then we turn password logins off completely, so the bots guessing passwords at your server are locked out for good.

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

BASIC. You have an Ubuntu server you can already log into with a password, and a laptop with a terminal. One path, no branching, every word of jargon defined.

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 — an optional password that protects the private key file itself, on your laptop.
  • 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, PowerShell on Windows 10/11 (its built-in OpenSSH is fine for this guide).
  • 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.

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, you already have a key of the right type. Skip to Step 3 and use it. If the folder does not exist at all, that is fine too — the next step creates it.

Check it worked: the command ran without listing id_ed25519. An error like No such file or directory also means "no key yet", which is fine.

Step 2 — generate your key pair

One command creates both halves of the key. When it asks where to save, press Enter to accept the offered path. When it asks for a passphrase, you may press Enter twice for none. Or type one if this laptop is shared or portable. A passphrase means typing it when the key is used, in exchange for the key file being useless if stolen.

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:XkWiTT9lsv13bvTeL5ahWmNv2jLoq55sBYM+yhEbyjM 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

ssh-copy-id logs in with your password one last time. It files the public key in the right place on the server, with the right permissions. Doing that by hand is where most people's first attempt goes wrong, so we let the tool do it.

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:f/WgqSmxfuUxkg9MZzeOxRVJSyL8td9cb5P3cjazElY.
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.

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

Step 4 — log in with the key

Now log in normally. If you set no passphrase, no prompt of any kind should appear.

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 password was asked. If you set a passphrase in Step 2, being asked for that is correct. Read the prompt: it says "Enter passphrase for key", not the server's name.

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

Step 5 — find out what actually controls password logins

Here is the first Ubuntu 24.04 trap. The obvious setting file, /etc/ssh/sshd_config, is not the whole story. A .d folder of drop-in files is read first, and on cloud-built servers one of them forces passwords on. Let's look, with sudo, because one of the files is readable by root only. Without sudo, grep reports "Permission denied" for exactly the file that matters. That cost me a confused minute during testing.

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. Your list may differ from mine — the fix in Step 6 works regardless.

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

You should see something like:


Silence is the pass mark here. Any output means a typo — 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 passing run includes:

active
active

Now restart:

sudo systemctl restart ssh

You should see something like:


No news is good news again. Your current connection survives a restart — SSH only 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 ground truth:

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

Trust, but verify. Keep your current server session open — it is your safety line. Then open a second terminal on your laptop, and ask the server for a password login on purpose:

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).

That refusal is the whole point of the guide. The server no longer offers passwords — note it never even asked for one. The brackets list what it will accept: keys only.

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.
  • You see Permission denied (publickey) from your own laptop after Step 7 → it means the server is keys-only and your key was not offered → from another terminal that is still logged in, remove /etc/ssh/sshd_config.d/00-lock-the-door.conf, restart ssh, and redo Step 3. This is why Step 8 says keep a session open.

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 key from the server. Open ~/.ssh/authorized_keys in an editor, or use the one-liner below. Every key is one long line ending in a short label; mine ended YOUR-NAME@YOUR-LAPTOP. Delete the line whose label matches your laptop:

sed -i '/YOUR-NAME@YOUR-LAPTOP/d' ~/.ssh/authorized_keys

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.

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.


Tried it? Improved it?

Tell the forum what worked and what didn’t: real experience beats recommendations, and the best answers get folded back into this guide with credit.

Related guides