How to generate an SSH key on Linux
The same commands work on Ubuntu, Debian, Fedora, Arch and nearly every other distribution: create an Ed25519 key, load it into ssh-agent and install it on a server.
Quick answer. Run the first command and press Enter at each prompt, typing a passphrase when asked.
The second installs the public key on a server; for GitHub, paste the output of
cat ~/.ssh/id_ed25519.pub instead.
ssh-keygen -t ed25519 -C "[email protected]"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
What you are creating
ssh-keygen creates a key pair: a private key that never leaves your machine and a
public key you install wherever you want to log in. When you connect, the server checks a signature
made with the private key against the public key in its authorized_keys file. No secret crosses the
network, nothing can be guessed, and once every user has a key the server can stop accepting passwords.
The same pair works for git hosting. GitHub, GitLab and Bitbucket accept the public key on your account page, and
git push stops asking for tokens.
Use the Ed25519 type. It is the default in current OpenSSH, small, fast and supported by every maintained server. RSA is for old systems that do not know Ed25519; the trade-offs are in Ed25519 vs RSA.
How to generate an SSH key on Linux
-
Make sure the OpenSSH client is installed
Almost every desktop and server distribution includes it. Run
ssh -V; if the command is missing, install the client package for your distribution:sudo apt install openssh-client # Debian, Ubuntu, Mint sudo dnf install openssh-clients # Fedora, RHEL, Rocky, Alma sudo pacman -S openssh # Arch, Manjaro sudo apk add openssh-client # Alpine -
Check for existing keys
Look in
~/.ssh. Ifid_ed25519is already there, either reuse it or choose a different file name in the next step so you do not overwrite a key that servers already trust.ls -al ~/.ssh -
Generate an Ed25519 key
Run ssh-keygen with a comment that identifies the key. Accept the default path with Enter and type a passphrase twice.
ssh-keygen -t ed25519 -C "[email protected]"The private key is saved as
~/.ssh/id_ed25519, the public key as~/.ssh/id_ed25519.pub. For a server that predates OpenSSH 6.5, usessh-keygen -t rsa -b 4096. -
Load the key into ssh-agent
Most desktops (GNOME, KDE) already run an agent;
echo $SSH_AUTH_SOCKprints its socket if so. Otherwise start one for this shell, then add the key and type the passphrase once:eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 -
Copy the public key to a server
ssh-copy-idlogs in with your password one last time, appends the key to~/.ssh/authorized_keyson the server and sets its permissions:ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostThen connect with
ssh user@host. You should be asked for the key passphrase (or nothing, if the agent has it), not the account password.
What the output means
A full run of step 3 looks like this:
$ ssh-keygen -t ed25519 -C "[email protected]"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519):
Created directory '/home/you/.ssh'.
Enter passphrase for "/home/you/.ssh/id_ed25519" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:I2McFhOvOOgBGIf3aLmk0z7TTKxZoLZ32hK6Bxbk7Tw [email protected]
The key's randomart image is:
+--[ED25519 256]--+
|... +. |
|o+. + |
|=..+ o . |
| +*o.+ o |
| **+o * S |
|+=oE+o o . |
|oo=Bo |
| o*++. |
| .+++. |
+----[SHA256]-----+
-
Created directory appears only if
~/.sshdid not exist; ssh-keygen creates it with mode700. -
The passphrase prompt reads
Enter passphrase (empty for no passphrase):on OpenSSH releases before 10. Typing shows nothing on screen. - The fingerprint identifies the public key. GitHub and GitLab show the same value next to the key, so you can tell keys apart later (more on fingerprints).
- The randomart is a picture of the same fingerprint. You can ignore it.
The public key is one line: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... [email protected]. The private key
file starts with -----BEGIN OPENSSH PRIVATE KEY----- and must never be pasted anywhere.
File permissions that ssh expects
If permissions are looser than this, the client refuses the key or the server silently ignores
authorized_keys.
| Path | Mode | Why |
|---|---|---|
~/.ssh | 700 | Only you may list or add keys. |
~/.ssh/id_ed25519 | 600 | The client rejects a private key others can read. |
~/.ssh/id_ed25519.pub | 644 | Public by design. |
~/.ssh/authorized_keys | 600 | sshd's StrictModes ignores a writable file. |
~/.ssh/config | 600 | ssh refuses a config others can write. |
| Your home directory | not group or world writable | StrictModes checks every parent folder. |
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys ~/.ssh/config
chmod 644 ~/.ssh/id_ed25519.pub
Ownership matters as much as mode: every file in ~/.ssh must belong to you. ls -la ~/.ssh
shows both.
Keep the key unlocked with ssh-agent
ssh-agent holds the decrypted key in memory, so you type the passphrase once instead of on every connection. Check whether one is running and what it holds:
$ ssh-add -l
256 SHA256:I2McFhOvOOgBGIf3aLmk0z7TTKxZoLZ32hK6Bxbk7Tw [email protected] (ED25519)
"The agent has no identities." means an agent runs but is empty; "Could not open a connection to your authentication agent." means there is none in this shell.
Add keys automatically on first use
Add this to ~/.ssh/config and the key joins the agent the first time you use it:
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
ssh-add -l lists the keys the agent holds, ssh-add -t 8h ~/.ssh/id_ed25519 adds a key that
expires after eight hours, and ssh-add -D forgets them all.
Desktops
GNOME (through GNOME Keyring or gcr-ssh-agent, depending on the release) and most KDE Plasma setups start an agent with your session. They may offer to remember the passphrase in the desktop keyring, which unlocks at login.
Servers, WSL and minimal systems
Without a desktop, nothing starts an agent. The keychain utility, packaged by most distributions, starts
one agent and shares it between all your shells. Add this line to ~/.bashrc or ~/.zshrc:
eval "$(keychain --eval --quiet id_ed25519)"
It asks for the passphrase in the first shell after a reboot and reuses the agent after that.
Copy the public key to the clipboard
For GitHub, GitLab or a web control panel you need the public key on the clipboard:
cat ~/.ssh/id_ed25519.pub # print it and select it
wl-copy < ~/.ssh/id_ed25519.pub # Wayland (wl-clipboard)
xclip -selection clipboard < ~/.ssh/id_ed25519.pub # X11 (xclip)
Copy the whole line starting with ssh-ed25519, never the file without .pub. Where to paste
it on each git host is covered in SSH key for GitHub, GitLab and Bitbucket.
Install the key on a server with ssh-copy-id
A first run of ssh-copy-id prints something like this:
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
/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
user@host's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -i /home/you/.ssh/id_ed25519 'user@host'"
and check to make sure that only the key(s) you wanted were added.
Use -p 2222 for a different port. If the server has password logins turned off already, you need
another way in: a cloud provider's key field, a console, or someone who can append the key for you. The manual method,
restricted keys and how to turn off passwords safely are in adding a key to a
server.
Use multiple SSH keys with ~/.ssh/config
Name each extra key with -f, then tell ssh which key goes with which host. Without this, ssh tries
id_ed25519 and the other default names, plus everything in the agent, in order.
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "[email protected]"
Host work-db
HostName db.internal.example.com
User alice
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Host *
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
Now ssh work-db uses the work key and only that key. For each option the first value found wins, so
keep Host * at the end. ssh -G work-db prints the settings that apply to a host.
SELinux on Fedora, RHEL, Rocky and Alma
On distributions with SELinux enforcing, sshd may only read files labelled ssh_home_t. A
.ssh folder created by mv from elsewhere, restored from a backup or copied with
cp -a can keep a wrong label, and key logins fail although the modes are right. Restore the default
labels on the server:
restorecon -R -v ~/.ssh
ls -Z ~/.ssh shows the current labels. The audit log (sudo ausearch -m avc -ts recent)
records the denial if SELinux is the cause.
Keys from the browser generator
You can also generate a key in your browser with the sshkeygen.dev generator. Move the downloaded files into place and set the permissions:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
mv -i ~/Downloads/id_ed25519 ~/Downloads/id_ed25519.pub ~/.ssh/
chmod 600 ~/.ssh/id_ed25519
Troubleshooting
"WARNING: UNPROTECTED PRIVATE KEY FILE!"
Permissions 0644 for '/home/you/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
The private key is readable by other users. Run chmod 600 ~/.ssh/id_ed25519.
"sign_and_send_pubkey: signing failed: agent refused operation"
The agent holds a key it cannot use, often after the files moved. Run ssh-add -D, fix the permissions
and add the key again.
"Could not open a connection to your authentication agent"
No agent runs in this shell. Start one with eval "$(ssh-agent -s)". Note that running
ssh-agent without eval only prints the variables and does not set them.
"Permission denied (publickey)"
Run ssh -v user@host. Lines with Offering public key show which keys were tried; if yours
is missing, add -i or an IdentityFile line. If it is offered and refused, the server does
not have it in the right account, or the server's permissions are wrong. On a Fedora, RHEL or Rocky server with
correct permissions, the SELinux labels may be wrong: run restorecon -Rv ~/.ssh there.
"Bad owner or permissions on /home/you/.ssh/config"
Run chmod 600 ~/.ssh/config. If ls -l shows root as the owner, the file was edited with
sudo; fix it with sudo chown "$USER": ~/.ssh/config.
"Host key verification failed"
The server's key no longer matches ~/.ssh/known_hosts, which happens after a reinstall and also during
an interception attempt. Verify the new fingerprint, then run ssh-keygen -R host. See
SSH key fingerprints.
"Unable to negotiate ... no matching host key type found. Their offer: ssh-rsa"
The server only offers the SHA-1 RSA signature, disabled by default since OpenSSH 8.8. Upgrade the server; if that is
impossible, allow it for that host only in ~/.ssh/config with
HostKeyAlgorithms +ssh-rsa and PubkeyAcceptedAlgorithms +ssh-rsa.
"ssh-copy-id: ERROR: No identities found"
ssh-copy-id found no key to send. Pass the file explicitly with -i ~/.ssh/id_ed25519.pub, and check
that the key was really created.
FAQ
Where are SSH keys stored on Linux?
Your own keys are in ~/.ssh, which is /home/your-name/.ssh (or /root/.ssh for root). The server's host keys, which identify the machine rather than you, are in /etc/ssh/ssh_host_*_key. Do not touch those when creating a personal key.
Do I run ssh-keygen with sudo?
No. Run it as the user who will connect. With sudo the key is written to root's home, or into yours but owned by root, and ssh then refuses it. If that happened, fix ownership with sudo chown -R "$USER": ~/.ssh.
Is the command the same on Ubuntu, Fedora and Arch?
Yes. All of them ship upstream OpenSSH, so ssh-keygen -t ed25519, ssh-agent, ssh-add and ssh-copy-id behave the same. Only the package name and the SSH server's service name differ.
How do I see my public key?
Run cat ~/.ssh/id_ed25519.pub. It is one line starting with ssh-ed25519. If the .pub file is lost, rebuild it from the private key with ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub.
Can I use the same key on several Linux machines?
It works, but one key per machine is safer: if a laptop is lost you remove one public key and every other machine keeps working. Copying a key also copies its weaknesses, such as a missing passphrase.
Should I generate a key without a passphrase?
Only for unattended jobs such as backups or CI, and then restrict what that key may do on the server. For a key you use interactively, set a passphrase and let ssh-agent remember it. See SSH key passphrases.
What is the difference between ssh-agent and keychain?
ssh-agent holds unlocked keys in memory for one login session. The keychain utility, packaged by most distributions, starts one agent and reuses it across shells and logins on the same machine, so you type the passphrase once per boot.