Set Up SSH Key Authentication and Disable Passwords
Generate a modern SSH key pair, install it on a remote host, and lock password login out entirely.
Password SSH is the slow leak in a lot of Linux servers. Brute-force bots hammer port 22 around the clock, and a weak password on any account is the whole thing. Key-based authentication fixes that, and the setup takes about five minutes.
This tutorial assumes you already have SSH access to the remote host via password. By the end, you will be logging in with a key and the password door will be shut.
Step 1 — Generate a key pair on your local machine
Use Ed25519. It is shorter, faster, and as secure as RSA at 4096 bits.
ssh-keygen -t ed25519 -C "you@your-laptop"
The -C comment is a label — it shows up in ~/.ssh/authorized_keys on the server and makes it easier to spot which key is which later.
Accept the default location (~/.ssh/id_ed25519) unless you are juggling multiple keys for different environments. Set a passphrase. If you skip the passphrase, anyone who walks off with your laptop gets every server you can reach.
You now have two files:
~/.ssh/id_ed25519— the private key. Never leaves this machine.~/.ssh/id_ed25519.pub— the public key. Safe to share.
Step 2 — Copy the public key to the server
The easy way:
ssh-copy-id user@server.example.com
This appends your public key to ~/.ssh/authorized_keys on the remote host, creating the file and .ssh directory if needed, with the correct permissions.
If ssh-copy-id is not available (rare but happens on minimal images), do it by hand:
cat ~/.ssh/id_ed25519.pub | ssh user@server.example.com \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
The permissions matter. If ~/.ssh is group-writable or authorized_keys is world-readable, sshd will ignore the file and silently fall back to password auth. This is the single most common reason for "my key doesn't work."
Step 3 — Confirm key login works before you lock anything down
Open a new terminal and connect:
ssh user@server.example.com
You should be prompted for the key's passphrase, not the account password. If you are asked for the account password, stop and figure out why before going any further — it is much easier to fix with a working session still open.
To see what sshd is actually doing on the server side, keep your existing password session open and tail the log in another window:
sudo journalctl -u ssh -f # Debian/Ubuntu
sudo journalctl -u sshd -f # RHEL/Fedora/Arch
Then try a fresh connection from a third terminal. The log will tell you exactly which auth method was used and why any of them failed.
Step 4 — Use ssh-agent so you are not typing the passphrase every time
Once you know the key works, add it to ssh-agent so the passphrase is cached for the session:
ssh-add ~/.ssh/id_ed25519
On macOS, add it to the keychain so it persists across reboots:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
You can also skip this step per-host by adding a section to ~/.ssh/config:
Host server
HostName server.example.com
User deploy
IdentityFile ~/.ssh/id_ed25519
AddKeysToAgent yes
Now ssh server is enough.
Step 5 — Disable password authentication
Only do this step after you have confirmed key login works from every machine that needs to reach the server. Once you turn passwords off, a lost key means you are going in through the console.
Edit the server's sshd config:
sudo nano /etc/ssh/sshd_config
Set or uncomment these lines:
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
On recent Ubuntu/Debian, there is also a conflicting override in /etc/ssh/sshd_config.d/50-cloud-init.conf that resets PasswordAuthentication yes. Edit that file too, or your change will be silently overridden:
sudo grep -r PasswordAuthentication /etc/ssh/
Step 6 — Reload sshd and verify
sudo systemctl reload ssh # Debian/Ubuntu
sudo systemctl reload sshd # RHEL/Fedora/Arch
Open a new terminal. Leave the current session open as insurance.
ssh -o PreferredAuthentications=password user@server.example.com
You should get Permission denied (publickey). That is the goal — even if someone has your password, sshd will not entertain the offer.
Close the insurance terminal only after the new session works cleanly.
Step 7 — Disable root login over SSH (while you are in there)
If you have not already, this is a good time:
PermitRootLogin no
Reload sshd again. Root logins were one of the main reasons brute-force bots paid attention in the first place. Turn them off and you will notice the port 22 noise in your logs drop by an order of magnitude.
One more layer: restrict by key
You can tie a key to specific commands or source IPs directly in authorized_keys:
from="198.51.100.0/24",command="/usr/local/bin/backup.sh",no-pty,no-port-forwarding ssh-ed25519 AAAAC3... backup@laptop
This key can only connect from that subnet, and when it does, it runs one specific script and nothing else. Useful for CI runners or backup servers that connect in with a dedicated key — if the key is ever stolen, the blast radius is exactly one command.
If you lock yourself out
Most hosting providers give you a console or recovery shell that does not go through sshd. Log in there, re-enable PasswordAuthentication yes, reload sshd, and start over. If you are on bare metal, you may need physical access.
The lesson most of us learn once: keep at least one session open until the new auth method is confirmed working. After that, key-based SSH is the kind of thing you set up once and forget about for years.
SysEmperor