ssh-copy-id
ssh-copy-id is a script that ships with OpenSSH and installs your public key on a remote server. It logs in over SSH, usually with a password, skips keys that are already installed and appends the rest to the account's ~/.ssh/authorized_keys, creating the directory and file when needed. It is the usual first step before password login is turned off.
What ssh-copy-id does, step by step
According to the ssh-copy-id manual, the script uses ssh to log in to the remote machine, "presumably using a login password", so password authentication has to be enabled for the first run. It builds a list of keys, tries to log in with each one to see whether it is already installed, and then installs only those that failed. By default it appends them to ~/.ssh/authorized_keys, creating the file and directory if necessary.
Reading the script itself shows the details. On the remote side it sets umask 077, so a new directory is private and a new file is readable only by its owner. It adds a missing trailing newline before appending, so keys do not run together, and it runs restorecon when that command exists, which restores SELinux labels. It never removes existing keys.
Which keys it copies depends on the options. With -i it uses only that file. Without it, if ssh-add -L prints anything, the keys in your agent are used, and otherwise the most recently changed ~/.ssh/id*.pub file.
Commands and a manual alternative
Use a Host alias from ~/.ssh/config so you do not retype the server details. First do a dry run, which only prints the keys that would be installed, then install for real:
ssh-copy-id -n -i ~/.ssh/id_ed25519.pub myserver
ssh-copy-id -i ~/.ssh/id_ed25519.pub myserver
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 myserverThe manual lists -p for the port, -o and -F to pass ssh options or a config file, -t for another target file, -f to skip the "already installed" check, and -s to use sftp when the server restricts remote commands. Check the result with a key-only login:
ssh -o IdentitiesOnly=yes -o PasswordAuthentication=no -i ~/.ssh/id_ed25519 myserverIf the script is not available, the same thing by hand is:
cat ~/.ssh/id_ed25519.pub | ssh myserver 'umask 077; mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'The manual method does not check for duplicates or a missing final newline, so look at the file afterwards.
Gotchas and mistakes
Several defaults surprise people.
- It may copy more keys than you meant. Without
-i, every key loaded in your ssh-agent is installed, and the manual notes the comment then becomes the file name used when the key was loaded. Always pass-i. - It needs a working login first. If password login is already off and you have no key, use your provider console, not the script.
- It adds, never reviews. Duplicates (with
-f) and forgotten keys pile up in authorized_keys. - No restrictions are added. The manual says that to apply options such as
fromorcommand, edit the key file before the copy. - Only the public key. Pass the
.pubfile, never the private key. - Permissions can still block the key. The sshd manual says that if the file, the
~/.sshdirectory or the home directory is writable by others, sshd will not use the file whileStrictModesis on. See Permission denied (publickey).
Install keys for a named admin account rather than root (see PermitRootLogin).
A safe workflow before disabling password login
Copying the key is step one of moving to key-based authentication, and the order matters.
- Create a key with ssh-keygen, using a passphrase.
- Install it with
ssh-copy-id -i, keeping your original session open. - From a second terminal, log in with the key only and confirm it works.
- Edit the server configuration, then run
sudo sshd -tand reload. - From a third terminal, confirm that the key still works and that a password-only attempt is refused.
The SSH hardening guide gives the exact PasswordAuthentication and related lines. If it goes wrong, the locked-out recovery guide shows how to get back in through the provider console.
Treat the install as an access change: record whose key it is, and when someone leaves, delete their line. For a hardware-backed key, see FIDO2 and WebAuthn and the SSH two-factor authentication guide.
Related terms: authorized_keys, Key-based authentication, ssh-keygen, PasswordAuthentication, PermitRootLogin.
Frequently asked questions
What does ssh-copy-id do?
It logs in to the server over SSH and appends your public key to ~/.ssh/authorized_keys, creating the directory and file if needed. It first checks which of your keys are already installed and skips them.
Do I need password login enabled to use ssh-copy-id?
Normally yes for the first run, since the script logs in with a password to install the key. If password login is already off, add the key through another working login or your provider console.
How do I copy a specific key with ssh-copy-id?
Use the -i option with the public key file, for example ssh-copy-id -i ~/.ssh/id_ed25519.pub myserver. Without -i the script uses the keys in your ssh-agent, or otherwise the most recent id*.pub file.
What if ssh-copy-id is not installed?
Append the key by hand: pipe the .pub file to ssh and run mkdir -p ~/.ssh and cat >> ~/.ssh/authorized_keys on the server with umask 077. Then check that the directory is 700 and the file 600.
Does ssh-copy-id remove old keys?
No. It only appends keys that are missing. Review authorized_keys yourself and delete lines for former staff or retired devices.
Want to see where your own server stands?
Run the free, read-only server check, or open the Security Lab and watch the detect, contain, recover, verify loop in action.
Get your free server checkOpen the Security Lab