# Set up SSH keys properly: Ed25519, a passphrase and the agent

SSH keys let you log in to servers and push to Git hosts without a password. Copied-and-pasted setups often end up with an outdated key type, no passphrase or the wrong file permissions. This guide does it properly in five steps.

## What you need

- A terminal: macOS, Linux, or Windows 10/11 (OpenSSH is built in; use PowerShell)
- An account on the server or Git host you want to reach

## 1. Check for an existing key

```
ls -al ~/.ssh
```

- `id_ed25519` and `id_ed25519.pub` exist: you already have a modern key. Skip to step 3.
- Only `id_rsa` exists: it still works if it is 3072 bits or more, but a new Ed25519 key is shorter, faster and the current default.
- Nothing there, or the folder is missing: carry on.

## 2. Generate a key

```
ssh-keygen -t ed25519 -C "laptop-2026"
```

- Press Enter to accept the default file location.
- Set a passphrase. It protects the key if the file is ever copied.
- The `-C` comment is only a label. Name the device, not your email, so you can tell keys apart later.

## 3. Load the key into the agent

The agent holds the unlocked key, so you type the passphrase once per session instead of on every connection.

macOS and Linux:

```
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
```

On macOS, use `ssh-add --apple-use-keychain ~/.ssh/id_ed25519` to save the passphrase in Keychain.

Windows (PowerShell as administrator, once):

```
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519
```

## 4. Give the public key to the other side

- Server: `ssh-copy-id user@host` (macOS and Linux). On Windows, append the contents of `id_ed25519.pub` to `~/.ssh/authorized_keys` on the server.
- GitHub or GitLab: paste the contents of `id_ed25519.pub` into the SSH keys page of your account settings.

Only ever share the file ending in `.pub`. The file without it is your private key.

## 5. Test the connection

```
ssh -T git@github.com
```

A greeting with your username means it worked. For a server, `ssh user@host` should log you in without asking for the account password.

## Common mistakes and fixes

| Mistake | Symptom | Fix |
| --- | --- | --- |
| Old DSA or short RSA key | Server refuses the key | Generate an Ed25519 key (step 2) |
| Private key readable by others | "UNPROTECTED PRIVATE KEY FILE", key ignored | `chmod 700 ~/.ssh` and `chmod 600 ~/.ssh/id_ed25519` |
| No passphrase | Anyone with a copy of the file can use it | Add one: `ssh-keygen -p -f ~/.ssh/id_ed25519` |
| Private key pasted into a website | Key is compromised | Remove it there, generate a new pair, share only the `.pub` |
| Several keys, wrong one offered | "Permission denied (publickey)" | Add a `Host` block with `IdentityFile` and `IdentitiesOnly yes` to `~/.ssh/config` |
