Building Diskless Clients with FreeBSD 5.2

Having prepared the FreeBSD
5.2 Netboot server, we can begin to configure our diskless workstations.
Let's prepare the kernel and add it to the two-part filesystem (accessible for reading only and accessible for reading and writing) and finally create
rc-scripts.

Kernel

As the previous article explained, pxeboot expects the NFS-resource at
192.168.1.2/diskless_ro to be the root filesystem, so it'll try
to find the kernel there. While booting the diskless client using pxeboot, we
could use the GENERIC kernel. GENERIC has many drivers, but there are no
useful BOOTP options for us. Instead, let's compile the DISKLESS kernel to put
on the client filesystem.

Compile the new kernel as usual, changing GENERIC and removing everything
unnecessary. Be sure to keep the following lines, though:

options NFS_ROOT
options NFSCLIENT

It's a very good thing to add the following options; they aren't in the
GENERIC kernel, but you can certainly do without them:

options BOOTP
options BOOTP_NFSROOT
options BOOTP_COMPAT

These options will cause an additional dialogue with the DHCP server to
rediscover the diskless client's IP address. Otherwise, the server cannot send
additional useful information over BOOTP such as the hostname. As the handbook mentions, you can also add the options BOOTP_NFSV3 and
BOOTP_WIRED_TO if you like.

Directory tree

The only difference between the diskless workstation and any other computer
is that the diskless client has its filesystems on the NFS resource. That's
why when it boots successfully, it's necessary to re-create a similar directory
tree with only a few changes. Having chosen the directories /diskless_ro
and /diskless_rw on the server for this task, we'll place all the
client files there.

/diskless_rw

First prepare directory_rw and put it aside. It's necessary only
at the final stage of diskless client booting.

The directory /diskless_rw holds individual filesystems for all
clients. Having set up the NFS server, these directories follow the form
/diskless_rw/workstation IP address/rw-file-system. For
example, we've created the following directories for the test diskless
client:

We'll mount the server directories /diskless_rw/workstation IP
address/etc and /diskless_rw/workstation IP
address/var as /etc and /var on the diskless
client. This naming scheme allows us to give each diskless station its
individual directories for reading and writing.

It's a good time to create more directories in /var and
/etc for later use. Run:

Now we don't need device.hints on the client filesystem any
more and can safely remove it. The defaults directory containing
loader.conf is no longer useful either, so execute the
following:

server# cd /diskless_ro/boot
server# rm -r defaults device.hints

The ACPI power-management module loads by default, but it may be useful to
disable it; sometimes diskless stations fail to boot with ACPI enabled. It can
also happen the other way around, when diskless clients can't boot without ACPI
(see acpi(4)). To disable ACPI, set the kernel variable
hint.acpi.0.disabled="1".

In device.hints, it's:

hint.acpi.0.disabled="1"

In loader.rc, it's:

set hint.acpi.0.disabled="1"

That's all for the directory /boot.

The dev directory mounts the devfs filesystem, which contains all
the device files of the FreeBSD system. Without this directory, the diskless
station will hang while loading the init process without giving an error!
So:

server# mkdir /diskless_ro/dev

Let's also take care of the free directory var to mount
/diskless_rw/var from the server 192.168.1.2:

server# mkdir /diskless_ro/var

In order not to create separate filesystems for the client's directories
home and tmp, make soft links from /home to
/var/home and /tmp to /var/tmp, which will ensure
access to the directories for reading and writing:

Then create and populate the etc directory. As it lives in the
/diskless_ro and all of the clients share it in read-only mode, it's
important to make its contents universal and compact. It will have only a few
required files. Let's take some of them (services, netconfig,
and login.conf) from the server filesystem:

We'll play a trick to give each diskless station its own individual
configuration. Considering that the init process runs /etc/rc, we'll
mount a filesystem from diskless_rw over diskless_ro/etc. To
this effect we'll create our own etc/rc in
diskless_ro/etc:

Sets the environment variable PATH to specify the path to the
executable files.

Defines the IP address received during booting and places it into the
boot_ip variable.

Uses the value of boot_ip (the client IP address) to mount
the NFS filesystems /etc and /var from the server
192.168.1.2. At this point, the directories /etc and /var,
previously accessible in read-only mode, become accessible both for reading and
writing. In this case, though, they have different files for different
stations.

Sets /var/swap as the swapfile.

Clears the directory /var/tmp and, in consequence, /tmp
because of the soft links created above.

Finally, runs the second rc-script (rc2), which continues
booting the system. Because the filesystem mounted in the directory
/etc is original for every diskless client, the script
rc2 as well as all the other files of the directory /etc
can differ. At this point we can start configuring each diskless client by
writing different commands in their rc2 files.