Problem with Openhab user executing command over ssh

Please bear with my while I attempt to explain my problem as I feel like I’ve done everything I’m capable of doing but I’m obviously missing something, something probably simple, it does not help that my troubleshooting Linux skill are almost zero and that I simply do not understand the fundamentals of Linux

  • I’m running openhabian 2.4 on one 3+ pi and Raspbian Lite Jessie on another 3+ pi
  • I have the exec and expire binding installed, all through config files, nothing installed via paper UI
  • I’m attempting to execute stop, start, restart and is-active service commands and also power off and restart commands from openhab user to the 2nd Pi with the pi user
  • All commands function as intended when I’m executing these against local services, example frontail, influxdb, grafana etc. I can also restart and power off the openhabian pi from the exec commands

Problem: When trying to do this over ssh to the 2nd Pi the only commands that run successfully are the is-active which I’m assuming is due to not requiring sudo to execute. All other commands fail. The services I’m trying to run commands against are PiHole, OpenVPN and Unifi as well as run commands to power off and restart, etc.

  • I have created keys, as described here, set permissions (I think correctly), added openhab to sudoers, created sudoers.d to minimize access to only those commands I want.
  • I’ve also run through Rich’s guide on the Exec binding issues here.
  • I’ve done some further searching on the issue and found the following threads here, here and here but I think I’m just getting more and more confused.

I’ve setup my exec things, items, sitemap and sudoers.d (I’m not overly sure I need this, but I put one on both pi’s in an attempt to get this working) as follows:

Things

//Service Things (Exec)
Thing exec:command:openhabstatus "OpenHAB Status" @ "Network" [command="/bin/systemctl is-active openhab2.service", interval=60, timeout=5]
Thing exec:command:openhab "OpenHAB Service" @ "Network" [command="sudo /bin/systemctl %2$s openhab2.service", interval=0, autorun=true]
Thing exec:command:influxdbstatus "InfluxDB Status" @ "Network" [command="/bin/systemctl is-active influxdb.service", interval=60, timeout=5]
Thing exec:command:influxdb "InfluxDB Service" @ "Network" [command="sudo /bin/systemctl %2$s influxdb.service", interval=0, autorun=true]
Thing exec:command:grafanastatus "Grafana Status" @ "Network" [command="/bin/systemctl is-active grafana-server.service", interval=60, timeout=5]
Thing exec:command:grafana "Grafana Service" @ "Network" [command="sudo /bin/systemctl %2$s grafana-server.service", interval=0, autorun=true]
Thing exec:command:frontailstatus "Frontail Status" @ "Network" [command="/bin/systemctl is-active frontail.service", interval=60, timeout=5]
Thing exec:command:frontail "Frontail Service" @ "Network" [command="sudo /bin/systemctl %2$s frontail.service", interval=0, autorun=true]
Thing exec:command:automationpower "Automation Power" @ "Network" [command="sudo /sbin/%2$s", interval=0, autorun=true]
//Thing exec:command:nginxstatus "NGINX Status" @ "Network" [command="ssh pi@192.168.1.3 /bin/systemctl is-active nginx.service", interval=60, timeout=5]
//Thing exec:command:nginx "NGINX Service" @ "Network" [command="sudo ssh pi@192.168.1.3 sudo /bin/systemctl %2$s nginx.service", interval=60, timeout=5]
Thing exec:command:piholestatus "PiHole Status" @ "Network" [command="ssh pi@192.168.1.3 /bin/systemctl is-active pihole-FTL.service", interval=60, timeout=5]
Thing exec:command:pihole "PiHole Service" @ "Network" [command="sudo ssh pi@192.168.1.3 sudo /bin/systemctl %2$s pihole-FTL.service", interval=60, timeout=5]
Thing exec:command:openvpnstatus "OpenVPN Status" @ "Network" [command="ssh pi@192.168.1.3 /bin/systemctl is-active openvpn.service", interval=60, timeout=5]
Thing exec:command:openvpn "OpenVPN Service" @ "Network" [command="sudo ssh pi@192.168.1.3 sudo /bin/systemctl %2$s openvpn.service", interval=60, timeout=5]
Thing exec:command:unifistatus "UniFi Status" @ "Network" [command="ssh pi@192.168.1.3 /bin/systemctl is-active unifi.service", interval=60, timeout=5]
Thing exec:command:unifi "UniFi Service" @ "Network" [command="sudo ssh pi@192.168.1.3 sudo /bin/systemctl %2$s unifi.service", interval=60, timeout=5]
Thing exec:command:servicepower "Service Power" @ "Network" [command="sudo ssh pi@192.168.1.3 sudo /sbin/%2$s", interval=0, autorun=true]
//Thing exec:command:naspower "NAS Power" @ "Network" [command="sudo ssh automation@192.168.1.8 sudo /sbin/%2$s", interval=0, autorun=true]
//Thing exec:command:mediacenterpower "Media Center Power" @ "Network" [command="sudo ssh mediapi@192.168.1.24 sudo /sbin/%2$s", interval=0, autorun=true]
//Thing exec:command:networkrouterpower "Router Power" @ "Network" [command="sudo ssh unifi@192.168.1.1 sudo /sbin/%2$s", interval=0, autorun=true]
//Thing exec:command:networkswitchpower "Switch Power" @ "Network" [command="sudo ssh unifi@192.168.1.2 sudo /sbin/%2$s", interval=0, autorun=true]

Items

//Automation System
String	system_automation	"Automation"	<none>	(gSystem,gAutomationSystem)
String	system_openhabstatus	"OpenHAB [MAP(system.map):%s]"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:openhabstatus:output"}
String	system_openhab	"OpenHAB []"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:openhab:input", expire="2s,command=OFF"}
String	system_influxdbstatus	"InfluxDB [MAP(system.map):%s]"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:influxdbstatus:output"}
String	system_influxdb	"InfluxDB []"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:influxdb:input", expire="2s,command=OFF"}
String	system_grafanastatus	"Grafana [MAP(system.map):%s]"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:grafanastatus:output"}
String	system_grafana	"Grafana []"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:influxdb:input", expire="2s,command=OFF"}
String	system_frontailstatus	"Frontail [MAP(system.map):%s]"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:grafanastatus:output"}
String	system_frontail	"Frontail []"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:frontail:input", expire="2s,command=OFF"}
String	system_automationpower	"Automation []"	<none>	(gSystem,gAutomationSystem)	{channel="exec:command:automationpower:input", expire="2s,command=OFF"}

//Service System
String	system_service	"Service"	<none>	(gSystem,gServiceSystem)
//String	system_nginxstatus	"NGINX [MAP(system.map):%s]"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:nginxstatus:output"}
//String	system_nginx	"NGINX []"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:nginx:input", expire="2s,command=OFF"}
String	system_piholestatus	"PiHole [MAP(system.map):%s]"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:piholestatus:output"}
String	system_pihole	"PiHole []"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:pihole:input", expire="2s,command=OFF"}
String	system_openvpnstatus	"OpenVPN [MAP(system.map):%s]"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:openvpnstatus:output"}
String	system_openvpn	"OpenVPN []"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:openvpn:input"}
String	system_unifistatus	"UniFi [MAP(system.map):%s]"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:unifistatus:output"}
String	system_unifi	"UniFi []"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:unifi:input", expire="2s,command=OFF"}
String	system_servicepower	"Service []"	<none>	(gSystem,gServiceSystem)	{channel="exec:command:servicepower:input", expire="2s,command=OFF"}

//NAS System
String	system_nas	"NAS"	<none>	(gSystem,gNASSystem)
String	system_naspower	"NAS []"	<none>	(gSystem,gNASSystem)	{channel="exec:command:naspower:input", expire="2s,command=OFF"}

//Media Center System
String	system_mediacenter	"Media Center"	<none>	(gSystem,gMediaCenterSystem)
String	system_mediacenterpower	"Media Center []"	<none>	(gSystem,gMediaCenterSystem)	{channel="exec:command:mediacenterpower:input", expire="2s,command=OFF"}

//Network System
String	system_network	"Network"	<none>	(gSystem,gNetworkSystem)
String	system_networkrouterpower	"Router []"	<none>	(gSystem,gNetworkSystem)	{channel="exec:command:networkrouterpower:input", expire="2s,command=OFF"}
String	system_networkswitchpower	"Switch []"	<none>	(gSystem,gNetworkSystem)	{channel="exec:command:networkswitchpower:input", expire="2s,command=OFF"}

//System Actions
String	system_powerexec	"Power"	<none>	(gSystem)
String	system_serviceexec	"Services"	<none>	(gSystem)

Sitemap

sitemap system label="System" {
	Frame label="Automation" {
		Text item=system_openhabstatus valuecolor=[system_openhabstatus=="active"="green", =="inactive"="red"]
		Text item=system_influxdbstatus valuecolor=[system_influxdbstatus=="active"="green", =="inactive"="red"]
		Text item=system_grafanastatus valuecolor=[system_grafanastatus=="active"="green", =="inactive"="red"]
		Text item=system_frontailstatus valuecolor=[system_influxdbstatus=="active"="green", =="inactive"="red"]
	}
	Frame label="Service" {
	//	Text item=system_nginxstatus valuecolor=[system_nginxstatus=="active"="green", =="inactive"="red"]
		Text item=system_piholestatus valuecolor=[system_piholestatus=="active"="green", =="inactive"="red"]
		Text item=system_openvpnstatus valuecolor=[system_openvpnstatus=="active"="green", =="inactive"="red"]
		Text item=system_unifistatus valuecolor=[system_unifistatus=="active"="green", =="inactive"="red"]
	}
	Frame label="Actions" {
		Text item=system_serviceexec {
			Frame label="Services" {
				Switch item=system_openhab mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_influxdb mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_grafana mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_frontail mappings=[stop="STOP",start="START",restart="RESTART"]
	//			Switch item=system_nginx mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_pihole mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_openvpn mappings=[stop="STOP",start="START",restart="RESTART"]
				Switch item=system_unifi mappings=[stop="STOP",start="START",restart="RESTART"]
			}
		}
		Text item=system_powerexec {
			Frame label="Power" {
				Switch item=system_automationpower mappings=[reboot="REBOOT",poweroff="POWER OFF"]
				Switch item=system_servicepower mappings=[reboot="REBOOT",poweroff="POWER OFF"]
	//			Switch item=system_naspower mappings=[reboot="REBOOT",poweroff="POWER OFF"]
	//			Switch item=system_mediacenterpower mappings=[reboot="REBOOT",poweroff="POWER OFF"]
	//			Switch item=system_networkrouterpower mappings=[reboot="REBOOT"]
	//			Switch item=system_networkswitchpower mappings=[reboot="REBOOT"]
			}
		}
	}
}

sudoers.d

# Allow openhab user to execute the following commands 

# Alias
Cmnd_Alias OPENHAB = /bin/systemctl start openhab2.service, /bin/systemctl stop openhab2.service, /bin/systemctl restart openhab2.service
Cmnd_Alias INFLUXDB = /bin/systemctl start influxdb.service, /bin/systemctl stop influxdb.service, /bin/systemctl restat influxdb.service
Cmnd_Alias GRAFANA = /bin/systemctl start grafana-server.service, /bin/systemctl stop grafana-server.service, /bin/systemctl restart grafana-server.service
Cmnd_Alias FRONTAIL = /bin/systemctl start frontail.service, /bin/systemctl stop frontail.service, /bin/systemctl restart frontail.service
Cmnd_Alias AUTOMATION = /sbin/reboot, /sbin/halt, /sbin/poweroff
Cmnd_Alias PIHOLE = /bin/systemctl start pihole-FTL.service, /bin/systemctl stop pihole-FTL.service, /bin/systemctl restart pihole-FTL.service
Cmnd_Alias OPENVPN = /bin/systemctl start openvpn.service, /bin/systemctl stop openvpn.service, /bin/systemctl restart openvpn.service
Cmnd_Alias UNIFI = /bin/systemctl start unifi.service, /bin/systemctl stop unifi.service, /bin/systemctl restart unifi.service
Cmnd_Alias SERVICE = /sbin/reboot, /sbin/halt, /sbin/poweroff

# Commands
openhab ALL=(ALL) NOPASSWD: OPENHAB, INFLUXDB, GRAFANA, FRONTAIL, AUTOMATION, PIHOLE, OPENVPN, UNIFI, SERVICE
pi ALL=(ALL) NOPASSWD: PIHOLE, OPENVPN, UNIFI, SERVICE
# Allow pi user to execute the following commands 

# Alias
Cmnd_Alias PIHOLE = /bin/systemctl start pihole-FTL.service, /bin/systemctl stop pihole-FTL.service, /bin/systemctl restart pihole-FTL.service
Cmnd_Alias OPENVPN = /bin/systemctl start openvpn.service, /bin/systemctl stop openvpn.service, /bin/systemctl restart openvpn.service
Cmnd_Alias UNIFI = /bin/systemctl start unifi.service, /bin/systemctl stop unifi.service, /bin/systemctl restart unifi.service
Cmnd_Alias SERVICE = /sbin/reboot, /sbin/halt, /sbin/poweroff
# Commands
pi ALL=(ALL) NOPASSWD: PIHOLE, OPENVPN, UNIFI, SERVICE

Basic UI
Screen grab showing services running expected from the is-active command (I’ve not implemented NGINX yet, I’m a little bit afraid I’ll break everything :upside_down_face:)

Screen grab showing the service commands (I know I cannot start openhab from BasicUI as this would assume it’s not running hence it would not work, but left it in for aesthetics)

Screen grab showing the power commands (most are not implemented yet as I cannot even get the 2nd pi commands to function)

Log
This is all I see in the frontail log if I’ve clicked the OpenVPN ‘STOP’ button (the OFF is from the expire binding, again for local services this seems to work fine and stop the service).

2019-07-16 21:14:48.896 [ome.event.ItemCommandEvent] - Item 'system_openvpn' received command stop
2019-07-16 21:14:48.907 [nt.ItemStatePredictedEvent] - system_openvpn predicted to become stop
2019-07-16 21:14:48.928 [vent.ItemStateChangedEvent] - system_openvpn changed from OFF to stop
2019-07-16 21:14:51.037 [ome.event.ItemCommandEvent] - Item 'system_openvpn' received command OFF
2019-07-16 21:14:51.048 [nt.ItemStatePredictedEvent] - system_openvpn predicted to become OFF
2019-07-16 21:14:51.061 [vent.ItemStateChangedEvent] - system_openvpn changed from stop to OFF

When I SSH to openhabian and run:

[21:20:52] openhabian@automation:~$ sudo -u openhab ssh pi@192.168.1.3 sudo /bin/systemctl is-active openvpn.service
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
active

It still shows as active (I’m not sure how to get rid of the setlocale warning)

When I SSH to openhabian and run:

[21:21:29] openhabian@automation:~$ sudo -u openhab ssh pi@192.168.1.3 sudo /bin/systemctl stop openvpn.service
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)

It stops successfully, I do however need to enter the openhabian user password on the first sudo command after logging in

[21:23:16] openhabian@automation:~$ sudo -u openhab ssh pi@192.168.1.3 sudo /bin/systemctl is-active openvpn.service
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
inactive

Looking at the commands in my things I’m sure this should all just work but alas it does not

Please help! (apologies for the super long post)

There is a lot here. Let’s simplify and get just one command to work.
I think you need to spend some time learning some Linux basics. Important places to focus are user permissions. Here is one though I’ve not gone through it so can’t vouch for the quality.

It isn’t clear from your description, but it seems like you have a misunderstanding about how users work and what ssh does. Your description of what you are trying to do and what you have done is a little jumbled and hard to follow. But here are a couple facts about Linux that appear to be unclear for you:

  • Each of your RPis have their own set of users and configurations. Changing sudoers to give openhab permission to run a command on one machine A does not give the openhab user permission to do anything on machine B. In fact, machine B doesn’t even have an openhab user.
  • When you ssh from machine A to machine B, you have entered a shell running on the other machine B. So only the users, files, and configuration that exist on machine B are available to you.

Your Things are ssh’ing to machine B as user pi. If you want to execute a command, then you need to give user pi the permissions in the sudoer’s file on machine B.

This is probably where you have gone wrong. There is no openhab user on the 2nd Pi. And even if there were, you are ssh’ing to user pi so all the commands are running as user pi. User pi needs to be given those permissions on the 2nd Pi.

Finally, I’ll mention that openHAB is really not the best tool to do this sort of thing. There are tools that are actually designed to monitor and help you administer running services on all of your machines.

Hi @rlkoshak, thanks for the feedback, gives me a few ideas I can try over the next few evenings. Also thanks for the Linux tutorials, I’ll hopefully get some free time to go through them.