How to Automate SSH Key Deployment by Scripting “yes” to ssh-copy-id’s First-Time Host Verification Prompt


6 views

When automating SSH key deployment using ssh-copy-id, the first connection attempt triggers host key verification:

# ssh-copy-id -i .ssh/id_dsa.pub backup@example.com
The authenticity of host 'example.com (xxx.xxx.xxx.xxx)' can't be established.
RSA key fingerprint is 39:fb:5e:70:30:33:2b:18:17:e9:4f:2f:91:b5:d2:21.
Are you sure you want to continue connecting (yes/no)?

Option 1: Using SSH StrictHostKeyChecking

The simplest method is to modify SSH's behavior:

ssh-keyscan -H example.com >> ~/.ssh/known_hosts
ssh-copy-id -i .ssh/id_dsa.pub backup@example.com

Or in a single command:

ssh -o StrictHostKeyChecking=no -i .ssh/id_dsa.pub backup@example.com "true"
ssh-copy-id -i .ssh/id_dsa.pub backup@example.com

Option 2: Expect Script

For more complex scenarios requiring interactive handling:

#!/usr/bin/expect -f
set timeout 20
spawn ssh-copy-id -i .ssh/id_dsa.pub backup@example.com
expect {
    "continue connecting" {send "yes\r"; exp_continue}
    "password:" {send "your_password\r"}
}
expect eof

Option 3: Using sshpass (for password-based auth)

sshpass -p 'your_password' ssh-copy-id -i .ssh/id_dsa.pub -o StrictHostKeyChecking=no backup@example.com

While automating the "yes" response is convenient, be aware that:

  • This bypasses host verification security
  • Only use in trusted environments
  • Consider pre-populating known_hosts through secure channels

For enterprise environments, combine multiple approaches:

#!/bin/bash
TARGET_HOST="example.com"
TARGET_USER="backup"
KEY_FILE=".ssh/id_dsa.pub"

# Pre-populate known_hosts
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan -H $TARGET_HOST >> ~/.ssh/known_hosts 2>/dev/null

# Deploy key
if ! ssh-copy-id -i $KEY_FILE $TARGET_USER@$TARGET_HOST; then
    echo "Key deployment failed" >&2
    exit 1
fi

When running ssh-copy-id for the first time against a new host, you'll encounter the host verification prompt:

# ssh-copy-id -i .ssh/id_dsa.pub backup@example.com
The authenticity of host 'example.com (xxx.xxx.xxx.xxx)' can't be established.
RSA key fingerprint is 39:fb:5e:70:30:33:2b:18:17:e9:4f:2f:91:b5:d2:21.
Are you sure you want to continue connecting (yes/no)?

The most secure way to automate this is to pre-populate the known_hosts file:

ssh-keyscan example.com >> ~/.ssh/known_hosts
ssh-copy-id -i ~/.ssh/id_dsa.pub backup@example.com

For temporary scripts or trusted environments, you can bypass the check:

ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
    -i ~/.ssh/id_dsa.pub backup@example.com "echo 'Key copied!'"

Here's a robust script that handles both approaches:

#!/bin/bash

HOST="example.com"
USER="backup"
KEY_FILE="$HOME/.ssh/id_dsa.pub"

# Method 1: Pre-scan host key
ssh-keyscan $HOST >> ~/.ssh/known_hosts 2>/dev/null

# Method 2: Direct copy with forced acceptance
ssh-copy-id -i $KEY_FILE $USER@$HOST || \
    ssh -o StrictHostKeyChecking=no -i $KEY_FILE $USER@$HOST "true"

# Verify successful key copy
ssh -i $KEY_FILE $USER@$HOST "echo 'SSH key authentication working!'"

While automation is convenient, consider these security best practices:

  • Always verify host fingerprints manually for production environments
  • Use ssh-keyscan rather than disabling StrictHostKeyChecking when possible
  • Implement proper error handling in your scripts

For complex interactive scenarios, you might use expect:

#!/usr/bin/expect -f

set timeout 20
set host "example.com"
set user "backup"
set keyfile "$env(HOME)/.ssh/id_dsa.pub"

spawn ssh-copy-id -i $keyfile $user@$host
expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "your_password\r" }
}
expect eof