While the main purpose of my tiny data center at home with a NUC and a couple of Raspberry Pis is of course to host my own cloud services (such as Owncloud, Selfoss, VPN server, VNC bridge, etc. etc.), it's also a great platform to try out new things. I like redundancy, especially when I am not at home for a while and have two backhaul connections, my main one over VDSL and a backup over LTE. While I could use a single router for both options I've decided to use two separate devices for redundancy. While this covers the most likely failure scenario of the VDSL line going down for extended periods of time (which it has done several times already when I was not at home) the solution's weak point is that my servers are connected to the Ethernet ports of the VDSL routers. In case the VDSL router hardware fails, this means that I would not be able to access my devices over the fallback router anymore. I could of course also use an Ethernet switch to interconnect all my devices but that would just move the hardware failure scenario from the router to the switch.
A solution to such a failure scenario is to have two Ethernet interfaces on the devices I run services on I rely on when I'm not at home and use them to connect the devices to both routers simultaneously. Redundancy is then achieved by bonding the two Ethernet ports together and only use one at a time with automatic failover. This is called Ethernet channel bonding and Debian Linux on which both Ubuntu and Raspbian are built on comes with an easy to use channel bonding kernel module. Here's how I set it up:
The first step is to install the kernel module for the bonding drive which is done as follows on both Ubuntu and Raspbian:
sudo apt-get install ifenslave-2.6
Once done the OS has to be instructed to load the kernel module during system startup. This is done by adding a new line in the /etc/modules configuration file that says "bonding". Make sure to back up the configuration file before making the change.
sudo nano /etc/modules
insert a new line which sys "bonding"
And finally, the network interfaces have to be configured for bonding. This is done in /etc/network/interfaces and my configuration looks as follows (again, backing up the configuration file first is a good idea!):
#eth0 is manually configured, and slave to the "bond0" bonded NIC
auto eth0
iface eth0 inet manual
bond-master bond0
bond-primary eth0
bond-mode active-backup
#eth1 ditto, thus creating a 2-link bond.
auto eth1
iface eth1 inet manual
bond-master bond0
bond-primary eth0
bond-mode active-backup
# bond0 is the bonding NIC and can be used like any other normal NIC.
# bond0 is configured using static network information.
auto bond0
iface bond0 inet static
address 192.168.77.33
gateway 192.168.77.1
netmask 255.255.255.0
dns-nameservers 192.168.77.1
bond-master bond0
bond-primary eth0
bond-mode active-backup
bond-miimon 100
bond-slaves none
While the bonding driver can also combine several Ethernet interfaces for load sharing I decided to use the active-backup mode and to declare the first Ethernet interface (eth0) as primary interface. This means that the system will always choose to use eth0 as the active interface and only use eth1 when this interface goes down. As soon as eth0 comes up again the bonding driver will immediately switch back to eth0. This perfectly fits my needs as eth0 is a gigabit Ethernet interface while eth1 is only a 100 Mbit/s interface connected to the server via USB. Also, eth0 connects to my VDSL router while eth1 connects to the backup LTE router. You might have noticed that the same options are spelled out three times above which seems superfluous. However, it wouldn't work when only using them once in the configuration.
Once the interfaces have been configured it's time to do a reboot of the system and then to check if the configuration works:
Status of the bonding driver: cat /proc/net/bonding/bond0
Status of the network interfaces: ifconfig
When the bonding interface is up and reports both Ethernet ports to be up and running, each can now be unplugged without the system loosing connectivity. Status changes are reported to the system log in /var/log/syslog which is a nice way to monitor changes. Another interesting exercise is to use tcpdump on eth0 and eth1 to record network traffic into separate Wireshark pcap trace files.
For more information have a look at the following resources:
General description of how to configure channel bonding on Ubuntu.com
And two interesting descriptions on how bonding is done on RedHat and Fedora Linux. Note that different configuration files are used on those systems.
Happy bonding!
Nice solution. But – sorry for asking – isn’t that just a move of the hardware failure scenario from the router to the internal USB hub of the Raspberry Pi?
Hi Tom,
Yes, instead of the router + the internal USB hub, only the internal USB
hub is now the weak point 🙂 Ive been playing with the thought to have
a closer look at DRBD and distributing the machines to different
locations. Something for long winter evenings perhaps… Cheers, Martin