On this page

This guide takes the SSH part of Remote Access & File Transfer deeper. There you learned which commands to type; here you learn what is actually going on — and end up with the everyday SSH setup most professionals use.

You need the ssh command, and something to connect to. On Ubuntu and Fedora, ssh is already there. On Arch, install it with sudo pacman -S openssh. The something can be a rented server, a Raspberry Pi under the stairs, whatever has SSH enabled. Everything in this guide was verified against OpenSSH on Ubuntu 26.04 and Fedora 44.

What SSH actually does

When you type ssh [email protected], your computer and the server build an encrypted channel between them. Everything you type — including your password — travels across the network as unreadable noise to anyone in between. That “anyone” is not theoretical: on an open Wi-Fi network, unencrypted traffic can be read by others on the same network. SSH exists so that this does not matter.

The old tools telnet and ftp sent everything as readable plain text. They still exist, but you should treat them as retired: everything they did, SSH does safely. The file-transfer commands in this guide — scp, rsync, sftp — all use SSH as their secure transport.

The first connection — whose server is this?

The very first time you connect to a new server, SSH stops you:

$ ssh [email protected]
The authenticity of host 'server.example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is: SHA256:e3OHEmcFeugtHcA5MbFxf+gMnmqAwm9ekKvOe2sYokI
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Every server has a permanent identity called its host key; the fingerprint is a short summary of it.

In plain language, SSH is asking: “I’ve never met this server before. Here is its fingerprint. Do you trust it?”

This is a real decision, not a license dialog, and the honest answer depends on whose server it is:

  • You rented it (a VPS from a hosting provider): the provider’s control panel usually shows the server’s fingerprint. Comparing it with what SSH shows you is excellent security hygiene.
  • It’s your own Raspberry Pi, or an old laptop in the closet? You set it up yourself, probably this week. If nothing else has touched it since, yes is well-founded trust.
  • If someone else runs it — work, school, a friend — ask them what the fingerprint should be. Or just accept it, and rely on the warning below if the key ever changes.

After you answer yes, SSH remembers the key in ~/.ssh/known_hosts and never asks again for that server:

Warning: Permanently added 'server.example.com' (ED25519) to the list of known hosts.

Then you log in with your password. But passwords have two weaknesses: you must type them every time, and anything that can guess them can get in. Keys fix both, and the rest of this guide is about them.

The warning you must not click past

One day you might connect to a server you have used many times, and see this instead:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:/b2fy6vIjRa/Wuj2adXHBQVTPRdV5yeWH6TGKMAyQM8.
Please contact your system administrator.
Add correct host key in /home/you/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/you/.ssh/known_hosts:3
  remove with:
  ssh-keygen -f '/home/you/.ssh/known_hosts' -R 'server.example.com'
Host key for server.example.com has changed and you have requested strict checking.
Host key verification failed.

The server’s key no longer matches what known_hosts remembers. Most likely the server was reinstalled — a fresh install generates fresh keys, so this is common after a rebuild or after reflashing a Raspberry Pi’s SD card. Or the name now points at a different machine. The unlikely-but-serious explanation is that someone is impersonating the server. Do not let the key types throw you: a server holds several host keys at once, one per type such as ED25519 and ECDSA, so different lines of the same warning can name different types.

What to do: if you know the server changed, fine. If nothing you know of changed, stop and check with whoever runs the server before connecting.

Once you know it is safe, the error text tells you exactly what to do. It names the file, the line, and the command:

Offending ECDSA key in /home/you/.ssh/known_hosts:3
  remove with:
  ssh-keygen -f '/home/you/.ssh/known_hosts' -R 'server.example.com'

Run that ssh-keygen -R command (it keeps a backup of the old file, and -R stands for remove), and the next connection asks the first-connection question again. Confirm first, delete second. Always.

Keys, properly

A key pair is two files that belong together. id_ed25519.pub is the public key — a padlock you can hand out to any server, freely. id_ed25519 is the private key, the only key to that padlock. It never leaves your computer, and you never share it with anyone.

A server that knows your public key can verify that you hold the private one, without you sending anything secret across the network. That is why key logins cannot be guessed the way passwords can.

Create a pair with:

$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519):

Press Enter to accept the default location, then:

Enter passphrase for "/home/you/.ssh/id_ed25519" (empty for no passphrase):
Enter same passphrase again:

Use a passphrase. It encrypts the private key where it lies, so a stolen laptop means a thief has an encrypted file — not a working key to your servers. The obvious worry, “won’t I type it constantly?”, is what the agent solves later in this guide.

Two details worth knowing. -t ed25519 selects a modern key type, short and fast and secure. And ssh-keygen sets sensible permissions by itself. The private key becomes 600 (only you), the public key 644. No chmod needed.

What ssh-copy-id actually does

The companion command, ssh-copy-id, installs your public key on a server:

$ ssh-copy-id [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/you/.ssh/id_ed25519.pub"
/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
[email protected]'s password:

Number of key(s) added: 1

You type your server password one last time. Behind the scenes, ssh-copy-id appends one line to a file called ~/.ssh/authorized_keys in your home directory on the server — “these keys may log in as me”. One line per trusted key. It also sets the permissions the server demands: 700 for ~/.ssh, 600 for authorized_keys.

Those permissions are not cosmetic. The server refuses keys if they are too open — if everyone on the machine could edit your trusted-keys file, your key would prove nothing. And it refuses them silently: you get Permission denied (publickey) (the exact list in parentheses varies from server to server) with no hint that permissions are the cause. If a key that should work suddenly does not, check permissions first, on the server:

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys

(chmod is covered in Permissions & Ownership.)

After ssh-copy-id, log in again, no password:

If your key has a passphrase, you type that instead. One last inconvenience to go.

The agent — type it once

An agent is a small program that holds your unlocked keys in memory for you. You give it the passphrase once, per session. Every ssh after that asks the agent, not you.

Most desktops start an agent for you when you log in, and it keeps running until you log out. That is why some terminal windows ask for your passphrase while others do not — the agent remembers the key for everything inside one login. To add a key yourself:

$ ssh-add
Enter passphrase for /home/you/.ssh/id_ed25519:
Identity added: /home/you/.ssh/id_ed25519

With no file argument, ssh-add loads your default key. List what the agent holds:

$ ssh-add -l
256 SHA256:WcaEXJ8FQlIOGBsjb6UXEXztgYpymlrQUcY7P43ragA you@laptop (ED25519)

Empty it again (for example before handing the laptop to someone else):

$ ssh-add -D
All identities removed.

The passphrase-protected key on disk never changes — the agent is just your convenience layer. Reboot, and you type the passphrase once more. The key file stays encrypted at rest; you type one passphrase per session.

Nicknames — the SSH config file

By now the login command has grown annoying to type. ~/.ssh/config fixes that: a plain text file where you describe each server once. The file may not exist yet — create it with nano ~/.ssh/config:

Host myserver
    HostName server.example.com
    User you
    Port 22
    IdentityFile ~/.ssh/id_ed25519

After this, all of these become interchangeable:

$ ssh myserver
$ scp file.txt myserver:
$ rsync -av project/ myserver:/var/www/

(On the scp line, a destination ending in a bare colon means your home directory on the server.)

Each line does what it says: HostName is the real address, User the account, Port only needed if not the default 22, IdentityFile which key to offer. Add one Host block per server, spacing them with a blank line. Keep the file readable only by you (chmod 600 ~/.ssh/config) — not because ssh insists, but because it describes your machines.

Where you are now

With keys, the agent, and a config full of nicknames, you now have the everyday SSH setup most professionals use. You are also already far safer than every password login you have retired.

The natural next steps live in Remote Access & File Transfer: scp and rsync for moving files, sftp for browsing interactively. All of them use your keys automatically. The cheat sheet keeps the commands on one line each. If you ever need a flag this guide skipped, the ssh manual documents every one of them. And when that something is a server you administer, the companion guide SSH — Hardening the Server hardens the other end. Servers that only answer through another server get reached with ProxyJump — one config line, documented in the ssh_config manual alongside everything else.