Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to type password only once when connecting to SSH so I use ssh-copy-id and install my pubkey into authorized keys.

But I don't keep track which servers already have my key and which does not, so I issue ssh-copy-id again sometimes which adds duplicate key to authorized_keys?

  1. How to prevent ssh-copy-id from installing the key when it is already installed?
  2. /* How to make key installation automatic and transparent when connecting to SSH (without explicit ssh-copy-id? */
share|improve this question

3 Answers 3

How to prevent ssh-copy-id from installing the key when it is already installed?

Write your own script. All ssh-copy-id does is append a line to a file. The following would check for key's existence:

#!/bin/bash
cat ~/.ssh/id_* | ssh "$@" 'mkdir -pm 0700 ~/.ssh &&
    while read -r ktype key comment; do
        if ! (grep -Fw "$ktype $key" ~/.ssh/authorized_keys | grep -qsvF "^#"); then
            echo "$ktype $key $comment" >> ~/.ssh/authorized_keys
        fi
    done'

How to make key installation automatic and transparent when connecting to SSH (without explicit ssh-copy-id?

You cannot, because if the server doesn't have your public key already, it will not know where to get it from, either.

share|improve this answer
    
"You cannot" -> I can, it is like trying to run "ssh-copy-id" every time before connecting or auto-executing certain commands after connecting. –  Vi. Mar 30 '11 at 10:34
    
Fine, you can run ssh-copy-id every time before connecting - but IMHO, that's lazy and ineffective. (In my $LOCATION, a SSH handshake may take up to 5 seconds on occassions, that's why I don't like it.) Copying the key once would be enough - just remember to do it the first time you connect to a new server. (If you manage tens or hundreds of servers, then you're using the wrong authentication method.) –  grawity Mar 30 '11 at 10:38
    
"just remember to do it the first time you connect to a new server" -> such things should be "remembered" by computer, not user. –  Vi. Mar 30 '11 at 14:59
    
@Vi: But only the user knows whether the key should be copied to the remote system (and if yes, which key: I have four). Also, where exactly the key should be put and in which format - OpenSSH has one, but not the only (unfortunately, RFC 4819 is not very common). –  grawity Mar 30 '11 at 18:40
    
@Vi: This hack may work as a ProxyCommand in your SSH client config. –  grawity Mar 30 '11 at 18:44

Will http://thinkinginsoftware.blogspot.com/2012/07/avoid-duplicates-in-authorizedkeys.html work for you? Basically the trick is you first add the key and after that you delete all occurrences of the key with the exception of the last one (Dollar+Exclamation Mark):

#!/bin/bash -ex
# ssh-copy-id-uniq.sh

user=$1
host=$2
publicKey=$3
privateKey=$4

LOCAL_HOST_NAME=`hostname`

USAGE="Usage: `basename $0`    "

if [ $# -ne "4" ] 
then
 echo $USAGE
  exit 1 
fi

su $user -c "ssh-copy-id -i $publicKey $user@$host"
ssh -i $privateKey $user@$host "sed -i \"\\\$!{/$user@$LOCAL_HOST_NAME/d;}\" ~/.ssh/authorized_keys"
share|improve this answer
1  
Would be more useful if it would remove keys based on the key itself, but not the comment - the comment might differ for the same key. OTOH there might be multiple keys with the same comment, which should be kept. –  blueyed Aug 29 '12 at 8:49
    
@blueyed: Not sure what you meant but I added some clarification in case the sed command is not clear. The line is not removed based on a comment but on the combination of user and host name. There should be no other keys for that user and hostname we would agree. –  Nestor Urquiza Oct 12 '12 at 17:27

To avoid duplicates, you can modify ssh-copy-id.

I have done this to the ssh-copy-id distributed with Debian's openssh-client, which for me was version 1:6.0p1-4. In short, I modified

cat >> ~/.ssh/authorized_keys

to

t=$(tempfile); cat ~/.ssh/authorized_keys - | sort -u > $t && mv $t ~/.ssh/authorized_keys

Here is a patch ( diff -c /usr/bin/ssh-copy-id.orig /usr/bin/ssh-copy-id )

*** /usr/bin/ssh-copy-id.orig   2013-02-08 23:18:09.000000000 +0100
--- /usr/bin/ssh-copy-id    2013-12-12 23:14:48.705964476 +0100
***************
*** 41,47 ****
  # strip any trailing colon
  host=`echo $1 | sed 's/:$//'`

! { eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 || true)" || exit 1

  cat <<EOF
  Now try logging into the machine, with "ssh '$host'", and check in:
--- 41,47 ----
  # strip any trailing colon
  host=`echo $1 | sed 's/:$//'`

! { eval "$GET_ID" ; } | ssh $host 'sh -c "umask 077; mkdir -p ~/.ssh ; t=$(tempfile); cat ~/.ssh/authorized_keys - | sort -u > \$t && mv \$t ~/.ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 || true)"' || exit 1

  cat <<EOF
  Now try logging into the machine, with "ssh '$host'", and check in:

As for 2 (make it automatic), you can't, but if you patch ssh-copy-id to avoid duplicates, it doesn't matter if you run ssh-copy-id too much.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.