Control anything SSH with Homeassistant's Hass.io


What is SSH?

SSH is a powerful command line-tool, allowing for you to connect to a remote machine and issue any shell command remotely. Basically, SSH is a way of sending a command to a remote machine without doing the typing in by sitting front of the computer yourself. This means you can do things like shutdowns, maintenance, updates or anything else you want with SSH (as long as you have the username and the password of that particular server). A good example would be shutting down a remote server using this SSH command:

ssh donald@192.168.1.2 'sudo reboot'

This command will effectively restart a machine with IP 192.168.1.2 machine. Cool, but how do you do that using Homeassistant? By using the command_line component. This is all fine and dandy, but if you tried to connect to donald using this command you probably noticed that you needed a password for that. And now you have probably realized that you will not be able to put your password to the command_line component, since password request interactive. Luckily for, you can do SSH commands without entering any passwords and yet still be safe at the same time. For this feat, you will need a public/private key pair that will be used to connect to your remote machine without any passwords.

After my migration from Hassbian to Hass.io, I ran into an issue. The issue was that I could not send proper SSH commands to a computer running Hyperion. These issues with SSH were in fact caused by the concept of Docker isolation. This means that my Homeassistant's instance was completely separated from my host machine, thus not allowing me to run executables such as SSH and others. Luckily official Homeassistant Docker image has SSH client installed to the container so this mean that you can call SSH commands, but yet again there is a catch. Can you guess what is that catch? As mentioned before, we need to authenticate ourselves using a password OR public/private key pair. So let us begin by making a public/private key pair.

Generating the SSH Keys

In reality, we need to generate ssh keys both on the FROM machine and the TO machine. Because this is the only way (in SSH) for BOTH machines can prove their identity to each other. In this tutorial, a machine that we issue commands FROM will be called the MASTER & the machine and the machine executing commands SLAVE in our case MASTER is the machine running HASS.io instance.

The Guide

prerequisites:

In this tutorial we will make button in Homeassistant that when pressed will shut down our SLAVE server via SSH. Basically it will append a text file every time we press a button. This example will be a good starting point for controlling remote devices.

In my case, IP addresses were:

  • MASTER IP 192.168.0.105 and SSH port 22222
  • SLAVE IP: 192.168.0.111

Make SSH keys both on MASTER and the SLAVE

Generate SSH keys on HASS.io Homeassistant docker container

Set up MASTER:

Connect to the MASTER. This will not work "out of the box" so first follow official tutorial on how to connect to the HASS.io host running ResinOS.

ssh root@192.168.0.105 -p 22222

Now attach to the Homeassistant docker container. List available docker containers.

docker ps -a

Find one looking something like homeassistant/homeassistant3. Copy its CONTAINER ID looking something like b7dfc2f4d0c4. Then attach to your container,

docker exec -it b7dfc2f4d0c4 /bin/bash

now finally generate your SSH key, but this time in a different directory:

mkdir /config/ssh
ssh-keygen -t rsa -f /config/ssh/id_rsa  

checkout two brand-new PUBLIC & PRIVATE keys

cd /config/ssh
ls -al
cat id_rsa.pub

if all went well you public key output should look something like this:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDyiprxeHAAieq2YtiXhFgSQIhZwvY6zsPAhsNU/N6yJ+JptVJGWBNY0tAD4eQiSsl88Qe4ryWVmtnw83jUjDMZp24uRtEAPnPW3f9N8mbDnyCEtbYhIDn1KseL3SuRWyFzk0fcMExZfsXrxgZ5nD/yQKvjcHm52LrhDfauxYADItonBZA+6mXh0E1LBrk6gP884IpLLbT9xetW2ZLP6htJDTPc2k9qN1cRVj3DD5Ppfyct1FmfZcAyi3Ua2dPxzngI5RUsjLBaqP+3lluc7fJVYK7fhnGZ36E/JNEamlzktBuLG1+1G3wxCshMFFBBuLTHb7qhtueIBY/4+wduJlFD root@hassio

Copy this value, it is your PUBLIC key we will use later!

Set up SLAVE:

For testing purposes, lets create a user called mister.slave connect to your SLAVE machine

ssh myUser@192.168.0.111

add a user called mister.slave

sudo useradd mister.slave sudo
sudo passwd mister.slave

This step may differ because Unix based distros use different commands for enabling sudo on your user in my case (Debian 9) I just had to write sudo when creating a new mister.slave user.

This will require a password to write something memorable. We will delete this user later anyway. After creating a mister.slave switch to it:

sudo su mister.slave

Now that you became mister.slave user lets finally make our SSH key pair

ssh-keygen -t rsa

Okay we have our keys setup but what about passwordless connection from MASTER? Its easy we have to add the public key we copied before to our SLAVE machines' authorized_keys file.

echo "PASTE YOUR MASTER KEY INSTEAD OF THIS TEXT" >> ~/.ssh/authorized_keys

On some systems authorized_keys file must have specific Unix permissions set , and it will fail silently if you do not add these permissions so let's do that. Line below will only make the file readable and writable to our user.

chmod 600 ~/.ssh/authorized_keys

Okay our connection should be good to go. So what we just did is we created an SSH key pair on both MASTER and the SLAVE machines & we installed MASTERS public key onto SLAVE. Now the SLAVE trusts the MASTER machine and allows it to connect without a password.

You will probably be interested in running some commands with sudo without a password. For this we will need to add these lines to /etc/sudoers file.

You should be very careful when editing /etc/sudoers file, one bad character could lock you out from the system forever!

sudo visudo

Since visudo uses vim text editor it will require you to know some commands. Do not worry I will denote editor command like this: [[ ]]. Everything in the [[ ]] are editor commands that you will have to type manually on your keyboard.

Go to the bottom of the file:

[[ shift + g ]] or simply [[ G ]]

enter insert mode:

[[ i ]]

Paste this to the end of the file.

mister.slave    ALL=(ALL) NOPASSWD:    ALL

Exit text editor and save contents:

[[ :wq ]]

If all went well you should be able to run sudo commands without password:

sudo whoami

Expected output should be root. So if console printed root and did not ask you for password congrats! You can now run all sudo commands without a having to enter your users password.

Test SSH connection from MASTER to SLAVE:

connect to our MASTER machine again:

ssh root@192.168.0.105 -p 22222

then let's issue a REBOOT command to our SLAVE:

docker exec -it b7dfc2f4d0c4 /bin/bash
ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=no mister.slave@192.168.0.111 'sudo reboot'

If all went well you congrats again you rebooted your mister.slave from Homeassistant manually!

-i /config/ssh/id_rsa: Defines in which directory our private SSH key can be found. -o StrictHostKeyChecking=no: Says to your SSH client to not prompt you with warning messages or yes/no questions when host has changed.

Keep in mind that b7dfc2f4d0c4 is a unique ID of my docker container yours will definitely vary! if you are confused refer to steps we did in the beginning Set Up MASTER chapter. When your SLAVE has rebooted you can continue to Add Homeassistant Components.

Add Homeassistant Components

Add these lines to your configuration.yaml file and then restart Hass.io

switch:
  - platform: command_line
    switches:
      test_ssh:
        command_on: "ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=no mister.slave@192.168.0.111 'sudo reboot'"
  friendly_name: Magic Test Switch

Now go to your Homeassistant dashboard and press your newly created button.

Conclusions

If you followed this tutorial thoroughly you should be good to seed to start for remote control via SSH. If you are a beginner this guide is a hard and if you managed to reboot something from Homeassistant you should pat your self on the back.

Personally, I used this method for turning on effects on my Hyperion daemon. Also, I am planning to make shutdown and reboot buttons on other server I have at home. One thing to mention though is that you will not have any console output when you call a remote command using command_line component, so monitoring things on a remote machine is not possible. You can check out my Hass.io config file for further inspiration here