I’ve noticed there’s a significant number of posts looking for help on this topic and the posters all seem to struggle with a few common issues. I realized I’ve been almost copying and pasting my responses on these topics so it seemed like a good case for a community guide.
This guide will walk through the process of getting a command which ssh’s into another machine to get some simple data ready to be included in a command line sensor. To keep it simple I’ll use the same example from the documentation (getting CPU temperature) I’ll just run it over SSH. The focus will more be on how to test correctly, how to set up the identity file and how to handle the known hosts file in a way that works with HA.
Note that these instructions could also easily apply to any of the command line integrations or shell command. Also these instructions are going to focus on users that installed HA via the Home Assistant OS and Supervised install methods as this is where I’ve seen the most issues. It’s not useless in other install methods but it is going to talk about add-ons so those parts won’t be followable as is, you’ll have to adjust for your setup.
The SSH & Web Terminal from the list of community add-ons set up and with protection mode disabled (this is necessary to be able to execute commands on specific containers, more on this below)
Since we’ll be running these commands from sensors or service calls, interactive SSH isn’t an option so we must go password-less (plus its a security best practice). So to start we need to generate an identity file. The easiest way to do this is just to
ssh into HA (or open “Terminal” from the left side nav of your UI) and then follow this guide (or if you don’t like mine, search for “setting up password-less SSH” and pick the guide of your choice).
However there is one key exception, do not store your key file in the default location. The default location for
~/.ssh which translates to
/root/.ssh. You should not store anything in
/root for a few reasons:
- It is not a shared folder between the docker containers. The SSH & Terminal add-on is actually a different docker container then the HA application which means they do not share a filesystem, they only share specific folders such as
/rootis not shared so anything you put in that folder while ssh’ed in like this is not visible to HA.
- Even if you do get to
/rootof the actual HA container, don’t use it. Only specific folders such as
/shareare preserved across updates, everything else is wiped clean. So anything you do have stored in
/rootin the HA container will be lost next update.
Instead I’d recommend telling
ssh-keygen to store its generated ID file in
/config/.ssh. You don’t have to put it in a folder called
.ssh if you don’t want to, I just like the consistency. But you should put it in
/config so it is preserved over updates.
Now that you have your ID file, lets test the command. To do this though, we can’t just run the command while SSH’ed in normally because if your command works while ssh’ed into HA that does not mean it will work when run from HA via a command line sensor.
The reason for this is because of the docker containers like I mentioned before. When you SSH into HA you’re actually ssh’ing into an add-on which is a different docker container from HA itself. Each docker container has its own filesystem and installed packages, successfully running it while ssh’ed really doesn’t tell you anything about whether it will work when run from HA.
This is where disabling protection mode comes in. While SSH’ed into HA execute the following command (thanks @VDRainer!):
docker exec -it homeassistant bash
What this will do is open an interactive bash shell on the actual
homeassistant container where HA runs. From this shell any commands we run will be run in exactly the same way HA will run them from a shell command or command line sensor. This way we know if they work from there then they will work from HA. So now we can run our command like so and confirm that it works:
Note that for those unaware,
-iis the flag to the
sshcommand which tells it where to find the identity file to use. Since we have put the identity file in an unusual location we must specify this. Sub in the name and location you used for yours.
You’ll notice in my last screenshot that it asked me to verify the authenticity of the host. This is the final issue we have to tackle since we can’t have any interactive pieces in our final product.
Normally you just go through this once and then you are good to go, it never prompts you to verify authenticity again. However with HA this is another gotcha. The problem is that by default the
known_hosts file is stored in
/root/.ssh. Which means if you stop here your sensor will appear to work but will break next update when
/root is wiped clean.
Fortunately, there’s a very simple solution to this, we just need to tell our command that the
known_hosts file is somewhere that isn’t wiped clean every update. I would suggest also putting it within
/config/.ssh but you can put it wherever you want, as long as its in somewhere like
/config that is preserved over updates. Once you decide where to put it, add this to your command:
-o UserKnownHostsFile=/config/.ssh/known_hosts. Then run your command once more from the
docker exec shell with this addition (or from portainer if you are using the atlernative approach) so it updates your custom
known_hosts file and then you are good to go:
Note: I used
known_hosts_2here because I already have a
known_hostsfile in this spot and I didn’t want to mess up my existing sensors by removing it. But again, you can call it whatever you want and put it wherever you want, as long as its somewhere in
Alternative - no host key check
There is an alternative you will see around the forum here. If you add
-o StrictHostKeyChecking=no to your command then it will turn off host verification entirely. This works as well and is probably fine if you are going between two systems on your local network. But since this is a security bad practice I’m recommending the other way. In the end the decision is up to you though.
A few last things to be aware of. Shell commands runs in a restricted environment that doesn’t allow expanding the home director (
~) or piping output of one command into another. This is the only situation I’ve personally run into so far where you have a command working in portainer that doesn’t work in HA. Make sure to read the documentation of the integrations you use to be aware of other integration specific gotchas like this.
Also if you are having trouble the command line integrations all log stdout and stderr if you set the log level of the integration you are trying to use to
That’s it, hope it helps!