Using ifplugd to resolve NAS booting problems
Updated March 2013 to include configuration files for `ifplugd`.
A year or two ago, I built a small Linux server for use as a NAS (network attached storage) and router. It evolved through a number of iterations, but in its latest configuration is running a fairly vanilla Arch Linux. There was one problem that kept bugging me when I moved it to a new residence/network, though--it always refused to finish the booting process the first time that I plugged it in. Because I have it set up as a NAT router, with two ethernet ports, I would try to debug the situation by plugging my laptop into the "LAN" side port. When I did that, the machine would have no problems at all booting up. The problem was exacerbated because I ran the server headless, and it would not finish bringing up the WAN side interface before it froze, so I couldn't even open an SSH session to see what was going on.
I eventually traced the problem to a quirk of the Arch Linux boot scripts. I am using net-profiles
, so I have internal
and external
profiles in /etc/network.d
. internal
was set to a static IP address, and netcfg
wouldn't allow the boot to continue if no cable was plugged into the port for internal. This explains both the booting problem and the symptom that it would magically work after I plugged in my laptop.
By searching the Arch forums, I found ifplugd
, which automatically brings up/takes down network interfaces depending on the media presence. It's useful for laptops which have the ethernet cable frequently connected or disconnected, but it has also come in handy in my situation. Instead of letting Arch start my network interfaces automatically, I set them to use ifplugd
instead. If the media are connected at boot, ifplugd
will bring up the respective interfaces, but if (for example) the internal interface is not connected to anything, ifplugd
won't bring it up (until it is connected). This neatly solves my problem, and ifplugd is already available in Arch repository extra
. I used this this configuration, which also starts/stops dnsmasq
, a DNS/DHCP server, with the internal interface:
# /etc/ifplugd/ifplugd.conf
INTERFACES="eth0 eth1"
# Run this script when a cable is plugged/unplugged
ARGS="--run=/etc/ifplugd/net_dnsmasq.action"
Here's the action file:
# /etc/ifplugd/net_dnsmasq.action
#!/bin/bash
# $1=[eth0|eth1], $2=[start|stop]
/etc/ifplugd/netcfg.action $1 $2
NETCFG_RETURN=$?
# Start/stop dnsmasq if eth1
if [[ "$1" == "eth1" ]]; then
case "$2" in
up)
systemctl start dnsmasq
;;
down)
systemctl stop dnsmasq
;;
esac
fi
exit $NETCFG_RETURN
netcfg.action
is included with the Arch package for ifplugd
(it determines the appropriate network profile for an interface and starts/stops it accordingly). The script I wrote, net_dnsmasq.action
, is just a simple wrapper for the included netcfg.action
which starts/stops dnsmasq
as appropriate.