# SSH & Keys, Explained

> What SSH actually is (an encrypted remote terminal into another machine), how key pairs replace passwords, and how to live with SSH day to day - config shortcuts, the agent, and the errors that bite everyone.


---

# SSH & Keys, Explained

The first time someone tells you to "just SSH into the server," it sounds like a secret handshake. You
type a command full of `@` and `:` symbols, a wall of text about fingerprints appears, you say *yes* to
something you don't understand, and suddenly your terminal is... somewhere else. Then later you're told to
"add your key," and now there are two files, one of which you must *never* share, and a single wrong move
gives you the dreaded `Permission denied (publickey)`.

Here's the calm version. SSH is one small idea - an encrypted terminal into another machine - plus one
clever trick for proving who you are without ever sending a password. Once those two ideas click, every
command and every error message stops being mysterious. This guide walks you there, slowly, with real
output at every step.

## How to read this
- **Stuck on an error right now?** Jump to [Phase 3: Living With SSH](03-living-with-ssh.md) and use the
  cheat-card at the top - it maps the common errors to calm fixes.
- **Want it to finally make sense?** Read in order. Phase 1 gives you the mental model, Phase 2 gives you
  the keys that make logins safe and effortless, and Phase 3 is how you actually live with it.

## The phases
1. **[What SSH Is](01-what-ssh-is.md)** - an encrypted remote terminal into another machine, the
   `ssh user@host` command line by line, and that first-connection fingerprint prompt explained.
2. **[Key Pairs, Demystified](02-key-pairs-demystified.md)** - public and private keys as a padlock and
   its only key, why this beats passwords, and how to generate and install one.
3. **[Living With SSH](03-living-with-ssh.md)** - the `~/.ssh/config` for shortcuts, the agent so you type
   your passphrase once, and the errors everyone hits, calmly fixed.

> This is the beginner's map. Deeper topics - port forwarding and tunnels, jump hosts, hardening
> `sshd_config` on a server you run - are deliberately left for follow-up guides so this one stays a clear
> on-ramp. When you're ready to put a key on a real machine you rent, [Deploying to a
> VPS](/guides/deploying-to-a-vps) picks up where this leaves off.

**Related:** [What a Server Is](/guides/what-a-server-is) · [Deploying to a VPS](/guides/deploying-to-a-vps) · [Linux for Servers](/guides/linux-for-servers)


---

# What SSH Is

You've used a terminal on your own computer: type a command, your machine runs it, you see the output. SSH
is that exact experience - except the machine running your commands is somewhere else. A server in a data
center. A Raspberry Pi in your closet. A cloud box you rented ten minutes ago. You type on your keyboard, the
commands travel across the internet, the *other* machine runs them, and its output travels back to your
screen.

That's the whole idea. Let's make it solid before touching a single command.

## What SSH actually is

**What it actually is.** SSH stands for **Secure Shell**. A *shell* is the program that reads your typed
commands and runs them (the thing you're already using locally). SSH gives you a shell on a *remote*
machine, with every keystroke and every byte of output **encrypted** as it crosses the network. Picture a
sealed pipe between your terminal and the far machine: anyone watching the wire in between sees only
scrambled noise.

📝 **Terminology.** People say "SSH into the server," "SSH to the box," or just "ssh in." All three mean the
same thing: open an encrypted shell session on a remote machine.

**Why people get this wrong.** Newcomers imagine SSH *transfers files* or *is a website thing*. It isn't. SSH
gives you a **command line on another computer** - the same prompt you'd get sitting at its keyboard.
(Copying files happens *over* SSH with separate tools like `scp`; a follow-up topic.) If you can use a
terminal, you already know how to use a machine over SSH. The only new part is getting *in*.

**Why this matters.** Before SSH, people logged into remote machines with Telnet, which sent everything -
including your password - as plain readable text across the network, for anyone in between to read. SSH
exists to fix exactly that: prove who you are and carry your session, all encrypted.

## The command: `ssh user@host`

**What it actually is.** One command opens a session. Here's the anatomy:

```text
   ssh   ada @ server.example.com
   │     │   │
   │     │   └── the host: which machine to connect to
   │     │       (a domain name, or a raw IP like 203.0.113.10)
   │     └────── the @ separates "who" from "where"
   └──────────── the user: which account to log in AS on that machine
```

So `ssh ada@server.example.com` means: *"Connect to the machine at `server.example.com` and log me in as the
user `ada`."* The user is an account **on the remote machine**, not your local username - though leaving off
`user@` makes SSH assume the remote username matches your local one.

**A real example.** Here's a first connection. Read the whole thing; we'll unpack the surprising middle part
next.

```console
$ ssh ada@server.example.com
The authenticity of host 'server.example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:Vlt8x2pQ0r9kZ3mC7nB1aF6dH4jL5sT0uW8yE2gXoI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'server.example.com' (ED25519) to the list of known hosts.
ada@server.example.com's password:
Welcome to Ubuntu 24.04 LTS

ada@server:~$
```

*What just happened:* a lot, in a calm order. SSH reached the remote machine, asked a one-time trust question
(the fingerprint block, explained next), accepted your `yes`, asked for `ada`'s password, and dropped you at
a **new prompt**: `ada@server:~$`. That last line is the tell - your prompt changed. You are no longer typing
into your own computer; every command from here runs *on the server*, as `ada`.

⚠️ **Gotcha - passwords here are invisible.** When SSH asks for a password, your terminal shows **nothing**
as you type - no dots, no stars, no moving cursor. This is on purpose (so nobody reads your password length
over your shoulder), but it makes everyone think the keyboard is broken the first time. It isn't - type the
password and press Enter. (Phase 2 replaces passwords with keys, which skip this prompt entirely.)

## That first-connection fingerprint prompt

This is the part that makes people nervous, so let's defuse it.

**What it actually is.** The very first time you connect to a machine, SSH has never seen it before, so it
can't be sure the thing answering is the *real* server and not an impostor in the middle. It shows you the
server's **host-key fingerprint** - a short, unique label derived from its identity - and asks you to confirm
it.

```text
   This is SSH saying:
   "Someone is claiming to be server.example.com. Their ID badge reads
    SHA256:Vlt8x2pQ...XoI. Do you trust this is who you meant to reach?"
```

**What it does in real life.** When you answer `yes`, SSH writes that fingerprint to a file on *your* machine
called `~/.ssh/known_hosts`. From then on, every time you connect, SSH silently checks that the server's
fingerprint still matches what it recorded. If it matches, you're not asked again - that's why you only see
this prompt once per machine. (The "Permanently added... to the list of known hosts" line is SSH telling you
it just saved the record.)

**The gotcha - and why this is a feature, not a nuisance.** If you connect later and the fingerprint has
*changed*, SSH will loudly refuse and warn you, because a changed key can mean someone is impersonating the
server. Most of the time it's innocent (the server was rebuilt and got a new identity), but SSH errs on the
side of stopping you. We cover that warning, and the safe way to clear it, in the
[Phase 3 cheat-card](03-living-with-ssh.md).

💡 **Key point.** The fingerprint prompt isn't a hurdle - it's SSH protecting you. If you genuinely set up or
were given this server, `yes` is correct: the first `yes` is you teaching your machine what the real server
looks like.

## What a "session" is

**What it actually is.** A **session** is the live connection from the moment you log in to the moment you
leave. While the session is open, your terminal is a window into the remote machine. Whatever you'd do
sitting at its keyboard, you do here.

**What it does in real life.** Try a couple of harmless commands once you're in, and watch where they run:

```console
ada@server:~$ whoami
ada
ada@server:~$ hostname
server
ada@server:~$ pwd
/home/ada
```

*What just happened:* `whoami` reported `ada` (the remote account you logged in as, not your local
username), `hostname` reported the *server's* name, and `pwd` ("print working directory") showed you're
sitting in `ada`'s home folder **on the server** - confirming what the changed prompt already hinted: you're
operating on the remote machine.

**Ending the session.** When you're done, you leave:

```console
ada@server:~$ exit
logout
Connection to server.example.com closed.
$
```

*What just happened:* `exit` (or `Ctrl-D`) closed the remote shell. The session ended, the encrypted pipe was
torn down, and your prompt snapped back to `$` - you're home, on your own machine again. Nothing you ran
remotely keeps running locally; the two were only joined for the life of the session.

⚠️ **Gotcha - know which machine you're on.** The single most common beginner mistake is forgetting whether
a prompt is local or remote, then running a command (especially a destructive one) on the wrong machine.
Your anchor is the **prompt**: `ada@server:~$` means you're *on the server*; a bare `$` means you're home.
When in doubt, run `hostname` - it never lies about where you are.

## Recap

1. **SSH = Secure Shell.** It's a command line on another computer, with everything encrypted on the wire.
2. **`ssh user@host`** opens a session: log in as `user` on the machine `host`.
3. **The fingerprint prompt** appears once per machine - it's SSH asking you to confirm the server is real,
   then saving that fact in `~/.ssh/known_hosts`.
4. **Passwords typed at the SSH prompt are invisible** by design - keep typing.
5. **A session** lasts from login to `exit`; your prompt changing is the sign you've arrived.

You can already get in with a password. The trouble with passwords is that they're typed, guessable, and
travel each time you connect. Next, we replace them with something far better.


---

# Key Pairs, Demystified

Passwords are exhausting and a little dangerous. You have to remember them, you type the same secret to the
server every single time you log in, and anything you type can, in principle, be guessed by a machine trying
millions of combinations. SSH keys throw that model out and replace it with something that feels like magic
the first time: you log in instantly, with no password sent anywhere, and it's *more* secure, not less.

The magic is one idea. Let's install it carefully - once you have the mental model, the commands are short
and the gotcha is obvious.

## The mental model: a padlock and its only key

**What it actually is.** When you make an SSH key, you actually make a **pair** of files that belong
together:

- A **public key** - think of it as an open **padlock**. You can hand it out freely. You hang it on any
  server you want to log into.
- A **private key** - the one and only **key that opens that padlock**. It never leaves your computer. You
  never send it anywhere. Ever.

```mermaid
flowchart LR
  PK["YOUR COMPUTER<br/>private key 🔑<br/>(stays here, never travels -<br/>the ONE key that opens the lock)"]
  PUB["THE SERVER<br/>your public key 🔒<br/>(a padlock you hung here -<br/>anyone can hold it; only your key opens it)"]
  PK -- prove ownership --> PUB
```

The beauty of a padlock: handing someone your padlock tells them **nothing** about your key. They can hang it
on a door, photograph it, copy it - and still can't open it. Only the matching private key can.

**Why people get this wrong.** The names sound symmetric, so beginners assume the two files are
interchangeable, or that the *public* one is the secret. It's the reverse: the public key is meant to be
shared, the **private** key is the secret you guard with your life. Mixing these up is the one mistake that
actually hurts (see the big gotcha below).

## Why this beats passwords

**What it does in real life.** When you log in with a key, the server doesn't ask for a secret you type -
instead it uses your padlock to pose a little challenge only the matching private key can answer. Your
computer answers it locally, the server sees a correct answer, and you're in. Two things follow, and they're
the whole reason keys win:

- **No secret ever travels.** With a password, you send the actual secret across the network on every login
  (encrypted, but the real thing still leaves your machine). With a key, your **private key never moves** -
  only a one-time proof does. There's no reusable secret on the wire to capture.
- **It resists brute force.** A password is short enough for a human to remember, which means it's short
  enough for a machine to eventually guess. A private key is enormous and random - far beyond what guessing
  can reach in any practical time. This is why internet-facing servers routinely turn passwords *off*.

💡 **Key point.** Passwords prove who you are by *sending a shared secret*. Keys prove who you are by
*demonstrating you hold the private key* - without revealing it. That single shift is what makes key logins
both effortless and safer.

## Generating a key with `ssh-keygen`

**What it does in real life.** One command creates the pair. The modern, recommended type is `ed25519`
(small, fast, strong). The `-C` flag just adds a comment so you can recognize the key later - your email is
the convention.

```console
$ ssh-keygen -t ed25519 -C "ada@example.com"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/ada/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ada/.ssh/id_ed25519
Your public key has been saved in /home/ada/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:9pK2vN... ada@example.com
```

*What just happened:* `ssh-keygen` asked three questions (Enter accepts the sensible default) and wrote
**two files**:

- `id_ed25519` - your **private** key. The secret. Guard it.
- `id_ed25519.pub` - your **public** key. The `.pub` extension always marks the padlock, the shareable half.

📝 **Terminology - the passphrase.** The *passphrase* is an optional extra lock on the **private key file
itself**, so if someone copies the file off your laptop, it's still useless without it. It's *not* the
server's password - it never goes to the server. Pressing Enter twice leaves the key unprotected (convenient,
riskier); setting one is safer, and Phase 3 shows how the **ssh-agent** lets you type it just once per
session.

## `~/.ssh/` - where keys live

**What it actually is.** All of this lives in a hidden folder in your home directory called `~/.ssh/`
(the `~` means "my home folder"). Take a quick look:

```console
$ ls -l ~/.ssh
total 12
-rw-------  1 ada ada  411 Jun 19 09:14 id_ed25519
-rw-r--r--  1 ada ada   98 Jun 19 09:14 id_ed25519.pub
-rw-r--r--  1 ada ada  142 Jun 19 09:02 known_hosts
```

*What just happened:* `ls -l` listed the folder in long form: your two new key files, plus `known_hosts` from
Phase 1 (the record of servers you've trusted). Look at the leftmost column - those letters are
**permissions**, and they matter here:

- The private key reads `-rw-------`: only *you* can read or write it. No one else on the machine can even
  look.
- The public key reads `-rw-r--r--`: you can write it, everyone can read it - fine, since it's meant to be
  shared.

⚠️ **Gotcha - permissions that are too open break logins silently.** SSH is deliberately paranoid: if your
private key or `~/.ssh` folder is readable by other users, SSH **refuses to use the key** rather than risk
it being stolen. If keys mysteriously stop working, this is a prime suspect - fix with `chmod 700 ~/.ssh` and
`chmod 600 ~/.ssh/id_ed25519`. (`ssh-keygen` sets these correctly when it creates the files; trouble usually
starts after copying keys around by hand.)

## Installing the public key with `ssh-copy-id`

**What it does in real life.** To log in with your key, the server needs your **padlock** - your public
key - added to a file in *its* `~/.ssh/` called `authorized_keys`. The clean way to do that is one command:

```console
$ ssh-copy-id ada@server.example.com
/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
ada@server.example.com's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'ada@server.example.com'"
and check to make sure that only the key(s) you wanted were added.
```

*What just happened:* `ssh-copy-id` logged in **this one last time with your password**, appended your
public key to the server's `~/.ssh/authorized_keys`, and disconnected. You just hung your padlock on the
server - from now on, your private key opens it, no password needed.

Prove it:

```console
$ ssh ada@server.example.com
Welcome to Ubuntu 24.04 LTS

ada@server:~$
```

*What just happened:* no password prompt this time. SSH offered your private key, the server checked it
against the padlock you installed, the match worked, and you were let straight in. (If you set a passphrase
on the key, you'll be asked for *that* once - Phase 3 makes even that a one-time-per-session thing.)

📝 **No `ssh-copy-id`?** On some systems (notably stock Windows) the command isn't installed. The same job
is just appending the contents of your `id_ed25519.pub` to the server's `~/.ssh/authorized_keys` - any
method that gets that one line of text into that one file works. `ssh-copy-id` automates it safely.

## The one rule that matters most

⚠️ **Gotcha - NEVER share or commit your PRIVATE key.** The single most important sentence in the guide.
Your private key (`id_ed25519`, the file *without* `.pub`) is the only thing standing between you and anyone
who wants to log in as you. So:

- **Never paste it** into a chat, an email, a ticket, or a forum post.
- **Never commit it** to a Git repository - accidentally pushing a private key to GitHub is a genuinely
  common, genuinely bad mistake, and bots scan for exactly this.
- **Never copy it onto a shared machine.** Need to log in from another computer? Generate a *new* key pair
  there.

The public key (`.pub`) is the opposite - share it freely, that's its entire purpose. You can hand out as
many copies of the padlock as you like, but the key that opens it stays in your pocket, always.

## Recap

1. **A key pair = a padlock (public key) + its only key (private key).** Hand out the padlock; guard the
   key.
2. **Keys beat passwords** because no secret travels on login, and a private key is too large to brute-force.
3. **`ssh-keygen -t ed25519`** creates the pair in `~/.ssh/`: `id_ed25519` (private) and `id_ed25519.pub`
   (public).
4. **A passphrase** is an optional extra lock on the *private key file*, not the server's password.
5. **`ssh-copy-id user@host`** installs your public key on the server so future logins use the key.
6. **Never share or commit the private key.** The `.pub` file is the only half you ever hand out.

You can now log in without typing a password. Next: making SSH pleasant to live with - short names instead
of long host strings, typing your passphrase once instead of every time, and reading the errors everyone
eventually hits.


---

# Living With SSH

You can get in, and you can get in with a key. Now let's make SSH something you barely think about: a short
name instead of a long command, your passphrase typed once instead of every time, and - when something does
go wrong - a calm, short list of what an error means and how to fix it.

If you arrived here mid-panic with an error in your terminal, start with the cheat-card. The explanations
underneath are for when you have a minute to actually understand it.

## Cheat-card: common errors → calm fixes

| What you see | What it means | Calm fix |
|---|---|---|
| `Permission denied (publickey)` | The server didn't accept your key (or you offered the wrong one / wrong username). | Check the **username** and that your **public key is in the server's `authorized_keys`**. See [below](#permission-denied-publickey). |
| `Permission denied (publickey,password)` | Same, but the server *would* take a password - your key just didn't work. | Same checks as above; you can also retry with a password to get in and fix the key. |
| `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!` | The server's host key is different from what you trusted before. | Confirm the change is expected, then remove the old line: `ssh-keygen -R hostname`. See [below](#the-host-key-changed-warning). |
| `Could not open a connection to your authentication agent` | The ssh-agent isn't running in this shell. | Start it: `eval "$(ssh-agent -s)"`, then `ssh-add`. See [below](#the-ssh-agent). |
| `Connection refused` | Nothing is listening for SSH at that host/port. | The server may be off, the address wrong, or SSH not running there. Verify the host and that the machine is up. |
| `Connection timed out` | No reply at all - usually a firewall or wrong address. | Double-check the host/IP; a firewall may be blocking you. |

Now the parts worth understanding.

## `~/.ssh/config` - stop typing long host strings

**What it actually is.** Typing `ssh ada@server.example.com` over and over (remembering which key, which
port, which username for *which* server) gets old fast. The file `~/.ssh/config` lets you save all of that
under a **short nickname** you make up.

**What it does in real life.** Create or edit `~/.ssh/config` and add a block:

```text
Host myserver
    HostName server.example.com
    User ada
    IdentityFile ~/.ssh/id_ed25519
```

Each line is plain: `Host` is the nickname you'll type, `HostName` is the real address, `User` is the
account to log in as, and `IdentityFile` points at the private key to use. Now your daily login shrinks to:

```console
$ ssh myserver
ada@server:~$
```

*What just happened:* SSH read `~/.ssh/config`, saw the nickname `myserver`, and expanded it into the full
`ada@server.example.com` connection using the key you named. You typed one short word; SSH filled in the
rest. The same nickname works with related tools too (like `scp`).

💡 **Key point.** The config file is pure convenience - it changes *nothing* about security, it just saves
you from memorizing and retyping connection details. The moment you have more than one server, you'll want
it.

## The ssh-agent - type your passphrase once

**What it actually is.** If you protected your private key with a passphrase (Phase 2 - and you should), SSH
asks for it *every* time you connect. The **ssh-agent** is a small program that holds your **unlocked**
private key in memory for the session, so you type the passphrase once and SSH borrows the key from the
agent after that.

```mermaid
sequenceDiagram
  participant You
  participant Agent as ssh-agent
  participant SSH
  You->>Agent: first time - type passphrase
  Agent->>Agent: unlock & hold the key
  SSH->>Agent: every connection after
  Agent-->>SSH: instant, no passphrase
  Note over Agent: log out / reboot - agent forgets (type it once more next time)
```

**What it does in real life.** On most desktop systems the agent is already running. You hand it your key
once with `ssh-add`:

```console
$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/ada/.ssh/id_ed25519:
Identity added: /home/ada/.ssh/id_ed25519 (ada@example.com)
```

*What just happened:* you typed the passphrase one time. The agent unlocked the key and is now holding it.
For the rest of this login session, `ssh myserver` just works - no more passphrase prompts - because SSH
quietly asks the agent instead of asking you.

⚠️ **Gotcha - "Could not open a connection to your authentication agent."** This means no agent is running
in your current shell. Start one and try again:

```console
$ eval "$(ssh-agent -s)"
Agent pid 4123
$ ssh-add ~/.ssh/id_ed25519
Identity added: /home/ada/.ssh/id_ed25519 (ada@example.com)
```

*What just happened:* `ssh-agent -s` printed the setup commands for a new agent, and `eval` ran them so your
shell knows how to reach it. Then `ssh-add` worked. The agent forgets everything on logout or reboot - by
design, a session convenience, not permanent storage.

## When it breaks

### `Permission denied (publickey)`

**What it means.** The error everyone meets eventually, and almost always one of a few mundane things, not a
deep failure. The server did not accept your key, so it slammed the door.

Walk this short checklist, top to bottom:

```console
$ ssh -v ada@server.example.com
...
debug1: Offering public key: /home/ada/.ssh/id_ed25519 ED25519 SHA256:9pK2vN...
debug1: Authentications that can continue: publickey
...
ada@server.example.com: Permission denied (publickey).
```

*What just happened:* the `-v` ("verbose") flag makes SSH narrate what it tried - here it *offered* your key
and the server still said no. That narration is your best diagnostic tool. The usual causes, in order of how
often they're the culprit:

1. **Wrong username.** You logged in as `ada` but the account is `ubuntu` (or `root`, or `git`). The
   username is part of *who* you're proving to be; get it wrong and the right key still fails. Double-check
   what account exists on that machine.
2. **Public key not installed on the server.** Your padlock isn't in the server's `~/.ssh/authorized_keys`,
   so there's nothing for your private key to match. Re-run `ssh-copy-id ada@server.example.com` (it'll ask
   for the password once) to install it.
3. **Wrong key offered.** With several keys, SSH may not offer the one the server knows. Point at the right
   one explicitly - `ssh -i ~/.ssh/id_ed25519 ada@server.example.com` - or, better, name it in
   `~/.ssh/config` (above) so it's automatic.
4. **Permissions too open.** As covered in Phase 2, SSH refuses a private key that other users could read.
   Tighten with `chmod 700 ~/.ssh` and `chmod 600 ~/.ssh/id_ed25519`.

🪖 **War story.** Nine times out of ten, `Permission denied (publickey)` on a fresh cloud box is just the
username. People paste a guide that says `ssh root@...` when their provider actually set up an `ubuntu`
account, get the error, and assume their keys are broken. They aren't - try the right username first, every
time.

### The host-key-changed warning

**What it means.** Remember the fingerprint you trusted in Phase 1? If a server's host key later *changes*,
SSH stops you cold:

```console
$ ssh myserver
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
...
Add correct host key in /home/ada/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/ada/.ssh/known_hosts:14
Host key verification failed.
```

*What just happened:* SSH compared the server's current fingerprint to the one you trusted earlier, found
they differ, and refused to connect - a changed key *can* mean an impostor in the middle. It even tells you
which line of `known_hosts` is stale (`:14` here).

**The calm fix - but think first.** Usually this is innocent - the server was rebuilt, reinstalled, or
replaced, so it legitimately has a new identity. But "usually" isn't "always," so confirm the change was
expected (you or your provider rebuilt the box) *before* clearing it. Once satisfied it's legitimate, remove
the old record and reconnect:

```console
$ ssh-keygen -R server.example.com
# Host server.example.com found: line 14
/home/ada/.ssh/known_hosts updated.
$ ssh myserver
The authenticity of host 'server.example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:Kp3rN7...
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
ada@server:~$
```

*What just happened:* `ssh-keygen -R` ("remove") deleted the outdated entry for that host from
`known_hosts`. With the stale record gone, the next connection is treated like a brand-new one - you get the
first-time fingerprint prompt again, confirm, and you're back in. You've re-taught your machine what the
server now looks like.

⚠️ **Gotcha - don't reflexively clear this on a machine you didn't change.** If you *didn't* rebuild the
server and have no idea why its key changed, that's exactly the situation the warning exists for. Pause and
check with whoever runs the machine before deleting the entry - the warning is annoying precisely so you
won't ignore the rare time it's real.

## Where to go next

You now have the full beginner's toolkit: get in, prove who you are with keys, and stay calm when it breaks.
The natural next step is putting this to work on a machine you actually rent - generating a key, adding it at
the provider, and logging into a fresh box. That's exactly what [Deploying to a
VPS](/guides/deploying-to-a-vps) walks through.

## Recap

1. **`~/.ssh/config`** turns long connection strings into short nicknames - pure convenience, zero security
   change.
2. **The ssh-agent** holds your unlocked key for the session so you type your passphrase once
   (`ssh-add` to load it; `eval "$(ssh-agent -s)"` if no agent is running).
3. **`Permission denied (publickey)`** is usually the username, a missing public key on the server, the
   wrong key being offered, or open permissions - check with `ssh -v`.
4. **A changed host key** stops you on purpose; confirm the change is expected, then clear the stale entry
   with `ssh-keygen -R hostname`.
5. **The cheat-card** at the top maps every common error to its fix - come back to it whenever something
   refuses you.
