SSH-COPY-ID(1)
โจ NAME โจ
Okay bestie, this is ssh-copy-id(1) from the General Commands Manual ๐ It's basically how you use the keys already on your machine to authorise logins on a remote machine ๐
๐ธ SYNOPSIS ๐ธ
ssh-copy-id [-f] [-n] [-s] [-x] [-i [identity_file]] [-t target_path]
[-F ssh_config] [[-o ssh_option] ...] [-p port]
[user@]hostname
ssh-copy-id -h | -?
๐ DESCRIPTION ๐
okay so ssh-copy-id is a script that uses ssh(1) to log into a remote machine ๐ง It usually needs a login password, so password authentication should be enabled, unless you've done some clever stuff with multiple identities ๐ It builds a list of one or more fingerprints (more on that below) and tries logging in with each key to see if any of them are already installed. Heads up, if you're not using ssh-agent(1), this can have you getting prompted for pass-phrases over and over, so iykyk ๐ญ Then it makes a list of the keys that failed to log in and, using ssh(1), enables logins with those keys on the remote server โจ
By default it adds the keys by appending them to the remote user's ~/.ssh/authorized_keys, and it'll create the file and directory if they don't exist yet ๐ It's also smart enough to notice if the remote system is a NetScreen, and in that case it uses its set ssh pka-dsa key ... command instead ๐
๐ฆ The options ๐ฆ
The options are as follows:
-i [identity_file]โ Lowkey the most important one ๐ This uses only the key(s) inside identity_file, instead of hunting for identities via ssh-add(1) or in the default_ID_file. If the filename doesn't end in.pub, that gets added for you. If you leave the filename out, the default_ID_file gets used. Pro tip: this is how you make sure the copied keys have the comment you want and/or extra options applied, as long as the key file has those set up before you attempt the copy ๐ซถ-fโ Forced mode ๐ It doesn't check whether the keys are already on the remote server, which means it doesn't need the private key at all. Be warned though, this can end up with more than one copy of the key installed on the remote system ๐-nโ Dry-run vibes ๐ Nothing gets installed. It just prints the key(s) that would have been installed.-sโ SFTP mode ๐ฆ Normally the public keys get installed by running commands on the remote side. With this one, your~/.ssh/authorized_keysgets downloaded, edited locally, and uploaded again with sftp. It's a lifesaver if the server restricts which commands you can run on its side ๐ฅ-t target_pathโ Where the keys get added on the target system ๐ It defaults to.ssh/authorized_keys.-p portโ The port to connect to on the remote host โญ-F ssh_config,-o ssh_optionโ These get passed through untouched, argument and all, to ssh/sftp ๐-Flets you pick an alternative config file, and-olets you set other options. Honestly though, it's usually cleaner to put per-host settings in ssh(1)'s configuration file, ssh_config(5), instead of typing them on the command line ๐ง-xโ Debugging the ssh-copy-id script itself ๐ It sets the shell's-xflag, so you can literally watch every command being run โจ-h,-?โ Prints the Usage summary ๐
Okay, so if you don't use -i, the default behaviour is to check whether ssh-add -L gives any output. If it does, those keys get used ๐
Just know that the comment on the key ends up being the filename you gave ssh-add(1) when you loaded it into your ssh-agent(1), not the comment inside the file. It's a bit of a shame, ngl ๐ฅบ If ssh-add(1) gives back no keys at all, the contents of the default_ID_file are used instead.
The default_ID_file is the most recent file matching ~/.ssh/id*.pub (excluding anything matching ~/.ssh/*-cert.pub) ๐ซง So if you made a key that isn't the one you want ssh-copy-id to use, just run touch(1) on your preferred key's .pub file to make it the most recent again. Main character energy ๐
๐ง EXAMPLES ๐ง
Real talk, if you've already installed keys from one system on a bunch of remote hosts, and then you make a brand new key on a new client machine, it gets hard to remember which systems have the new key ๐ญ One way to handle this is to load both the new key and the old key(s) into your ssh-agent(1). Load the new key first, without the -c option, then load one or more old keys into the agent, possibly by ssh-ing to the client machine that has that old key, using the -A option to allow agent forwarding ๐
user@newclient$ ssh-add
user@newclient$ ssh -A old.client
user@oldl$ ssh-add -c
... prompt for pass-phrase ...
user@old$ logoff
user@newclient$ ssh someserver
Now, if the new key is installed on the server, you'll get let in without being prompted ๐ซถ But if you only have the old key(s) enabled, you'll get asked for confirmation, and that's your cue to log back out and run:
user@newclient$ ssh-copy-id -i someserver
So why use the -i option here? It makes sure the comment on the installed key is the one from the .pub file, not just the filename that got loaded into your agent ๐ It also means only the id you meant to install gets installed, instead of every key sitting in your ssh-agent(1) ๐ฅ Of course, you can specify another id, or use the contents of the ssh-agent(1) if that's your thing โจ
Also, since we're talking about ssh-add(1)'s -c option: you might think about using it whenever you use agent forwarding, to stop your key getting hijacked ๐ But honestly it's way better to use ssh(1)'s ProxyCommand and -W option to bounce through remote servers while still doing direct end-to-end authentication ๐
That way the middle hop(s) never get access to your ssh-agent(1). A web search for ssh proxycommand nc should be super enlightening ๐ (NB: the modern approach is to use the -W option, rather than nc(1).)
๐ฆ SEE ALSO ๐ฆ
That's the whole tea โ๐ This page is from Debian, dated June 17, 2010, and it's SSH-COPY-ID(1) forever ๐ง๐โจ
๐ฆ where this page comes from
- alpine 3.22: openssh-doc 10.0_p1-r10 ยท SSH-OpenSSH
- alpine 3.23: openssh-doc 10.2_p1-r0 ยท SSH-OpenSSH
- alpine 3.24: openssh-doc 10.3_p1-r1 ยท SSH-OpenSSH
- arch rolling: openssh 10.6p1-1
- arch rolling: openssh 10.6p1-2 ยท 0BSD AND BSD-2-Clause AND BSD-3-Clause AND ISC AND LicenseRef-Public-Domain AND MIT
- centos-stream 10: openssh-clients 9.9p1-34.el10 ยท BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND snprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
- centos-stream 9: openssh-clients 9.9p1-16.el9 ยท BSD
- debian trixie: openssh-client 1:10.0p1-7+deb13u2 ยท OpenSSH
- debian trixie: openssh-client 1:10.0p1-7+deb13u4 ยท OpenSSH
- fedora 43: openssh-clients 10.0p1-12.fc43
- fedora 43: openssh-clients 10.0p1-14.fc43 ยท BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND snprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
- fedora 43: openssh-clients 10.0p1-5.fc43 ยท BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
- fedora 44: openssh-clients 10.2p1-14.fc44
- fedora 44: openssh-clients 10.2p1-16.fc44 ยท BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND snprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
- fedora 44: openssh-clients 10.2p1-7.fc44 ยท BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND snprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
- nixos 26.05: openssh 10.6p1
- nixos 26.05: openssh-test 10.6p1
- nixos 26.05: openssh-with-gssapi 10.4p1
- nixos 26.05: openssh-with-hpn 10.5p1
- nixpkgs unstable: openssh 10.6p1
- nixpkgs unstable: openssh-test 10.6p1
- nixpkgs unstable: openssh-with-gssapi 10.4p1
- nixpkgs unstable: openssh-with-hpn 10.5p1
- nixpkgs unstable: ssh-copy-id 10.6p1
- opensuse-leap 16.0: openssh-clients 10.0p2-160000.7.1 ยท BSD-2-Clause AND MIT
- opensuse-leap 16.0: openssh-clients 10.0p2-160000.7.1 ยท BSD-2-Clause AND MIT
- opensuse-leap 16.0: openssh-clients 10.0p2-160000.7.1 ยท BSD-2-Clause AND MIT
- opensuse-leap 16.0: openssh-clients 10.0p2-160000.7.1 ยท BSD-2-Clause AND MIT
- ubuntu questing: openssh-client 1:10.0p1-5ubuntu5
- ubuntu questing: openssh-client 1:10.0p1-5ubuntu5.4 ยท OpenSSH
- ubuntu resolute: openssh-client 1:10.2p1-2ubuntu3 ยท OpenSSH
- ubuntu resolute: openssh-client 1:10.2p1-2ubuntu3.6
- ubuntu resolute: openssh-client 1:10.2p1-2ubuntu3.7
- ubuntu resolute: openssh-client 1:10.2p1-2ubuntu3.8 ยท OpenSSH
- ubuntu stonking: openssh-client 1:10.5p1-1ubuntu2
- ubuntu stonking: openssh-client 1:10.5p1-1ubuntu3.1
- ubuntu stonking: openssh-client-gssapi 1:10.5p1-1ubuntu3 ยท OpenSSH
- ubuntu stonking: openssh-client-gssapi 1:10.5p1-1ubuntu3.1 ยท OpenSSH
- ๐ girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms