autossh, systemd, and a Raspberry Pi


  • Thu 17 August 2017
  • misc

I recently had occasion to build a Raspberry Pi to leave sitting on someone else's network, ssh home with a bunch of tunnels configured, and keep things nailed up "forever".

Unfortunately headless initial configuration (i.e. turning on sshd without needing to be hooked up to video and mouse) does not appear to be a thing on my favorite tiny ARM board distro so I went with raspbian-jessie-lite (edition of 2017-07-05) since getting Raspbian running headless has a well-understood procedure.

I gave Jamie a holler because I couldn't remember the name of the program that we'd used before as a wrapper to keep ssh running. He reminded me - it's called Autossh.

You can tell by the design characteristics of that page that autossh goes back a number of years. Indeed, it turns out that a lot of the functionality of autossh has been overcome by time and features in openssh. For instance the "-M" flag that periodically checks connectivity with a tromboned message over two more ssh channels has effectively been eclipsed by "-o ServerAliveInterval=x -o ServerAliveCountMax=y" and allowing the ssh process to die and be restarted by autossh. Indeed, this is in their README now.

With the advent of modern replacements for rc.local, rc.d, and the like such as launchd, smf, and everyone's favorite johnny-come-lately second-system-syndrome poster child, systemd, the core functionality of autossh (refork process when child dies) has been eclipsed by the startup manager as has the ability to run as a specific user rather than root as part of the startup process.

With Raspbian Jessie, we have systemd but are stuck fumbling around for the degenerate case of "how do I start-a-process-with-multiuser-as-a-dependency-and-restart-if-it-croaks" because (a) systemd is more opaque than I'd like and doesn't tell you what it's unhappy about with any degree of obviousness for a novice, and (b) the interface to systemd has morphed over the years and continues to morph.

I created non-passworded ssh keys on the Pi in ~pi/.ssh/ with {% raw %} ssh-keygen -b 4096 -f .ssh/id_rsa

Then, after some goofing around I have something that works for Raspbian at least as of July 2017. No warranty for any other platform but it may be a good starting place.

{% raw %} pi@raspi:~ $ cat autossh.service # # to install (had trouble getting it to actually start without reboot # # sudo cp autossh.service /etc/systemd/system/ ; sudo systemctl enable autossh.service ; sudo reboot

[Unit]
Description=Keep ssh tunnel to specified remote host open
After=network.target

[Service]
User=pi

ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -R2222:127.0.0.1:22 -R2223:10.1.10.99:443 -R2224:10.1.10.222:443 -R2225:10.0.10.222:443 -i /home/pi/.ssh/id_rsa user@example.com

RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target


pi@raspi:~ $

{% endraw %}

And that's it.