Forward port 22 to a Raspberry Pi, wait a day, and read its auth log. You will find hundreds of failed logins for “root”, “admin” and “pi” from addresses you have never seen. Switching to SSH keys makes those attempts pointless, and setting them up takes about fifteen minutes.

Why SSH keys beat passwords on an exposed port
Bots don’t target you personally. They sweep whole address ranges and try common usernames with lists of default and leaked passwords. A cheap VPS, a home lab box or a NAS you opened up so you could reach it from the office all get the same treatment. A single weak or reused password is enough for them.
A key pair replaces that guessable secret. You generate two matching files on your Mac or Linux computer. The private key stays on your computer and is never sent anywhere. The public key goes on the server, in a list of keys that are allowed to log in. When you connect, the server sends a challenge that only the holder of the private key can answer. Nothing reusable crosses the network, so there is nothing for a bot to guess.
If your ISP uses carrier-grade NAT, which is common on home broadband and almost universal on mobile data in much of South Asia, your machine may not be reachable from the internet at all. Keys are still worth setting up on the local network. Once anything sits on a public IP, they are essential.
Generating an ed25519 key with a passphrase
Open Terminal and run:
ssh-keygen -t ed25519 -C “home-laptop-2026”
Ed25519 is the sensible modern choice: keys are short and fast, and any reasonably current OpenSSH supports them. Some very old NAS firmware only accepts RSA. In that case use -t rsa -b 4096. The -C comment is a label added to the end of the public key. Name the device and the year so that you can spot this key on a server later. The ssh-keygen manual page lists every other option.
Accept the default location (~/.ssh/id_ed25519). Then pick a passphrase, and don’t skip this step. The passphrase encrypts the private key file. Without one, anyone who copies that file gets a free login to every server that trusts it. The file could leak from a stolen laptop, an unencrypted backup drive or a family computer you share. Choose something long that you can actually type. If you already keep a vault, our notes on password manager habits that actually stick explain how to store it sensibly.
Copying the public key and fixing permissions
Run ssh-copy-id [email protected], replacing the username and address with your own. It asks for the server password one last time. It then appends your public key to ~/.ssh/authorized_keys on the server and creates that directory if it doesn’t exist. It never touches your private key. Recent macOS versions include ssh-copy-id. If yours doesn’t, print ~/.ssh/id_ed25519.pub on your computer and paste that single line into authorized_keys on the server.
Wrong permissions are the most common reason a key gets silently ignored. If the files are writable by other users, OpenSSH refuses the key and quietly falls back to asking for a password. On the server, run:
- chmod 700 ~/.ssh
- chmod 600 ~/.ssh/authorized_keys
On your own computer, run chmod 600 ~/.ssh/id_ed25519. The home directory on the server must not be group-writable either. Some NAS systems reset home folder permissions after updates or permission changes in their web panel, so check again if a working key suddenly stops working. For a clue, connect with ssh -v and read the server’s auth log.
Test in a second terminal, then disable password login
Leave your current session open. Open a new terminal window and connect again. You should be asked for your key’s passphrase, not the server password. If the server password prompt appears, the key is not being used. Fix that before you go any further.
Once the key works, edit /etc/ssh/sshd_config with sudo and set PasswordAuthentication no. Also set KbdInteractiveAuthentication no. Older systems call that option ChallengeResponseAuthentication. Then look inside /etc/ssh/sshd_config.d/. Some Ubuntu cloud images ship a file there that sets password authentication back to yes. Because sshd uses the first value it reads, that file can override your change.
Run sudo sshd -t to check the syntax. Then reload the service: sudo systemctl reload ssh on Debian, Ubuntu and Raspberry Pi OS, or sshd instead of ssh on Fedora and Arch. A reload doesn’t drop the session you’re already in, which is why you kept it open. In a fresh terminal, confirm two things:
- Your key still logs you in.
- ssh -o PubkeyAuthentication=no user@host is refused with “Permission denied (publickey)”.
If something goes wrong, you can still fix it from the open session. Close that session only after both checks pass. For a VPS, confirm beforehand that your provider offers a web console. For a Pi, a keyboard and monitor are your fallback.
Host aliases, ssh-agent and the macOS keychain
Typing addresses gets old quickly. Add a block like this to ~/.ssh/config on your computer:
- Host pi
- HostName 192.168.1.50
- User pi
- IdentityFile ~/.ssh/id_ed25519
Now ssh pi is all you need to type, and scp and rsync understand the same alias.
To avoid retyping the passphrase, let ssh-agent hold the unlocked key. Most Linux desktops start an agent automatically, so run ssh-add once per login. On a Mac, add AddKeysToAgent yes and UseKeychain yes under a Host * block, then run ssh-add –apple-use-keychain ~/.ssh/id_ed25519 once. After that, your macOS login unlocks the key.
Backups, lost laptops and what keys don’t fix
The simplest approach is a separate key for each computer you own. Then losing one key costs you nothing more than removing a single line. If you do back up a private key, its passphrase protects it, but keep the copy on encrypted storage anyway. When a laptop is lost or sold, remove its line from authorized_keys on every server. The comment you added at generation time is how you find the right line. Rotating keys every few years follows the same steps: create a new key, add it, test it, then delete the old line.
Be clear about the limits. Keys protect the SSH login and nothing else. They don’t patch an outdated system, secure a NAS web panel left open to the internet, or save a weak admin password on that panel. Keep packages updated. Updates fail on full disks, so clearing space safely on Linux is part of the job. Turn on two-factor authentication for the NAS account and router admin page wherever they support it. With all of that in place, the noise in your auth log becomes harmless.
