5. Clients setup, creation of the root filesystem

Tired? No you're not. Remember you're a hero. Here comes the tricky part. We will (err... you will) build the client's root filesystem. This shouldn't be very hard, but you probably will have to use trial and error.

The simplest way to create a root filesystem is to use an already working filesystem and customize it for the needs of diskless operation. Of course, you can also build one by hand (like in the good old times) if you like:=), but I won't explain this here.

5.1. Creating the first files and directories

First, cd to your future station's root directory. You can safely create the future /home directory with the mkdir command, or by copying it from anywhere you want (you can use cp -a to do a recursive copy preserving owners, groups, symlinks, and permissions). Same thing for the future /mnt, /root, /tmp (don't forget to chmod 0 it, this is only a mount point for the actual /tmp we will use, because each workstation needs to have its own /tmp). Then, copy some existing /bin, /sbin, /boot, and /usr into this future root directory (use cp -a). You can create the /proc directory with mkdir, and chmod 0 it. Note some applications need write access to their user's home directory.

The /lib directory can be safely copied from somewhere else, but you will have to put the proper modules in it. To do so, use the following commands (assuming you have compiled the kernel for your clients on the server in /usr/src/linux, and the root filesystem will reside in /nfsroot):
        # cd /usr/src/linux
        # make modules_install INSTALL_MOD_PATH=/nfsroot
      

Don't forget to put the System.map file in /nfsroot/boot. A first problem we will have to fix is that, depending on your configuration, your system may try to run fsck on the root filesystem at boot time. It shouldn't if there is no hard drive in the box. Most distributions will also skip this fsck if they find a fastboot file in the root directory. So, issue the following commands if you do not plan to mount any hard drive:
        # cd /nfsroot
        # touch fastboot
        # chmod 0 fastboot
      
Another method is tell fsck that checking a NFS filesystem always succeeds:
      # cd /nfsroot/sbin
      # ln -s ../bin/true fsck.nfs
    

The /dev directory can also be safely copied from another place into /nfsroot. But permissions and symlinks have to be preserved, so use cp -a. Another solution is to use kernel 2.2.x devfs feature, which will reduce memory consumption and improve performance, but the drawback of this method is that all symlinks created in /dev will be lost. The point to remember is that each workstation needs to have its own /dev, so you will have to copy it on a ramdisk if you plan to use several clients and not to use devfs.

5.2. The /var and /etc directories

We will use ramdisks for these directories, because each client needs to have its own one. But we still need them at the beginning to create their standard structure. Note you are not required to do so if you use a single client. So copy these directories (cp -a) from another place into /nfsroot. Then you can make some cleanup in /var: you can remove everything in /nfsroot/var/log and /nfsroot/var/run. You also probably can remove everything in /nfsroot/var/spool/mail, if you plan to export it via NFS. You also will have to remove the files containing host specific information in /nfsroot/etc to build them on the fly during the boot process.

The startup scripts will have to be customized in order to mount some parts of the filesystem: the /dev directory, if you don't use devfs, the /tmp, the /var, and the /etc directories. Here is some code which will achieve this:
        # this part only if you don't use devfs
        mke2fs -q -i 1024 /dev/ram0 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram0 /dev
        # this part for everyone
        mke2fs -q -i 1024 /dev/ram1 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram1 /tmp
        chmod 1777 /tmp
        cp -a /etc /tmp
        mke2fs -q -i 1024 /dev/ram2 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram2 /etc
        find /tmp/etc -maxdepth 1 -exec cp -a '{}' /etc ';'
        mount -f -t ext2 -o rw,suid,dev,exec, \
            async,nocheck,remount /dev/ram2 /etc
        mount -f -o remount /
        cp -a /var /tmp
        mke2fs -q -i 1024 /dev/ram3 16384
        mount -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram3 /var
        find /tmp/var -maxdepth 1 -exec cp -a '{}' /var ';'
      

If you plan to use more than a single client, you will also have to change files dynamically at boot time in /etc: the files which contain the IP and hostname of the client. These files depend on your distribution, but you will easily find them with a few greps. Just remove client-specific information from them, and add code into your startup files to generate this information again at boot time but only once the new /etc has been mounted on the ramdisk! A way to obtain your IP address and hostname at bootup is the following (if you have the bootpc package installed on the workstations'filesystem):
        IPADDR="$(bootpc | awk '/IPADDR/ \
                                {
                                  match($0,"[A-Za-z]+")
                                  s=substr($0,RSTART+RLENGTH)
                                  match(s,"[0-9.]+")
                                  print substr(s,RSTART,RLENGTH)
                                }
                               ')"

        HOST="$(bootpc | awk '/HOSTNAME/ \
                              {
                                match($0,"[A-Za-z]+")
                                s=substr($0,RSTART+RLENGTH)
                                match(s,"[A-Za-z0-9-]+")
                                print substr(s,RSTART,RLENGTH)
                              }')"

        DOMAIN="$(bootpc | awk '/DOMAIN/ \
                                {
                                  match($0,"[A-Za-z]+")
                                  s=substr($0,RSTART+RLENGTH)
                                  match(s,"[A-Za-z0-9-.]+")
                                  print substr(s,RSTART,RLENGTH)
                                }')"
      
This is a complicated solution, but I guess it should work on most sites. The IP address can alternatively be obtained with the output of ifconfig and the hostname can be obtained from the output of the host command, but this is not portable, because these outputs differ from system to system depending on the distribution you are using, and the locales settings.

Then, the hostname should be set with the hostname $HOSTNAME command. When this is done, it is time to generate on the fly the configuration files which contain the IP address or the hostname of the client.

5.3. Last details

Now, it's time to do the fine tuning of the client. As /var will be mounted on a ramdisk (unless you have a single client), you will have to send the logs to a logs server if you want to keep them. One way to do that is to delete the /nfsroot/etc/syslog.conf file and replacing it by the following file (see man syslog.conf for details):
        *.*     /dev/tty12
        *.*     @dns or IP of the logs server
      
If you do so, the logs server will have to run syslogd with the -r option (see the syslogd manual page).

If you use logrotate and you have done the preceding operation, you should replace the logrotate configuration file (/etc/logrotate.conf on most boxes) by an empty file:
        # rm -f /etc/logrotate.conf
        # touch /etc/logrotate.conf
      
If you don't use it, just remove the logs rotation scripts from the crontab, and as you no longer have log files in /var/log, put an exit 0 at the beginning of your logs rotation scripts.

In the /nfsroot/etc/fstab file, remove anything related to the hard drive, floppy disk reader, or cdrom if you don't have such devices on your workstations. Add an entry for the /var/spool/mail directory, which should be exported by the server through NFS or any other network filesystem. You probably also want to put an entry for the /home directory in this file.

You can also comment the lines running newaliases, activating swap, and running depmod -a and remove the /nfsroot/etc/mtab file. Comment out the line(s) removing /fastboot, /fsckoptions, and /forcefsck in your startup scripts. Also remove or comment any line in the startup scripts that would try to write on the root filesystem except for really necessary writes, which should all be redirected to some ramdisk location if you use several clients.

5.4. Trial...

Time has come for a small trial. MAKE A BACKUP OF YOUR NEWLY CREATED /nfsroot. tar -cvvIf should do fine. Take a minute to verify we didn't forget anything. Try to boot a client.

5.5. And Error!

Look carefully at the client's screen during the boot process. Oh, I didn't tell you to connect a screen... Run, forest! Run an get one. You will probably see some error messages. Fix the problems, and make frequent backups of your /nfsroot. One day, the client will boot properly. This day, you will have to fix errors occurring during shutdown;=P.