SSH Tunnel

Merle uses SSH tunneling (aka SSH port forwarding) to connect Thing to Thing Prime. The WebSocket created between Thing and Thing Prime is secure inside the tunnel; Thing Data is secure.

SSH Password-Less Setup

To create the SSH tunnel, Merle requires password-less SSH access to the Mother host (the system running Thing Prime). To setup password-less SSH, create and push keys to Mother from Thing. The steps are:

  1. On Thing system, use ssh-keygen to create a key-pair with an empty password.

  2. Use ssh-copy-id to push key from Thing system to Mother host system. (See the note about Google Cloud Platform below if you're using that service).

  3. Verify password-less SSH login is working.

The script merle/scripts/key-push will do steps 1 and 2:


if [ $# -eq 0 ]; then

echo "missing user@host"




if [ ! -f "$FILE" ]; then

ssh-keygen -t rsa -N "" -f $FILE


ssh-copy-id -i $FILE $1

Run the script and manually verify login without prompting for password:

$ ./scripts/key-push <user>@<mother host>

$ ssh <user>@<mother host>

Now Thing can connect to Thing Prime.

If Thing Prime is running in a bridge or hub or controller, then keys must be push from each Thing wanting to connect to the bridge.

📓Note for Google Cloud Platform

For GCP, ssh-copy-id will not work because GCP disallows SSH OS Login by default. The alternative to ssh-copy-id is to manually install the public SSH key into the VM's Metadata. Once the public key is installed to the VM's Metadata, verify you can SSH into Thing without a password.

Half-Dropped TCP Connections

Since SSH is built on TCP, there is this annoying problem with TCP connections where one side of the connection is dropped, but the other side doesn't know that that had happened, until there is a TCP write event at which time the other side sees the connection closed. But on a quiet Thing, there may be no data sent or received for a long time, so it will be long time before Thing Prime notices the SSH disconnect.

In Merle, we'd really like to know when a Thing disconnects, as soon as possible.

We can mitigate the problem on half-dropped TCP connections by configuring the SSH server (Mother host) to timeout disconnected SSH clients (Things). Edit /etc/ssh/sshd_config and set:

ClientAliveInterval 30

ClientAliveCountMax 4

This example will timeout connections after two minutes.


Enable HTTPS/TLS by setting a non-zero port to thing.Cfg.PortPublicTls. Port :443 is the standard HTTPS/TLS port:

thing.Cfg.PortPublicTls = 443

If enabled, Thing's web server will serve both HTTP and HTTPS. The HTTP server is only used to get the TLS certificate from Let's Encrypt before handing over to HTTPS. Now, Thing's UI accesses are secure and TLS encrypted.

📓Note: When using TLS, Thing must be accessed by Domain Name and not by IP address. Let's Encrypt will not generate a TLS certificate for an IP address. So Thing must have a Domain Name registered on the Internet when enabling TLS.

HTTP Basic Authentication

Enable HTTP Basic Authentication by setting a non-empty user name in thing.Cfg.User:

thing.Cfg.User = "merle" // Enable HTTP Basic Authentication

// for user "merle"

If enabled, HTTP Basic Authentication will prompt for user name and password before displaying Thing's UI. Thing's UI is displayed if valid credentials. The browser may cache the credentials for a bit.

Manage users and passwords on Thing using standard tools (adduser, passwd, etc).

Warning: HTTP Basic Authentication sends the credentials encoded but not encrypted. This is completely insecure unless the exchange is over a secure connection (HTTPS/TLS, see above).