SSH keys explained: how to create and use an SSH key

How SSH key login works, how to create an Ed25519 key on Windows, macOS and Linux, add it to a server or GitHub, and fix Permission denied (publickey).

Illustration for the article: SSH keys explained: how to create and use an SSH key

SSH keys are the standard way to log in to servers, push code to GitHub or GitLab, and copy files securely without typing a password. Instead of a secret you share with the server, you hold a private key and the server holds the matching public key. This guide explains how SSH key login works, how to create a key pair on Windows, macOS and Linux, how to install it on a server, and the mistakes that most often cause “Permission denied (publickey)”.

What SSH keys are

SSH (Secure Shell) is a protocol for running commands on a remote computer over an encrypted connection. It supports passwords, but passwords can be guessed, phished or reused. An SSH key pair replaces the password with two files:

  • Private key, for example ~/.ssh/id_ed25519. It stays on your computer and must never be shared.
  • Public key, for example ~/.ssh/id_ed25519.pub. You copy it to every server or service you want to access.

The two are mathematically linked, as described in what is a public key: whatever the private key signs, the public key can verify, but the public key cannot be used to recreate the private one.

How an SSH key login works

  1. Your computer connects to the server and both sides set up an encrypted channel. The server proves its own identity with its host key.
  2. Your client says which public key it wants to use.
  3. The server checks whether that public key is listed in the user’s ~/.ssh/authorized_keys file.
  4. If it is, the server asks the client to sign a piece of data unique to this session. The client signs it with the private key.
  5. The server verifies the signature with the public key. If it is valid, you are logged in.

The private key never leaves your machine, and the signed data is different for every connection, so an eavesdropper has nothing to replay. A server that is broken into leaks only public keys, which are useless to an attacker.

How to create an SSH key

Modern Windows 10 and 11, macOS and Linux all include OpenSSH. Open a terminal (PowerShell on Windows) and run:

ssh-keygen -t ed25519 -C "your-name@laptop"
  • -t ed25519 chooses the Ed25519 algorithm: short, fast and secure. Use -t rsa -b 4096 only for very old systems that do not support it.
  • -C adds a comment so you can recognise the key later.
  • Accept the default file location and enter a passphrase. The passphrase encrypts the private key on disk, so a stolen laptop or backup does not give away your access.

To avoid typing the passphrase every time, load the key into the SSH agent once per session with ssh-add ~/.ssh/id_ed25519. macOS can store it in the Keychain, and Windows has an “OpenSSH Authentication Agent” service.

How to add the public key to a server

The simplest method on macOS and Linux is:

ssh-copy-id user@server.example.com

It logs in once with the password and appends your public key to ~/.ssh/authorized_keys. On Windows, or when ssh-copy-id is missing, do the same by hand: copy the single line from the .pub file and paste it as a new line into authorized_keys on the server. Then test with ssh user@server.example.com; you should be asked for the key passphrase, not the server password.

For GitHub, GitLab and similar services, open Settings > SSH keys, paste the contents of the .pub file and save. Test with ssh -T git@github.com or ssh -T git@gitlab.com.

Host keys and the first-connection warning

The first time you connect, SSH shows the server’s fingerprint and asks whether to trust it. Your answer is saved in ~/.ssh/known_hosts. If the fingerprint later changes, SSH refuses to connect with a loud warning. This usually means the server was reinstalled, but it can also mean someone is intercepting the connection. Confirm the new fingerprint with the server’s administrator before removing the old entry with ssh-keygen -R hostname.

Fixing “Permission denied (publickey)”

  • Wrong key offered. Run ssh -v user@host to see which keys are tried. Pick one explicitly with ssh -i ~/.ssh/id_ed25519 user@host.
  • Permissions too open. SSH ignores keys others can read. On the server, ~/.ssh should be 700 and authorized_keys 600; your private key should be readable only by you.
  • Key pasted incorrectly. The public key must be one unbroken line. Line breaks added by an editor or chat app make it invalid.
  • Wrong user. The key is installed for one account. ssh root@host and ssh deploy@host check different files.
  • Agent not running. If ssh-add -l says it cannot connect to the agent, start it or use -i.

Good practice

  • Use one key per device. If a laptop is lost, remove only its public key from your servers and accounts.
  • Always set a passphrase, or keep the key on a hardware security key with ssh-keygen -t ed25519-sk.
  • Once key login works, disable password login on your servers (PasswordAuthentication no in sshd_config). This stops password-guessing attacks entirely.
  • Never paste a private key into a chat, ticket or repository. If it happens, generate a new pair and remove the old public key everywhere.
  • Review authorized_keys occasionally and delete keys you no longer recognise.

Frequently asked questions

Are SSH keys safer than passwords?

Yes. A key is far too long to guess, the server never receives your secret, and a phishing site cannot capture it. Combined with a passphrase, it is also protected if the file is stolen.

Can I use the same SSH key on several computers?

You can copy it, but it is better to create a separate key on each computer. That way one lost device does not force you to replace access everywhere.

What happens if I lose my private key?

Nothing can recover it. Log in another way, for example with a cloud provider’s web console, add a new public key and remove the old one.

Is SSH the same as SFTP?

SFTP is a file-transfer protocol that runs inside an SSH connection, so the same keys work for both.

In short: create a key pair with ssh-keygen -t ed25519, protect the private key with a passphrase, and copy only the .pub file to servers and Git hosts. The server verifies a fresh signature on every login, so your secret never travels over the network.