SSH keys replace passwords with a public/private key pair: the server stores your public key, and only the holder of the matching private key can log in. Keys cannot be brute forced like passwords, and once they work you can switch password logins off entirely. In this tutorial you will generate an Ed25519 key on your local machine, install it on an Ubuntu 24.04 server, make day-to-day use convenient with ssh-agent and ~/.ssh/config, disable password authentication, and learn how to rotate and revoke keys.
Prerequisites
To follow this tutorial, you need:
- A server running Ubuntu 24.04 LTS, such as a CubePath VPS, reachable over SSH.
- A non-root user with
sudoprivileges on the server that can currently log in with a password (or an existing key). - A local machine with OpenSSH: Linux, macOS or Windows 10/11 (the built-in OpenSSH client works in PowerShell).
Throughout the guide, replace your_user with your server username and your_server_ip with the server's public IP address.
Step 1 - Generating an Ed25519 key pair
Ed25519 is the recommended key type today: keys are short, fast and supported by every current OpenSSH release. Use RSA only if you must connect to very old systems, and then with at least 3072 bits (-t rsa -b 4096).
On your local machine, run:
ssh-keygen -t ed25519 -C "your_user@laptop-2026"
The -C comment is stored in the public key and helps you recognise it later in authorized_keys. Accept the default path (~/.ssh/id_ed25519) and enter a passphrase when asked. The passphrase encrypts the private key on disk, so a stolen laptop or backup does not give away server access.
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519):
Enter passphrase for "/home/you/.ssh/id_ed25519" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:q3Y0mXq0... your_user@laptop-2026
Two files were created: id_ed25519 (private, never share it) and id_ed25519.pub (public, safe to copy anywhere). Confirm the permissions; OpenSSH refuses to use a private key that other users can read:
ls -l ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
-rw------- 1 you you 464 Sep 25 10:12 /home/you/.ssh/id_ed25519
-rw-r--r-- 1 you you 104 Sep 25 10:12 /home/you/.ssh/id_ed25519.pub
If the private key shows anything other than -rw-------, fix it with chmod 600 ~/.ssh/id_ed25519.
TipIf you have a FIDO2 hardware key (YubiKey, SoloKey, Nitrokey), you can generate a key whose private part never leaves the device with
ssh-keygen -t ed25519-sk. The server needs no extra configuration.
Step 2 - Copying the public key to the server
The server authorises keys listed in ~/.ssh/authorized_keys of the target user. The simplest way to add yours is ssh-copy-id, which creates the file with correct permissions and avoids duplicates:
ssh-copy-id -i ~/.ssh/id_ed25519.pub your_user@your_server_ip
You will be asked for the user's password one last time:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'your_user@your_server_ip'"
and check to make sure that only the key(s) you wanted were added.
ssh-copy-id is not available in Windows PowerShell. There, pipe the key over SSH instead:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh your_user@your_server_ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Now log in. You should be asked for the key passphrase, not the account password:
ssh your_user@your_server_ip
Enter passphrase for key '/home/you/.ssh/id_ed25519':
Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.8.0-84-generic x86_64)
Step 3 - Caching the passphrase with ssh-agent
Typing the passphrase on every connection gets old quickly. ssh-agent holds the decrypted key in memory for your session, so you enter the passphrase once.
On most Linux desktops and on macOS an agent is already running. Add your key to it:
ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/you/.ssh/id_ed25519:
Identity added: /home/you/.ssh/id_ed25519 (your_user@laptop-2026)
If you get Could not open a connection to your authentication agent, start one in the current shell first with eval "$(ssh-agent -s)". On Windows, enable the agent service once from an administrator PowerShell with Get-Service ssh-agent | Set-Service -StartupType Automatic followed by Start-Service ssh-agent.
List the keys the agent holds:
ssh-add -l
256 SHA256:q3Y0mXq0... your_user@laptop-2026 (ED25519)
To limit how long a key stays unlocked, add it with a lifetime, for example eight hours: ssh-add -t 8h ~/.ssh/id_ed25519.
Step 4 - Creating an SSH client configuration
The file ~/.ssh/config lets you give servers short names and pin which key each one uses. Create or edit it on your local machine:
nano ~/.ssh/config
Add a block for your server:
Host web1
HostName your_server_ip
User your_user
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host *
ServerAliveInterval 60
AddKeysToAgent yes
IdentitiesOnly yes makes SSH offer only the listed key instead of every key in the agent, which prevents Too many authentication failures errors when you have several keys. AddKeysToAgent yes loads the key into the agent automatically the first time you use it. OpenSSH uses the first value it finds for each option, so keep specific Host blocks above the Host * block.
Make sure the file is private, then connect with the alias:
chmod 600 ~/.ssh/config
ssh web1
Step 5 - Disabling password authentication on the server
With key login working, turn off password logins so bots can no longer guess passwords. Keep your current SSH session open during this step so you can undo mistakes.
On Ubuntu 24.04, /etc/ssh/sshd_config includes every file in /etc/ssh/sshd_config.d/ before its own settings, and for each option the first value read wins. Cloud images often ship 50-cloud-init.conf with PasswordAuthentication yes, so put your settings in a file that sorts earlier:
sudo nano /etc/ssh/sshd_config.d/10-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PermitRootLogin prohibit-password still allows root to log in with a key if you have one installed, but never with a password. Use PermitRootLogin no if you only log in as your sudo user.
Check the syntax and the effective values before applying anything:
sudo sshd -t
sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication)'
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
Apply the change:
sudo systemctl restart ssh
From a new terminal on your local machine, confirm that the server now refuses passwords by forcing password authentication:
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password your_user@your_server_ip
your_user@your_server_ip: Permission denied (publickey).
Then confirm that ssh web1 still logs you in with your key before closing the old session.
Step 6 - Restricting what a key can do
Every line in authorized_keys can carry options in front of the key. This is useful for automation keys, such as the one a backup server uses, that should only work from one address and never open port forwards.
On the server, open the file:
nano ~/.ssh/authorized_keys
Prefix the relevant key with options:
from="203.0.113.10",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... backup@backup-server
from= limits the key to the given source address (it also accepts comma-separated lists and wildcards like 10.0.0.*), and restrict disables port, agent and X11 forwarding and PTY allocation. To lock a key to a single task, add command="/usr/local/bin/run-backup" so that whatever the client asks for, the server runs only that command. The changes apply on the next connection; no restart is needed.
Step 7 - Rotating and revoking keys
Rotate keys when a laptop is replaced, a team member leaves, or on a fixed schedule. The safe order is add, test, then remove, so you are never locked out.
-
Generate the new key on your local machine with a distinct file name:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_2026 -C "your_user@laptop-2026-rotated" -
Install it with the old key still working:
ssh-copy-id -i ~/.ssh/id_ed25519_2026.pub web1 -
Point
IdentityFilein~/.ssh/configat~/.ssh/id_ed25519_2026and test withssh web1. -
On the server, list the installed keys with their fingerprints and comments:
ssh-keygen -lf ~/.ssh/authorized_keys256 SHA256:q3Y0mXq0... your_user@laptop-2026 (ED25519) 256 SHA256:Zt8LxQ2b... your_user@laptop-2026-rotated (ED25519) -
Remove the old key's line from
~/.ssh/authorized_keyswithnano, then confirm that the old key is rejected:ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes your_user@your_server_ipyour_user@your_server_ip: Permission denied (publickey).
Comments are what make this workable, so always give keys a comment that names the person and device. To audit who can log in, check authorized_keys for every account with a login shell, including /root/.ssh/authorized_keys.
If you only want to change the passphrase of an existing key without replacing it, run ssh-keygen -p -f ~/.ssh/id_ed25519.
Troubleshooting
Permission denied (publickey) after copying the key. On the server, sshd ignores authorized_keys if the home directory, ~/.ssh or the file itself is writable by others. Fix the permissions with chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys and make sure the home directory is not group-writable. Then check the server log with sudo journalctl -u ssh -n 50, which states the reason, for example Authentication refused: bad ownership or modes.
Too many authentication failures. Your agent holds more keys than the server's MaxAuthTries (6 by default) and SSH offers them all. Add IdentitiesOnly yes and an explicit IdentityFile for that host in ~/.ssh/config.
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! The server's host key differs from the one saved in ~/.ssh/known_hosts. This is expected after reinstalling the server; confirm that is what happened, then remove the stale entry with ssh-keygen -R your_server_ip. If you did not reinstall anything, do not connect and investigate first.
Seeing what the client is doing. Run ssh -v web1 to print which keys are offered and which methods the server accepts.
Conclusion
You now log in to your Ubuntu 24.04 server with a passphrase-protected Ed25519 key, the agent handles the passphrase, and password authentication is disabled. You also know how to limit automation keys and rotate keys without locking yourself out. As next steps, add a second factor with TOTP for SSH, install Fail2ban to block scanners, and restrict port 22 to known addresses with UFW.
