Remotely control your home cluster
Page written in 2015, tested on OpenSSH v6.1

This page is a quick overview on how to control from far away your home cluster. This tutorial has two goals: Let's start.

In principle, connecting to your home computer via SSH from an outer network (say, at work) is straightforward: just insert the home computer IP! If you think about it a little more, you will note that it's not that trivial..

First: connecting to a computer "hidden" behind a router is not very simple and typically implies tweaking around with your router to enable port forwarding (we'll avoid this)
Second: by contract, your Internet Provider is probably assigning you a dynamic IP address, that can change anytime.

One way to overcome those difficulties is having access to a machine on the internet with a static IP address. This machine will be our reference point: we'll connect the cluster to it and then we'll access the cluster through it from wherever we are.
Here's the situation: you are C, eating an excellent Kebab in Milan, your cluster A is at home and you own a machine B (say a Virtual Private Server) with a static IP somewhere in the world. I own a small Virtual Private Server at OVH and pay only a couple of euros/month for it.

The goal is connecting from C to A, but then again, how do we penetrate the router? A solution is setting an SSH tunnel from A to B (I suppose you have access to your home cluster from time to time, so you can set a tunnel and it will be persistent in time): after doing that, you can connect from any machine to B and tunnel your connection directly to A! Got it?

Let's now create a simple tunnel. From A connect to B with:
clusteruser@cluster:$ ssh -R 8888:localhost:22 serveruser@

The previous command, executed from A, specifies that port 8888 of the remote server is to be forwarded to port 22 on localhost (port associated to SSH). Here, serveruser is a user on the server and is the remote server's address.

Once it's done, your tunnel is established and you can connect to your cluster from host C (say, your laptop) in two steps: first of all connect to your server B
you@laptop:$ ssh serveruser@

and now from within B, connect to A exploiting the tunnel:
serveruser@server:$ ssh -p 8888 clusteruser@localhost

Pretty simple, right? The last command connects via SSH to port 8888 on localhost, at user clusteruser (that is present on your cluster). Of course there are more options allowing for example to run the tunnel in background. Also, one can set keypairs to enable passwordless login and call SSH from a chron job, so that if connection fails for some reason, it can be resumed.

Ready for part II? Once you are connected to the master node, you could exploit wake-on-lan technology to get every node up.. I've followed another way and built a very simple device to physically switch on the nodes.
Please note that I take no responsibility for whatever damage you may cause to your computer or yourself.

This circuit works with the parallel port and simply switches on some relais that I've found upon an old board. The transistors are needed since the parallel port is meant to transmit signals, not power, so it's thiny current must be amplified. Transistors act as switches that let current flow across relais when switched on.

My transistor is a TIP29B, but also BD139 or BD239 should work. Diodes 1N4002 to 4007 will do the work and are needed to avoid a voltage peak when the coil current is shut-off. The 220 ohm resistor is basically a protection for your LPT port.

Here's a dirty assembly with 3 relais.

You only have to connect the circuit to your master node power supply (12V is yellow cable, while red is 5V) and connect the rele' free pins to the power-on pins of computers to be awaken. Those pins will be shorted when the rele' is on and nodes will boot.

Here's a little C program that I've written to control the device above. The program switches on a specified pin (and thus a rele') for a certain time. It must be called with 2 arguments:
#include <stdio.h> #include <stdlib.h> #include <sys/io.h> // low level operations #include <unistd.h> // geteuid() #define PORTA 0x378 // LPT address main(int argc, char *argv[]) { if(geteuid()) // Returns value greater than 0 if user is not root { printf("Error: must be root!\n"); exit(1); } // Check number of passed parameters and prints usage if(argc < 3) { printf("\nUsage: prog <b|l> <1|2|..|8>\n"); printf(" b -> brief pulse\n"); printf(" l -> long pulse\n"); printf(" number -> destination pin"); printf("\n"); exit(1); } // Variables.. int pin_dec_val; // pin value in decimal int time_on; // on time // Assign value to pin_value_decimal accordingly to input if(*argv[2] == '1') pin_dec_val = 128; else if(*argv[2] == '2') pin_dec_val = 64; else if(*argv[2] == '3') pin_dec_val = 32; else { printf("Pin value not recognized.\n"); exit(1); } // Assign value to time_on accorgingly to input if(*argv[1] == 'b') time_on = 500000; // 0.5s else if(*argv[1] == 'l') time_on = 10000000; // 10s // Activating for required time ioperm(PORTA, 1, 1); // gives permissions to the program outb(0, PORTA); // just switching off printf("\nActivating port..."); outb(pin_dec_val, PORTA); usleep(time_on); outb(0, PORTA); printf(" done. Now port is off again.\n\n"); ioperm(PORTA, 1, 0); // removing permissions from program }
Note that when the master node switches on, there's a small amount of time in which the parallel port is up, so attached computers will switch on too, but since the master is supposed to be on all the time, this won't be an issue.