Running dhcpcd under LXC

Fri 01 February 2013 by Lars Kellogg-Stedman

I've been working with Arch Linux recently, which uses dhcpcd as its default DHCP agent. If you try booting Arch inside an LXC container, you will find that dhcpcd is unable to configure your network interfaces. Running it by hand you will first see the following error:

# dhcpcd eth0
dhcpcd[492]: version 5.6.4 starting
dhcpcd[492]: eth0: if_init: Read-only file system
dhcpcd[492]: eth0: interface not found or invalid

This happens because dhcpcd is trying to modify a sysctl value. Running dhcpcd under strace we see:

open("/proc/sys/net/ipv4/conf/eth0/promote_secondaries", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EROFS (Read-only file system)

This happens because /proc is typically mounted read-only in a container environment (to prevent the container from modifying things that would potentially affect the host system).

We can use a "bind mount" to solve this problem. A "bind mount" allows you to mount part of a filesystem on another part of the filesystem. In this case, we're going to mask that value in /proc by bind mounting a file on top of it.

  • First, we create the file we'll use as a mask:

    # echo 0 > /var/tmp/promote_secondaries
  • Then we mount in on top of the /proc entry:

    # mount -o bind /var/tmp/promote_secondaries \

And now that /proc value is "writable" from the perspective of dhcpcd. If we try to run dhcpcd now, we see:

# dhcpcd eth0
dhcpcd[770]: version 5.6.4 starting
dhcpcd[770]: eth0: sending IPv6 Router Solicitation
dhcpcd[770]: eth0: rebinding lease of
dhcpcd[770]: eth0: acknowledged from
dhcpcd[770]: eth0: checking for
dhcpcd[770]: eth0: sending IPv6 Router Solicitation
dhcpcd[770]: eth0: leased for 3600 seconds
dhcpcd[770]: forked to background, child pid 796

If you are running dhcpcd via the dhcpcd@.service unit, then you can automate this masking with the following service unit:

Description=Mask read-only /proc entries for %I.

ExecStartPre=/bin/dd if=/proc/sys/net/ipv4/conf/%I/promote_secondaries \
ExecStart=/bin/mount -o bind /var/tmp/promote_secondaries_%I \
ExecStop=/bin/unmount /proc/sys/net/ipv4/conf/%I/promote_secondaries


If you see...

/usr/lib/dhcpcd/dhcpcd-hooks/30-hostname: line 17: /proc/sys/kernel/hostname: Read-only file system may need to do something similar to mask the kernel.hostname entry in /proc, although this will need to be done once rather than per-interface. Alternatively, you can modify the hook script responsible for setting the hostname (/usr/lib/dhcpcd/dhcpcd-hooks/30-hostname).