A Raspberry Pi 3

Raspberry Pi (aka rpi) is a nice little thing. It is cheap, runs debian from an SD card. Doing anything on it is fast and easy, as long as you don’t use it as a headless device.

Headless devices are those devices which don’t have peripherals like monitor, mouse or keyboard attached. They essentially are at their bare minimum: Power and Networking. (These can run lightweight distros without GUI). The only way of accessing these machines is through a serial-to-usb adapter or ssh. Particularly, access through ssh presents its own problems.

How would you shutdown your headless rpi without network connectivity?

There is an entire thread on reddit dedicated to shutting down headless pi’s. Most of the answers revolve around attaching a button to GPIO or buying an addon board. There are quite a lot of solutions involving buying stuff.

Am I going to buy stuff?

No way!

Once upon a time, Stefan Tomanek wrote something named triggerhappy. In his words,

Triggerhappy is a hotkey daemon developed with small and embedded systems in mind, e.g. linux based routers. It attaches to the input device files and

interprets the event data received and executes scripts configured in its

configuration.

Just give me the steps already!

To shutdown the pi, we are going to plug in a mouse into the pi’s USB and right click. We will configure triggerhappy daemon to listen for this event and call the shutdown command.

Find the event code of trigger

Connect your mouse (or any other input device) to rpi. Find out the event name of your click/tap by running thd --dump /dev/input* . This should list the events related to your click. In my case, it was BTN_RIGHT 1 for mouse right button down and BTN_RIGHT 0 for button up.

Create the shutdown script

Make a file /etc/trigger.sh with

#!/bin/bash # Announce to all terminals

wall 'A mouse forced me to shut down' # The actual shutdown command. sudo is used because shutdown

# needs root previlages

sudo /sbin/shutdown now

Make the script executable

sudo chmod +x /etc/trigger.sh

Create the triggerhappy config file

Create a file /etc/triggerhappy/triggers.d/mouse-poweroff.conf with the following contents. (Replace BTN_RIGHT with your trigger event code from the first step)

BTN_RIGHT 1 /etc/trigger.sh

Restart triggerhappy

sudo systemctl restart triggerhappy.service

Roadblock!

Well, isn’t it supposed to work already? Nope.

triggerhappy, executes our script as a user called nobody . According to wikipedia,

In many Unix variants, “nobody” is the conventional name of a user account which owns no files, is in no privileged groups, and has no abilities except those which every other user has. Some systems also define an equivalent group “nogroup”.

The shutdown command needs root previlages to actually power off the pi. nobody actually cannot execute any command with superuser privilages. We are going to bypass that now. We need to allow user nobody to execute shutdown with sudo without requiring password.

Now, sudo visudo will open an editor to edit the sudoers file. Append the following at the end, save and exit.

# We add echo command for testing. Remove later

nobody ALL =NOPASSWD: /bin/echo*,/sbin/shutdown*

Warning: This is not a clean or secure way, since we are granting permission for nobody to shutdown your pi.

To see if it works, sudo su -s /bin/bash nobody from your current user and check if you can sudo echo 'hello world' as nobody .

And we’re done.

Attach the mouse to your rpi, right click and watch the rpi turn off.