When I have a private key loaded for a user, I can run ssh-copy-id user@remotehostname and will be prompted for a password. When I enter the correct password, I can now log in with the key. I have previously always run this command with -i <path to public key> as an argument, but now realize I don't need the path to the public key.

When I log in as user@hostname, I cat the .ssh/authorized_keys file, and see the public key that my private key matches, which is what confuses me - I never provided a public key.

How does ssh-copy-id know which public key matches the private key I have loaded locally when I run the command? How does it know what to add to the authorized keys file when I don't provide it?

I hope I am being clear - I've always run ssh-copy-id -i <public key> and it makes sense to me how this works - it logs in and copies the public key to the authorized keys file. But if I DON'T provide the public key (i.e. I run ssh-add <private key> before running ssh-copy-id), it still works as long as I have the private key loaded, and I don't understand how it gets the public key.

edit: To clarify, I am not keeping the default id*.pub naming convention. So the logic that I'm seeing about searching for an id*.pub in the man page doesn't seem to apply. In fact, I can create a keypair called randompair, load randompair, rename rendompair.pub as newname.pub, run ssh-copy-id and it still loads the correct public key.

Looking at the bash script itself leaves me a little confused as to how it accomplishes this.

  • 1
    ssh-copy-id is a shell script. It's not difficult to read it and see how it works.
    – Kenster
    Jul 30, 2019 at 18:27
  • @ilkkachu I'm not using default key names so it could not be that Jul 30, 2019 at 18:28
  • 2
    @Kenster, please, do use the "Your answer" text box down below.
    – ilkkachu
    Jul 30, 2019 at 18:36
  • If you lose your public key you can get it back from the private key (ssh-keygen -y), so the private key is really all you need, but I guess that wasn't your question... Jul 30, 2019 at 18:41
  • @Kenster that's a good idea, but the shell script isn't commented clearly enough for someone of my experience to understand how it accomplishes this. If it's clear to you, could you please share the answer? Jul 30, 2019 at 18:53

2 Answers 2


This is pretty well documented in the manual page on recent systems. Note that there are several different versions of the script; Arch Linux and RHEL/CentOS seem to have the same version as Debian/Ubuntu, but FreeBSD has slightly different options.

By default, ssh-copy-id calls ssh-add -L to list the keys that you have registered in the SSH agent. ssh-add -L outputs a list of public keys for which you have the private key in the agent. You might wonder how the agent can do this since you don't pass it a public key either. The answer is that it's always possible to reconstruct the public key from the private key (this is true of all the cryptosystems that SSH supports and most that it doesn't). This is only true of the “mathematical” part of the key, however. The public key file can also contain a comment (which you can set with ssh-keygen -C), and the agent does not load this comment, so if you use ssh-copy-id and it takes a key via the agent, the remote host won't have this comment in authorized_keys.

If there is no running agent or it doesn't have any key, recent Linux ssh-copy-id look for (straight from the man page)

the most recent file that matches: ~/.ssh/id*.pub, (excluding those that match ~/.ssh/*-cert.pub) so if you create a key that is not the one you want ssh-copy-id to use, just use touch(1) on your preferred key's .pub file to reinstate it as the most recent.

Older versions of the script and non-Linux versions don't have this most-recent-file behavior. As far as I remember, even older versions didn't probe the agent and just read the default path ~/.ssh/id_rsa.pub by default.


ssh-copy-id uses [1] ssh-add -L command, which allows [2]

you to view the public keys of the identities ssh-agent currently maintains.

So, if no -i provided, it can find it out on this way.

[1] https://linux.die.net/man/1/ssh-copy-id

[2] How to check which SSH keys are currently 'active'?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .