In my ongoing effort to make my lazy client work I’ve embarked on the next phase of the project: Making a client boot from a generic NFS mounted root partition and then giving it its own /etc on a ramdisk.

This way I’m saving disk space and administration overhead on my server. The virtual /etc is provisioned by cfengine. This allows for small changes between the lazy clients while they still share the bulk of the rest of the files.

In Debian and Ubuntu the first script that is started when init is booting is:

# grep sysinit /etc/inittab
si::sysinit:/etc/init.d/rcS

/etc/init.d/rcS. This will be a good starting point to make a ramdisk and copying /etc over to the ramdisk and then restarting the boot-up.

The script itself is small:

#! /bin/sh
#
# rcS
#
# Call all S??* scripts in /etc/rcS.d/ in numerical/alphabetical order
#

exec /etc/init.d/rc S

Ramdisk

What is needed to make a ramdisk? I’m going to use tmpfs here. First we need an empty directory which will hold our ramdisk. As this directory is created on the shared (NFS) filesystem, we need some way to make this directory random. As this is the first script run from init it will probably have a low PID, so using $$ is not a good idea as it might be not so random. Let’s use /bin/mktemp to create a dir, mount it as a ramdisk, copying /etc over and re-mounting it over /etc. Like this

# make a unique directory
RAMDISK=$(mktemp -d -p /var/tmp ram.XXXXXX)

# mount it as tmpfs disk
/bin/mount -t tmpfs tmpfs $RAMDISK

# next copy /etc over
/bin/cp -rap /etc $RAMDISK

# mount this "new" disk UNDER /etc
/bin/mount -o bind $RAMDISK /etc

The final script When putting this together the following SHOULD work. I say should here, because I haven’t tested this (yet).

#! /bin/sh
#
# rcS
#
# Call all S??* scripts in /etc/rcS.d/ in numerical/alphabetical order
#

# make a unique directory
RAMDISK=$(mktemp -d -p /var/tmp ram.XXXXXX)

# mount it as tmpfs disk
/bin/mount -t tmpfs tmpfs $RAMDISK

# next copy /etc over
/bin/cp -rap /etc $RAMDISK

# mount this "new" disk UNDER /etc
/bin/mount -o bind $RAMDISK /etc

# start the rest 
exec /etc/init.d/rc S

Somewhere in the boot process cfengine comes along and will configure this host. The only thing needed for that is that cfengine needs to know which host it is configuring. One idea could be to put the IP number of a host in /proc/cmdline and then have a module look at the file.

If this works then cfengine can work its magic.

Links Other postings about this subject:

Update

It works! More postings on this later