How to add an SSH key to a server
A server trusts a key listed in the account's ~/.ssh/authorized_keys, one public key per line. Put it there, get the permissions right, turn off passwords, and fix Permission denied.
Quick answer. Run ssh-copy-id with your public key and the remote account. It asks for
the password once and adds the key to ~/.ssh/authorized_keys on the server. Then log in without a
password.
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
ssh user@host
How key login works
When you connect, the client tells the server which public key it would like to use. sshd looks the key up in the
target account's ~/.ssh/authorized_keys. If it is listed, the server asks the client to sign a value
that is unique to this session, and checks the signature with the public key. The private key never leaves your
computer, and a recorded login cannot be replayed.
So adding a key means adding one line, the content of your .pub file, to that file on the server, with
permissions sshd accepts. Everything else on this page is either a convenient way to do that or a reason it can fail.
If you still need a key, the Linux, macOS
and Windows guides cover creating one.
Add an SSH key to a server, step by step
-
Have a key pair ready
You need the public key, the
.pubfile. If you do not have one yet, runssh-keygen -t ed25519or generate one in your browser with the sshkeygen.dev generator. -
Copy the key with ssh-copy-id
From your computer, run ssh-copy-id with the public key and the account you want to log in as. It asks for that account's password one last time.
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostFor a non-standard port add
-p 2222. ssh-copy-id skips keys that are already installed, so running it twice is harmless. -
Or append it by hand
Without ssh-copy-id (on Windows, for example), pipe the key over an ordinary SSH session. This creates the folder and file if needed and sets their permissions:
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" -
Log in with the key
Connect again. You should be asked for the key's passphrase, or nothing if ssh-agent holds it, but not for the account password.
ssh -i ~/.ssh/id_ed25519 user@host -
Turn off password logins
Once key login works for every account you need, and with a second session still open as a safety net, set these in
/etc/ssh/sshd_configand reload the SSH service:PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-passwordCheck the file with
sudo sshd -t, then reload withsudo systemctl reload sshon Debian and Ubuntu orsudo systemctl reload sshdon Fedora, RHEL and Arch.
What ssh-copy-id does
ssh-copy-id ships with OpenSSH on Linux and macOS. It logs in with whatever works (usually the password), creates
~/.ssh and authorized_keys if needed, appends the keys that are not there yet and fixes
their permissions. A typical run:
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
/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
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -i /home/you/.ssh/id_ed25519 '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
Always pass -i with the .pub file. Without it, ssh-copy-id installs every key loaded in
your agent, or else the newest key in ~/.ssh, which may not be the one you meant. -n shows what would be installed without changing
anything.
Add a key for another user
As an administrator you often install a colleague's public key for them. Do it as that user so the files get the right owner:
sudo -u bob mkdir -p -m 700 /home/bob/.ssh
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... bob@laptop' | sudo -u bob tee -a /home/bob/.ssh/authorized_keys
sudo chmod 600 /home/bob/.ssh/authorized_keys
Ask for the .pub file only, and confirm its fingerprint with the person through a second channel, for
example by reading ssh-keygen -lf bob.pub to each other. The how and why is in
SSH key fingerprints.
Inside authorized_keys
A typical file holds one key per line, with optional restrictions at the start of a line:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC0... you@laptop
from="203.0.113.0/24" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHk... office
restrict,command="/usr/local/bin/backup" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM2... backup-job
from="..."accepts the key only from the listed addresses or networks.-
command="..."runs that one command whatever the client asks for, ideal for backup or deploy keys. The command the client requested is available to it in$SSH_ORIGINAL_COMMAND. -
restrictturns off port, agent and X11 forwarding and terminal allocation in one word. Re-enable single features after it, for examplerestrict,pty. -
no-port-forwarding,no-agent-forwarding,no-X11-forwardingandno-ptyturn off one feature each, if you prefer to list them. permitopen="localhost:5432"allows port forwarding to that destination only.expiry-time="20271231"makes the key stop working after that date.
To revoke a key, delete its line. Lines starting with # are comments. List fingerprints with
ssh-keygen -lf ~/.ssh/authorized_keys.
The location is set by AuthorizedKeysFile in sshd_config. The default is
.ssh/authorized_keys .ssh/authorized_keys2, relative to the home directory. Some hardened setups move it
to a root-owned path such as /etc/ssh/authorized_keys/%u, in which case editing the file in your home
changes nothing.
Permissions sshd requires
With the default StrictModes yes, sshd ignores authorized_keys if it, the
.ssh folder, or the home directory can be written by anyone other than the owner. The fix:
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Ownership matters too: a file root creates in someone else's home belongs to root, and sshd will not trust it. Fix
it with chown -R alice: /home/alice/.ssh. On Fedora, RHEL, Rocky and Alma, also restore the SELinux
labels with restorecon -R -v /home/alice/.ssh.
Disable password login safely
Key-only login stops password guessing completely. Do it in this order so you cannot lock yourself out:
- Confirm that key login works for every account that needs access, including the one you use for sudo.
- Keep one SSH session open while you change the configuration. Existing sessions survive a reload.
-
Put the settings in a drop-in file. Debian, Ubuntu and Fedora include
/etc/ssh/sshd_config.d/*.confat the top ofsshd_config, and for each option the first value sshd reads wins. Cloud images often ship50-cloud-init.confwithPasswordAuthentication yes, which silently overrides a line further down in the main file. A file whose name sorts earlier wins:
sudo tee /etc/ssh/sshd_config.d/10-key-only.conf > /dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sudo sshd -t && sudo systemctl reload ssh
Use sshd instead of ssh as the service name on Fedora, RHEL and Arch. Then confirm the
effective values and test from a new terminal:
$ sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication)'
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
$ ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password user@host
user@host: Permission denied (publickey).
The refusal is what you want: the server no longer offers passwords at all. Only then close the safety session.
Cloud servers and panels
AWS, Google Cloud, Azure, Hetzner, DigitalOcean and others take a public key when you create a server and install
it on first boot. The default user varies: ubuntu on Ubuntu images, ec2-user on Amazon
Linux, admin on Debian images on AWS, root on many VPS providers.
-
Adding a key later through the panel usually only affects new servers. For a running one, append
it to
authorized_keysas above. -
Google Cloud keeps keys in project or instance metadata in the form
username:ssh-ed25519 AAAA... commentand its guest agent writes them into that user'sauthorized_keys. With OS Login enabled, metadata keys are ignored. - cloud-init user data can create users with keys on any provider that supports it:
#cloud-config
users:
- default
- name: deploy
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... you@laptop
Remove or rotate a key
When a laptop is lost or a colleague leaves, delete their line from authorized_keys on every server and
account. Match lines by fingerprint rather than by comment, since comments are free text:
ssh-keygen -lf ~/.ssh/authorized_keys
To rotate your own key, install the new public key first, log in with it, then remove the old line. On many servers this is a job for configuration management or SSH certificates, which the ssh-keygen reference introduces.
Troubleshooting "Permission denied (publickey)"
Work through these in order.
-
See what the client offers. Run
ssh -v user@host. Lines likeOffering public key: /home/you/.ssh/id_ed25519show which keys were tried, andServer accepts keyshows success. If your key is never offered, add-ior anIdentityFileline. -
Check the account. The key must be in the home of the user you log in as.
ssh hostuses your local user name, which is often not the remote one. - Check permissions and ownership on the server, as above.
-
Read the server log. sshd says exactly why it refused a key. Run
sudo journalctl -u ssh -n 50(Debian, Ubuntu) orsudo journalctl -u sshd -n 50, or look in/var/log/auth.logor/var/log/secure. "Authentication refused: bad ownership or modes" points at permissions. - Check for a broken line. A key pasted with line breaks, or a private key pasted by mistake, will not match. Each key must be a single line.
-
SELinux. On Fedora, RHEL, Rocky and Alma, wrong file labels block sshd even with correct modes.
Run
restorecon -Rv ~/.ssh. -
Old servers and RSA. OpenSSH 8.8 and later clients no longer sign with SHA-1. A server older
than OpenSSH 7.2 only understands that, so RSA keys fail against it. Upgrade the server, use an Ed25519 key if it
supports one, or, as a last resort, add
PubkeyAcceptedAlgorithms +ssh-rsafor that host in your client config. -
sshd configuration. Confirm
PubkeyAuthenticationis notnoand thatAuthorizedKeysFilepoints where you think, withsudo sshd -T | grep -i authorizedkeys.
The list in the error tells you what the server still allows: (publickey) means keys only;
(publickey,password) means the key failed and you mistyped the password or cancelled the prompt.
Other common errors
"Received disconnect ... Too many authentication failures"
Your agent holds many keys and ssh offered them all before the right one; the server stops after six attempts by
default (MaxAuthTries). Name the key for that host and add IdentitiesOnly yes, or run
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 user@host.
"WARNING: UNPROTECTED PRIVATE KEY FILE!"
This one is on your side: the private key is readable by others and ssh ignores it. Run
chmod 600 ~/.ssh/id_ed25519.
"Host key verification failed"
The server presented a host key that differs from the one in your known_hosts, typically after a
reinstall. Check the new fingerprint on the server's console, then remove the old entry with
ssh-keygen -R host.
"no matching host key type found. Their offer: ssh-rsa"
The server's OpenSSH is too old to sign its host key with SHA-2. Upgrade it; meanwhile
HostKeyAlgorithms +ssh-rsa in a Host block for that server lets you connect.
"Connection refused" or "Connection timed out"
The problem is not the key: nothing listens on that port, or a firewall drops the connection. Check the port, that
sshd runs (systemctl status ssh), and the provider's firewall or security group.
Windows servers
The OpenSSH Server on Windows reads C:\Users\name\.ssh\authorized_keys for standard users. For
members of the Administrators group it reads C:\ProgramData\ssh\administrators_authorized_keys
instead, and that file must be writable only by Administrators and SYSTEM. The exact icacls command is
in the Windows guide.
FAQ
Where does the public key go on the server?
In ~/.ssh/authorized_keys in the home directory of the account you log in as, for example /home/alice/.ssh/authorized_keys, one key per line. The private key never goes on the server.
Can I add several keys to one account?
Yes. Put each public key on its own line. Any one of them is enough to log in, which is how a team shares a deploy account or how you use one key per device.
Do I need to restart sshd after editing authorized_keys?
No. sshd reads authorized_keys on every login. You only reload the service after changing /etc/ssh/sshd_config or a file in sshd_config.d.
Is ssh-copy-id safe to run twice?
Yes. It first tries to log in with the key and skips keys that already work, so it does not create duplicate lines.
What if password login is already disabled and I have no key on the server?
You need another way in: the cloud provider's console or key field, a rescue system, or someone who already has access appending your public key for you. Send them the .pub file only.
Should root log in with a key?
It is better to log in as a normal user and use sudo. If root must log in directly, PermitRootLogin prohibit-password, the OpenSSH default, allows keys and refuses passwords.
How do I add a key to a server I reach through a jump host?
ssh-copy-id passes options to ssh, so ssh-copy-id -i ~/.ssh/id_ed25519.pub -o ProxyJump=bastion user@internal-host works, as does a ProxyJump line for that host in ~/.ssh/config.