linux, networking, OYB software, shell

Easy passwordless SSH with sshh

This little wrapper for SSH and SCP allows for comfortable management and scripting.

It is specifically recommended for developing and testing embedded systems and virtual machines  before production, where strong security is not required.


Use sshh and scpp exactly as you would use ssh and scp.


Easy install! Paste on your zsh terminal

wget -O - >> ~/.zshrc

, or on bash

wget -O - >> ~/.bashrc

It requires sshpass to be installed in the system. In Debian and derivatives, do

sudo apt-get install sshpass

Most of us already know that the ideal way to do passwordless SSH is creating a public-private key pair and adding the public key to ~/.ssh/authorized_keys.

cat ~/.ssh/ | ssh pi@ "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Also, the first time we log in remotely we will be prompted for confirmation and the connection will be registered in ~/.ssh/known_hosts.

$ ssh pi@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:PkLRnkDFSQ8dVUs7RgEvHQnSqiwPWxbIWBaczLzMaCc.
Are you sure you want to continue connecting (yes/no)?

This is all good and safe, but it is really not very practical when we are developing embedded systems, containers or virtual machines of some kind. Every time we flash our board or reinstantiate a virtual machine we will encounter this welcoming message

$ ssh pi@         
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
Please contact your system administrator.
Add correct host key in /home/nacho/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/nacho/.ssh/known_hosts:41
ECDSA host key for has changed and you have requested strict checking.
Host key verification failed.

For this kind of work, we will have different systems appear in the same default IP address, meaning that every single time we will have to remove the line from authorized_keys and again confirm for known_hosts. This is not only unconvenient, but totally prevents automated scripts from working.

The next logical thing to do is to reconfigure our SSH client in ~/.ssh/config like this

Host *
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

We won’t be bothered with the message again. As long as we copy the public key every time then we can begin scripting until we reflash or run a new VM image.

We can still do better though. It is not ideal to change our configuration from its secure defaults, and we still need to copy the key and input the password at least once.

My favourite solution is to call ssh  with the right options from the command line

ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no pi@

As for the password, we can use sshpass. It will accept the password in the command line, and that is fine for us because in this case, security is not a concern.

sshpass -p raspberry ssh pi@

We can combine both solutions, but of course this is not something that is nice to read, let alone to type. We need a wrapper for this.

Enter sshh.

sshh pi@

sshh will first prompt for your password, just as ssh . Upon successful login, it will save the password in the environment variable SSH_PWD . Consequent logins will use sshpass with the stored password.

If we are scripting or lazy we can export SSH_PWD  as part of the script or in .zshrc and .bashrc.


We can now summarize some advantages

  • There is no need to change configurations.
  • There is no need to generate keys and save them as part of the build process, which would have to be changed everytime we want to test from a new computer.
  • The public key method still works and takes precedence over SSH_PWD.
  • Care has been taken to allow for the same use cases as SSH: you can pipe to it, you can append commands, use here-strings and here-documents, and so on.
  • Ideal defaults for scripting, ServerAliveInterval  and ConnectTimeout  will detect connection problems fast enough so your routines will not remain stuck at a faulty board all night.

This all applies to scpp  just the same.

scpp file.txt pi@

Should the stored password fail, you will be prompted for a new password, but if for whatever reason you want to be asked again, rewrite SSH_PWD  or unset it.

unset SSH_PWD

# SSH and SCP wrappers for easy workflow on embedded systems using sshpass
# Usage: just do sshh where you would do ssh. Same with scpp and scp
# Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
# GPL licensed (see end of file) * Use at your own risk!

#SSH_PWD="raspberry"             # uncomment to work with this password by default

function run_only_interactive() { [ -z "$PS1" ] || $@; }
function run_only_script()      { [ -z "$PS1" ] && $@; }

function sshh()
  local RED=$'\e[1;31m'
  local YE=$'\e[1;33m'
  local NC=$'\e[0m'
  local SSH=( ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=5 -o ConnectTimeout=1 -o LogLevel=quiet )
  if [[ "$SSH_PWD" == "" ]]; then
    run_only_interactive echo -e "$1 password:"
    run_only_interactive read -s SSH_PWD
    [ "$SSH_PWD" != "" ] && run_only_interactive echo -e "saved ${BLD}$SSH_PWD${NC}"
  [[ "$SSH_PWD" != "" ]] && local SSHPASS=( sshpass -p $SSH_PWD )
  ${SSHPASS[@]} ${SSH[@]} $@
  local RET=$?
  if [ $RET -eq 5 ]; then
    echo -e "${RED}wrong SSH password ${YE}$SSH_PWD${NC} for ${YE}$1${NC}" >&2
    run_only_interactive unset SSH_PWD
    run_only_interactive sshh $@
    return 1
  if [ $RET -eq 255 ]; then
    echo -e "${RED}error in SSH connection ${YE}$1${NC}" >&2
    return 1
  return 0

function scpp()
  local RED=$'\e[1;31m'
  local YE=$'\e[1;33m'
  local NC=$'\e[0m'
  local SCP=( scp -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=5 -o ConnectTimeout=1 -o LogLevel=quiet )
  if [[ "$SSH_PWD" == "" ]]; then
    echo -e "${YE}warning${NC}: parameter SSH_PWD not found. Running without sshpass"
    $SCP $@
    sshpass -p $SSH_PWD ${SCP[@]} $@
  if [[ $? -ne 0 ]]; then
    echo -e "${RED}error in SCP connection${NC}" >&2
    return 1

# License
# This script is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this script; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA  02111-1307  USA


Author: nachoparker

Humbly sharing things that I find useful [ github dockerhub ]


  1. Very nice. Instead of doing ‘Host *’ in your ssh config you can do ‘Host some-device’ and then put device specific options there. Like:

    Host device-under-test
    User pi
    StrictHostKeyChecking no

    You still have the password problem that this solves.

Leave a Reply

Your email address will not be published. Required fields are marked *