SSH Keys Explained: Generate, Add and Use Them Safely
Create an SSH key with ssh-keygen, add it to a server and to GitHub, use ssh-agent and a config file, and fix the most common SSH permission errors.
· 6 min read
Contents
- How SSH keys work in one minute
- Step 1: Check for an existing key
- Step 2: Generate a new key
- Step 3: Add your public key to a server
- Step 4: Add your key to GitHub (or GitLab)
- Step 5: Use ssh-agent so you type the passphrase once
- Step 6: Save time with ~/.ssh/config
- Using different keys for work and personal accounts
- Step 7: Disable password logins on your server
- Fixing common SSH errors
- Best practices
- FAQ
- Ed25519 or RSA?
- Can I use the same key for multiple servers?
- I forgot my key's passphrase. Can I recover it?
- Is it safe to share my public key?
- Further reading
SSH keys let you log in to servers and push to Git hosts without typing a password — and they are far more secure than passwords. This guide covers how they work, how to create one, how to install it on a server and on GitHub, and how to fix the errors everyone hits along the way.
The commands work on Linux, macOS and Windows 10/11, which ship with OpenSSH built in.
How SSH keys work in one minute
An SSH key is a pair of files:
- Private key (for example
~/.ssh/id_ed25519): stays on your computer. Never share it, never upload it, never commit it. - Public key (
~/.ssh/id_ed25519.pub): safe to share. You copy it to every server or service you want to access.
When you connect, the server uses your public key to send a challenge that only the matching private key can answer. Your private key never leaves your machine, so there is no password for an attacker to intercept or guess.
Step 1: Check for an existing key
ls -l ~/.ssh
If you see id_ed25519 and id_ed25519.pub (or id_rsa and id_rsa.pub), you already have a key and can skip to step 3. On Windows PowerShell, use ls $env:USERPROFILE\.ssh.
Step 2: Generate a new key
ssh-keygen -t ed25519 -C "you@example.com"
-t ed25519picks the Ed25519 algorithm: modern, fast, with short keys. It is the recommended default today.-Cadds a comment (usually your email or machine name) to help you identify the key later.
Press Enter to accept the default location, then set a passphrase. The passphrase encrypts the private key on disk, so a stolen laptop or backup does not give away access. With ssh-agent (step 5) you only type it once per session.
If you need to connect to an old system that does not support Ed25519, generate an RSA key instead:
ssh-keygen -t rsa -b 4096 -C "you@example.com"
Step 3: Add your public key to a server
The easiest way on Linux and macOS:
ssh-copy-id user@203.0.113.10
It appends your public key to ~/.ssh/authorized_keys on the server and sets the right permissions.
Windows does not include ssh-copy-id. In PowerShell, this does the same:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@203.0.113.10 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
Now test it:
ssh user@203.0.113.10
If you are asked for your key passphrase (not the server password), it worked.
Step 4: Add your key to GitHub (or GitLab)
Print the public key and copy it:
cat ~/.ssh/id_ed25519.pub
On GitHub, go to Settings → SSH and GPG keys → New SSH key, paste it and save. GitLab and Bitbucket have equivalent pages in their user settings.
Test the connection:
ssh -T git@github.com
A message greeting you by username means it works. Then clone with the SSH URL:
git clone git@github.com:user/repo.git
To switch an existing repository from HTTPS to SSH:
git remote set-url origin git@github.com:user/repo.git
Step 5: Use ssh-agent so you type the passphrase once
The agent keeps your decrypted key in memory for the session.
Linux:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
macOS (stores the passphrase in the Keychain):
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
Windows (PowerShell as Administrator, once):
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519
Step 6: Save time with ~/.ssh/config
Instead of typing ssh deploy@203.0.113.10 -p 2222 -i ~/.ssh/work_key every time, create ~/.ssh/config:
Host myserver
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519
AddKeysToAgent yes
Now ssh myserver is all you need, and tools like scp, rsync and Git use the same settings:
scp backup.tar.gz myserver:/tmp/
rsync -av ./site/ myserver:/var/www/site/
Using different keys for work and personal accounts
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Clone work repositories with git clone git@github-work:company/repo.git, and Git will use the work key.
Step 7: Disable password logins on your server
Once key login works — test it in a second terminal first — turn off password authentication so bots cannot brute-force it. Edit /etc/ssh/sshd_config on the server:
PasswordAuthentication no
PermitRootLogin prohibit-password
Then reload SSH:
sudo systemctl reload ssh # Ubuntu/Debian (the service may be called sshd on other distros)
Keep your current session open until you have confirmed a new login works. Our VPS security checklist covers the rest of a server's first-day hardening.
Fixing common SSH errors
| Error | Cause | Fix |
|---|---|---|
Permission denied (publickey) | Server does not have your public key, or SSH is offering a different key | Re-run step 3; check with ssh -v user@host which keys are tried |
UNPROTECTED PRIVATE KEY FILE! | Private key permissions too open | chmod 600 ~/.ssh/id_ed25519 |
| Key ignored on the server | Wrong permissions on the server's .ssh | chmod 700 ~/.ssh and chmod 600 ~/.ssh/authorized_keys |
REMOTE HOST IDENTIFICATION HAS CHANGED! | Server was reinstalled — or something is intercepting the connection | Confirm the server really changed, then ssh-keygen -R hostname |
Too many authentication failures | Agent offers many keys before the right one | Add IdentitiesOnly yes and IdentityFile in ~/.ssh/config |
The single most useful debugging tool is verbose mode:
ssh -v user@host # add more v's (-vvv) for more detail
Best practices
- One key per device, not one key copied to every laptop. If a device is lost, you remove just its public key.
- Always use a passphrase on keys stored on laptops.
- Never commit private keys to a repository. Add
id_*patterns to your global gitignore if you keep keys in unusual places. - Review
authorized_keyson your servers occasionally and remove keys you no longer use. - Back up your private key securely (for example in a password manager) or be ready to replace it.
FAQ
Ed25519 or RSA?
Ed25519 for anything modern. Use RSA with 4096 bits only for old systems that do not support Ed25519.
Can I use the same key for multiple servers?
Yes. The same public key can be added to as many servers and services as you like.
I forgot my key's passphrase. Can I recover it?
No. Generate a new key pair and replace the old public key everywhere you used it. If you remember it and just want to change it, use ssh-keygen -p -f ~/.ssh/id_ed25519.
Is it safe to share my public key?
Yes — that is its purpose. Only the private key (the file without .pub) must stay secret.
Further reading
Keep reading
How to Secure a New Linux VPS: 10 Steps for the First Hour
A practical hardening checklist for a fresh Ubuntu or Debian server: a sudo user, SSH keys, firewall, automatic updates, fail2ban and backups.
How to Write a Good README (With a Copy-Paste Template)
What every README needs, in the order readers look for it: a clear summary, quick start, usage, configuration and contributing — plus a template you can reuse.
How to Undo Almost Anything in Git (Without Losing Work)
Undo the last commit, unstage files, discard changes, fix a bad merge or recover deleted commits. Every Git undo scenario with the exact command to use.