When FreeBSD 5.2.1 appeared, the differences in diskless operations from
branch 4.x were so great that the handbook needed revising. That correction
occurred recently, so the ISO image of the FreeBSD-5.2.1-Release, written on
25.02.2004, included the obsolete version, which applied to FreeBSD-5.1 (at
best). Besides, the guide doesn't cover everything; the steps to build the
system server-diskless stations are a maze of variants of
realizations, technologies, and descriptions of differences between FreeBSD
versions.
While trying not to miss the multitude of the possibilities, I've concentrated on only one method to install FreeBSD-5.2.1-Release as a server for diskless clients. For the sake of precision, I have illustrated the process with a concrete example.
As I've confined myself to a single alternative, it's important to lay out some conditions. First, the method here differs from the canonical version in the way it uses rc files in the FreeBSD distribution. For example, diskless stations won't put their file systems in virtual memory; instead, they will use NFS to mount file systems as read-only (/ and /usr) and read-and-write (/etc and /var).
Second, I'll use FreeBSD-5.2.1-Release server for the entire process, along with the following software:
If I don't specify otherwise, install the software from ports.
|
Related Reading
BSD Hacks |
The diskless stations will use the address pool of 192.168.1.10 through 192.168.1.254. The hostname will follow the format "diskless-<the-last-IP-address-octet>", so the hostname "diskless-101" refers to the test diskless workstation (Intel Pentium-90, 16Mb RAM, LAN Intel EtherExpress-100 PXE) with IP address 192.168.1.101/24. I'll used this station for all examples.
The main point of the problem is to send a FreeBSD kernel over the network to the computer while it boots. The handbook mentions two ways to do it:
net/etherboot and net/netboot) and the web sites of
developers.Both PXE and Etherboot use BOOTP or DHCP to receive information about
network addresses. The difference between the two is that PXE uses TFTP to fetch
a much smaller program for pxeboot, which then itself loads the kernel by NFS
or TFTP, while Etherboot uses TFTP or
NFS uploads and boots the kernel from the server.
Nowadays, it's easier to buy a new net card supporting the PXE specification than it is to burn PROM into an old adapter, so I'll skip the methods to boot diskless clients using Etherboot or Netboot. I'll only say that it's far easier to set up Etherboot then Netboot for loading the FreeBSD kernel. PXE is the easiest of all, because it doesn't need any additional software.
When loaded on a diskless station, a FreeBSD kernel mounts the root file
system on the resource of NFS-server and calls /sbin/init (or a
likely substitute, such as init.bak, oinit, or
sysinstall), mounts devfs on /dev, executes the
/etc/rc script, and forks a getty process for each
relevant terminal device listed in /etc/ttys.
The script /etc/rc, which finishes the booting procedure and starts the main system daemons, is worth mentioning. This script is important for this variant of diskless booting for one more reason. While running /etc/rc, the system needs to substitute one of the diskless client's file systems.
For the sake of saving space on the server hard drive, I've decided to share the root file system for all the diskless clients. That's why it's more reasonable to mount it read-only. As an unfortunate result, /etc will be the same for all of the diskless stations and accessible only for reading. In order to provide the flexibility of creating individual /etc directories for every client, I placed a special operation in /etc/rc to mount the stations' /etc in read-write mode.
It's possible to do the same with the default FreeBSD rc scripts, though they'll store /etc in virtual memory. This isn't very good, in my opinion, because the RAM is doubtless the main and often scarce resource for all diskless stations. That's why I used a different approach. For more information, see the scripts /etc/rc.d/initdiskless and /etc/rc.d/diskless.
Installing a diskless station itself requires little effort and only consists
of mounting a PXE-supported network card into the computer case. Then, in
accordance with the particular station equipment, you have only to choose the
right order of the booting--"boot from LAN," in our case, either in the
computer's BIOS in the menu of the LAN adapter itself. On the test station,
where the BIOS didn't support booting from LAN, I had to do the configuration
through the menu of the network adapter. In order to access the menu of the
network card, I had to press Ctrl-S while booting the diskless station.
Now it's clear that the set up's principal work takes place on the server. It's time to configure the server.
To set up FreeBSD as the diskless station server requires configuring NFS, DHCP, and TFTP. The sequence of this configuration doesn't really matter, but let's follow the logic of the boot process and select this order: DHCP, TFTP, NFS.
Install the server as usual, with one small change. To place the client file systems, allocate two separate partitions, one for "reading only" and the other "reading and writing." Mount these file systems into the following directories of the root file system of the server:
/diskless_ro
/diskless_rw
In the future, the server will export these file systems with the proper permissions to the diskless clients over NFS. If you can't use these special partitions as the diskless clients file systems, don't make a mistake of putting them on the same physical file system of the server. It would be better to choose subdirectories in /usr, /home or /var. For example, if /usr and /var are different file systems on the server, the client directories can be /usr/diskless_ro and /var/diskless_rw. Such allocation of files corresponds to the NFS specification, which I'll mention again when describing the configuration of the NFS server.
The first thing required to boot a diskless workstation remotely is to supply it with the information about its IP address, subnet mask, the place of the root file system, and so on. You have a choice of a BOOTP or DHCP server.
Nowadays, BOOTP is rare in comparison with its successor DHCP, so I'll confine myself to the modern alternative. Besides, anyone interested in the configuration of the classic BOOTP server can read about it in the handbook.
For the DHCP server, I use ISC DHCP (isc-dhcp3), which also supports the
BOOTP protocol. The basic FreeBSD distribution doesn't include the ISC DHCP, so
I installed it from ports. The installation usually resembles:
server# cd /usr/ports/net/isc-dhcp3 && make install clean
Every diskless client will have NFS shares for writing, so it doesn't make sense to change IP addresses from time to time. In the DHCP server configuration, disable dynamic IP address distribution. Instead, use DHCP in the BOOTP mode (DHCP for BOOTP clients, in the terminology of ISC DHCP).
The main configuration of the DHCP server lives in the file /usr/local/etc/dhcpd.conf. Edit this file in order to make the simple configuration. As there is only one server and one subnet, almost all of this information goes into the global parameters section:
# Server is authoritative for the subnets.
authoritative;
# Disable dynamic DNS updates.
ddns-update-style none;
# Send the client the "hostname", specified in the option
# "host" in the host declaration.
use-host-decl-names on;
# Set the default gateway.
option routers 192.168.1.1;
# The server from which to upload the initial boot-file.
next-server 192.168.1.2;
# The file to load from the "next-server".
filename "pxeboot";
# The shared root file system of diskless workstations
option root-path "192.168.1.2:/diskless_ro";
# Network definition. There are no options because of
# dynamic distribution of IP-addresses is disabled.
# But DHCP refuses to load without this line, so we
# can't remove it.
subnet 192.168.1.0 netmask 255.255.255.0 { }
# Diskless station definitions: we must specify
# hostname, IP and MAC addresses for each client
host diskless-10 {
# Hostname which will be sent to the client because of
# "use-host-decl-names on"
# Ethernet-address of the workstation LAN adapter
hardware ethernet 00:0D:9D:8B:BB:48;
# Workstation IP-address.
fixed-address 192.168.1.10;
}
...
host diskless-101 {
hardware ethernet 00:0C:29:74:2B:35;
fixed-address 192.168.1.101;
}
...
host diskless-254 {
hardware ethernet 00:02:B3:8A:D6:BF;
fixed-address 192.168.1.103;
}
Now start the DHCP server:
server# /usr/local/sbin/dhcpd
If it loads successfully, you'll see a message similar to this:
Internet Software Consortium DHCP Server V3.0.1rc12
Copyright 1995-2003 Internet Software Consortium.
All rights reserved.
For info, please visit http://www.isc.org/products/DHCP
Wrote 0 deleted host decls to leases file.
Wrote 0 new dynamic host decls to leases file.
Wrote 0 leases to leases file.
Listening on BPF/fxp0/00:0c:29:f8:78:fc/192.168.1.0/24
Sending on BPF/fxp0/00:0c:29:f8:78:fc/192.168.1.0/24
Sending on Socket/fallback/fallback-net
Run this to start DHCP at boot time:
server# cd /usr/local/etc/rc.d
server# mv isc-dhcpd.sh.sample isc-dhcpd.sh
server# chmod 755 isc-dhcpd.sh
|
There are three pieces of information that the clients need to know to download the appropriate booting code from the TFTP server:
option root-path: The location of its root file system on the
remote NFS server.next-server: The address of the TFTP server from which clients
must receive files to continue booting.filename: The name of the file to fetch from the TFTP
server.A little later, they also need the root-path option to load the
kernel and mount the root file system. For now, the PXE LAN adapter of the
station automatically tries to use two of the other parameters to continue
booting. The pxeboot(8) file is a modified version of the
loader(8), which runs on the third stage of the FreeBSD booting
process (see the handbook for more details about the boot procedure). As the
diskless client expects to fetch this program via TFTP, it must be exist on the
server at 192.168.1.2.
The FreeBSD distribution includes a TFPT server, so you do not need to
install additional software. The daemon is tftpd and usually
starts from inetd. To start TFTP server, create a special
directory of /tftpboot and copy pxeboot there:
server# mkdir /tftpboot
server# cp /boot/pxeboot /tftpboot
Add the following line into /etc/inetd.conf:
tftp dgram udp wait root /usr/libexec/tftpd tftpd -l -s /tftpboot
The -l switch turns on the logging of TFTP operations. The
-s switch specifies the root directory for tftpd
after it calls chroot(). For more details about tftpd
and chroot(), see man tftpd(8) and
chroot(2).
The server is ready to run after you restart inetd:
server# killall -HUP inetd
If everything is okay, the command
server# sockstat -4l | grep 69
will return results similar to this:
root inetd 556 5 udp4 *:69 *:*
After the client successfully downloads the pxeboot file,
according to the root-path option, it'll try to connect over NFS to
the /diskless_ro directory of the server 192.168.1.2 to find the
root filesystem with an appropriate kernel there.
You can also configure pxeboot to upload a kernel with TFTP.
This will allow you to boot different diskless stations with different kernels.
In that case, you need to recompile pxeboot with the option
LOADER_TFTP_SUPPORT=YES in /etc/make.conf. See also
the handbook and /usr/share/examples/etc/make.conf.
I confined the example network to using one kernel for all the workstations. As a consequence, I set up the NFS server to export the proper directories. As the name implies, the directory /diskless_ro should export as read-only. The diskless_rw directory contains subdirectories specific to each client for its writing. Each subdirectory must itself contain the special etc and var directories. For example, the test diskless workstation will have its own directory, diskless_rw/192.168.1.101, with two subdirectories named /diskless_rw/192.168.1.101/etc and /diskless_rw/192.168.1.101/var.
The directory /diskless_ro should be empty, while /diskless_rw contains something like:
/diskless_rw/192.168.1.10
/diskless_rw/192.168.1.10/etc
/diskless_rw/192.168.1.10/var
...
/diskless_rw/192.168.1.101
/diskless_rw/192.168.1.101/etc
/diskless_rw/192.168.1.101/var
...
/diskless_rw/192.168.1.254
/diskless_rw/192.168.1.254/etc
/diskless_rw/192.168.1.254/var
Besides these two exports, the diskless station will use /usr from the server in read-only mode.
In order to let the diskless station use all of these directories, you must configure the NFS server accordingly. Add the following lines to the file /etc/exports on the server:
# file systems accessible only for reading:
/usr -ro -maproot=0 -network 192.168.1.0 -mask 255.255.255.0
/diskless_ro -ro -maproot=0 -network 192.168.1.0
-mask 255.255.255.0
# file systems accessible for writing. All the resources
# given to every diskless station are specified by one line:
#
# Diskless-10
/diskless_rw/192.168.1.10/etc /diskless_rw/192.168.1.10/var \
-mapall=root 192.168.1.10
# ...
# Diskless-101
/diskless_rw/192.168.1.101/etc /diskless_rw/192.168.1.101/var \
-mapall=root 192.168.1.101
# ...
# Diskless-254
/diskless_rw/192.168.1.254/etc /diskless_rw/192.168.1.254/var \
-mapall=root 192.168.1.254
Then change /etc/rc.conf to start the NFS server while the system boots:
rpcbind_enable="YES"
nfs_server_enable="YES"
You may also need to change the nfs_server_flags variable:
nfs_server_flags="-u -t -n 48 -h 192.168.1.2"
The -n switch is very important here. It specifies the number
of nfsd daemons that regulate the NFS, which influences the number
of the NFS clients that can connect simultaneously. Tune this parameter
according to the number of clients. The -u and -t
switches turn on UDP and TCP. -h binds the daemon to a network
interface.
Now, start the NFS server by hand (so as not to have to reboot the server):
server# rpcbind
server# nfsd -u -t -n 48 -h 192.168.1.2
server# mountd -r
After the NFS server starts correctly, check the exported file systems:
server# showmount -e
Exports list on localhost:
/usr 192.168.1.0
/diskless_rw/192.168.1.103/var 192.168.1.254
/diskless_rw/192.168.1.103/etc 192.168.1.254
...
/diskless_rw/192.168.1.101/var 192.168.1.101
/diskless_rw/192.168.1.101/var 192.168.1.101
...
/diskless_rw/192.168.1.101/etc 192.168.1.10
/diskless_rw/192.168.1.101/etc 192.168.1.10
/diskless_ro 192.168.1.0
It is not a good idea to place diskless_rw and diskless_ro within the same physical file system because NFS doesn't export the directory but the whole file system. In /etc/exports, every line represents of the export of one server file system to one or several clients. For each exported file system, you can specify the same client only once.
For example, if diskless_rw and diskless_ro occupy different file systems, then this /etc/exports will be correct:
/diskless_rw 192.168.1.101
/diskless_ro -ro 192.168.1.101
A mistaken /etc/exports might be:
/usr/diskless_rw 192.168.1.101
/usr/diskless_ro -ro 192.168.1.101
If diskless_rw and diskless_ro are directories of
the same file system /usr, an error will occur while exporting
them to the same clients, which will prevent them from mounting
diskless_ro. The rules demand that you specify both resources,
/usr/diskless_rw and /usr/diskless_ro on one line, so
you have to decide whether to make them both accessible for reading only or for
both reading and writing.
Nevertheless, you can deceive the mountd daemon by using
IP address ranges instead of hostnames. For example, here's another mistaken
version of /etc/exports that will execute successfully:
/usr/diskless_rw -network 192.168.1.0 -mask 255.255.255.0
/usr/diskless_ro -ro -network 192.168.0.0 -mask 255.255.0.0
In this case, the server will successfully export /usr/diskless_rw and /usr/diskless_ro. As this configuration handles the whole file system and not only the directories, the subnet 192.168.1.0/24 will be able to mount both /usr/diskless_rw and /usr/diskless_ro in read-write mode, so there are security risks.
Mikhail Zakharov is presently the senior UNIX Administrator in a Moscow banks where he administers a wide spectrum of servers running various UNIX-like operating systems.
Return to the BSD DevCenter
Copyright © 2007 O'Reilly Media, Inc.