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.
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.
I've tested this kernel successfully on several diskless stations.
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.
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:
server# mkdir /diskless_rw/192.168.1.101
server# mkdir /diskless_rw/192.168.1.101/etc
server# mkdir /diskless_rw/192.168.1.101/var
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:
server# mkdir /diskless_rw/192.168.1.101/etc/pam.d
server# mkdir /diskless_rw/192.168.1.101/etc/X11
server# mkdir /diskless_rw/192.168.1.101/var/home
server# mkdir /diskless_rw/192.168.1.101/var/log
server# mkdir /diskless_rw/192.168.1.101/var/run
server# mkdir /diskless_rw/192.168.1.101/var/tmp
The directory trees for /etc and /var on the test diskless workstation will be:
/diskless_rw/192.168.1.101
/diskless_rw/192.168.1.101/etc
/diskless_rw/192.168.1.101/etc/pam.d
/diskless_rw/192.168.1.101/etc/X11
/diskless_rw/192.168.1.101/var
/diskless_rw/192.168.1.101/var/home
/diskless_rw/192.168.1.101/var/log
/diskless_rw/192.168.1.101/var/tmp
/diskless_rw/192.168.1.101/var/run
Unfortunately, the code for passing the kernel information about the swapfile through BOOTP no longer exists in FreeBSD. Instead, place each client's swapfile within its filesystem:
dd if=/dev/zero of=diskless_rw/192.168.1.101/swap bs=1k
count=32000
Repeat this operation on every diskless workstation. We'll speak later about the file contents of all these directories as well as how to ensure that /etc and /var work properly.
The directory diskless_ro will host the diskless station's root filesystem. It will contain the directories bin, boot, dev, etc, lib, libexec, mnt, sbin, usr, and var.
The directories bin, lib, libexec, and sbin contain the main FreeBSD libraries and programs. We'll take them from the server filesystem without modifying them:
server# cp -r /bin /lib /libexec /sbin /diskless_ro
Create the directory usr to mount the directory /usr from the server later:
server# mkdir /diskless_ro/usr
Now we must prepare the diskless station /boot directory and put
the kernel there. We'll make it by copying the boot directory of the
server and there copying the compiled DISKLESS kernel:
server# cp -r /boot /diskless_ro
server# cp /sys/i386/compile/DISKLESS/kernel /diskless_ro/boot/kernel
When I used this configuration I had problems booting some workstations. I
solved this on some computers by removing boot4th and creating my
own loader.rc. If you are ready to do the same, then use:
server# cd /diskless_ro/boot
server# rm *.4th
Without boot4th there's no automatic loading of
device.hints. You have two ways to fix the problem:
device.hints into the kernel. See hints
GENERIC.hints in the GENERIC kernel example.loader.rc instead of device.hints.Old equipment isn't very reliable, and sometimes it takes too long to configure. To be more flexible configuring the kernel, I used the second approach on the test station.
As the values in device hints are common kernel variables, it's possible to
include them as set variable="value" into the
loader.rc file. An example loader.rc will look
like:
set hint.fdc.0.at="isa"
...
boot /boot/kernel/kernel
The last line of loader.rc specifies which kernel to load.
I think it's more efficient to compile loader.rc this way and
then remove spare kernel variables:
server# cd /diskless_ro/boot
server# awk '{print "set "$1}' device.hints > loader.rc
server# echo "boot /boot/kernel/kernel" >> loader.rc
I used this loader.rc.
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:
server# cd /diskless_ro
server# ln -s /var/tmp .
server# ln -s /var/home .
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:
server# mkdir /diskless_ro/etc
server# cp /etc/services /etc/netconfig /etc/login.conf /diskless_ro/etc
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:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin; export PATH
boot_ip=`kenv boot.netif.ip`
mount -t nfs 192.168.1.2:/diskless_rw/${boot_ip}/etc /etc
mount -t nfs 192.168.1.2:/diskless_rw/${boot_ip}/var /var
swapon /var/swap
rm -rf /var/tmp/*; rm -rf /var/tmp/.*;
. /etc/rc2
exit 0
This simple script executes the following actions:
PATH to specify the path to the
executable files.boot_ip variable.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.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.
|
By placing the required files in the /diskless_rw/workstation-IP
address/etc and editing the file rc2 there, we can
configure each station by its IP address. To continue booting, the station will
need the following files in this directory:
auth.conf
disktab
fstab
gettytab
group
hosts
login.access
login.conf
login.conf.db
master.passwd
netconfig
protocols
pwd.db
rc
rc2
services
spwd.db
syslog.conf
termcap -> /usr/share/misc/termcap
ttys
You can copy almost all of these files from the server directory /etc to /diskless_rw/192.168.1.101/etc without changes. There are only a few exceptions:
fstab will need editing, as all the client's filesystems will use
NFS.rc is already written and must come from
/diskless_ro/etc.rc2 will contain commands and daemons particular to each
diskless station.syslog.conf will configure the system logs.ttys will need changing if you want to use
internationalization on the system.Let's begin with fstab for the station with IP address
192.168.1.101.
The script /etc/rc is in the root filesystem of the diskless
client, so:
server# cp /diskless_ro/etc/rc /diskless_rw/192.168.1.101/etc
Then edit rc2:
#!/bin/sh
mount -a /sbin/ldconfig -elf /usr/lib/compat /usr/X11R6/lib /usr/local/lib
syslogd
exit 0
This script executes the following actions when booting diskless clients:
syslogd daemonNow create the configuration for syslogd. To this effect, edit
/etc/syslog.conf of the diskless client. For example, the test
workstation will use the file
/diskless_rw/192.168.1.101/etc/syslog.conf. There are plenty of
alternatives. In one, syslogd will send all system logs to the
server 192.168.1.2:
*.* @server
If you do this, make sure to load the daemon with the -a option
pointing to the server 192.168.1.2. For example:
syslogd -a 192.168.1.0/24
Another option is to have syslogd send all logs to
/var/log/all.log on its own filesystem:
*.* /var/log/all.log
If you choose this approach, be sure to create the file /var/log/all.log with proper permissions beforehand:
server# touch /diskless_rw/192.168.1.101/var/log/all.log
server# chmod 600 /diskless_rw/192.168.1.101/var/log/all.log
If you need to enable localization on the system, you must add a few lines
to rc2 and edit ttys. To enable the Russian language
(koi8-r), add the following commands to rc2:
kbdcontrol < /dev/ttyv0 -l "ru.koi8-r"
vidcontrol < /dev/ttyv0 -l "koi8-r2cp866"
vidcontrol < /dev/ttyv0 -f 8x16 "cp866-8x16"
vidcontrol < /dev/ttyv0 -f 8x14 "cp866-8x14"
vidcontrol < /dev/ttyv0 -f 8x8 "cp866-8x8"
and edit ttys to change all entries of cons25 to
cons25r for each virtual terminal. For example, for
ttyv0 the line will become:
ttyv0 "/usr/libexec/getty Pc" cons25r on secure
You must perform this operation on all diskless workstations. Then you can turn on your workstations and they will boot and work. There can be some hidden traps, though.
Authentication files come from the server. Now all the usernames and their
password on the server and stations are identical. If this doesn't suit you,
edit master.passwd for each workstation to remove all the spare users.
Then give root a new password and home directory. For
example:
root::0:0::0:0:Charlie &:/root:/bin/csh
toor:*:0:0::0:0:Bourne-again Superuser:/root:
daemon:*:1:1::0:0:Owner of many system processes:/root:/sbin/nologin
operator:*:2:5::0:0:System &:/:/sbin/nologin
bin:*:3:7::0:0:Binaries Commands and Source:/:/sbin/nologin
tty:*:4:65533::0:0:Tty Sandbox:/:/sbin/nologin
kmem:*:5:65533::0:0:KMem Sandbox:/:/sbin/nologin
games:*:7:13::0:0:Games pseudo-user:/usr/games:/sbin/nologin
news:*:8:8::0:0:News Subsystem:/:/sbin/nologin
man:*:9:9::0:0:Mister Man Pages:/usr/share/man:/sbin/nologin
sshd:*:22:22::0:0:Secure Shell Daemon:/var/empty:/sbin/nologin
smmsp:*:25:25::0:0:Sendmail Submission User:/var/spool/clientmqueue:/sbin/nologin
mailnull:*:26:26::0:0:Sendmail Default User:/var/spool/mqueue:/sbin/nologin
bind:*:53:53::0:0:Bind Sandbox:/:/sbin/nologin
uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
pop:*:68:6::0:0:Post Office Owner:/nonexistent:/sbin/nologin
www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/sbin/nologin
nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/sbin/nologin
test:$1$nkgb9jxT$a5ZgR4DUgOIUJGBg3.gJr.:1001:1001::0:0:test:/home/test:/bin/sh
Remember to rebuild the password database:
pwd_mkdb -d /diskless_rw/192.168.1.101/etc /diskless_rw/192.168.1.101/etc/master.passwd
Edit the file etc/group (for example, /diskless_rw/192.168.1.101/etc/group), and then create home directories for the rest of the users in the directory var/home (/diskless_rw/192.168.1.101/var/home).
Now, as we have configured our system to keep user home directories in the filesystem of each diskless station (directory /var/home and soft link /home to /var/home), a user who has changed stations can't access his files from his previous computer. To solve the problem, export the server's /home to all the diskless stations. For example, add this line to the server's /etc/exports:
/home -network 192.168.1.0 -mask 255.255.255.0
Thus, add this line to fstab on each station:
192.168.1.2:/home /home nfs rw 0 0
Finally, don't forget to change the link from /home to /var/home for the real directory /home:
server# cd /diskless_ro
server# rm home
server# mkdir home
Remember, though, that exporting the home directories of all users can be dangerous.
If you need the X Window system, you have two options:
startx and run X on the diskless station
only.xdm and use the server resources.Both alternatives will require you to load the moused daemon to
enable the mouse. For a test workstation with a mouse connected to the COM2
port, invoke moused with:
/usr/sbin/moused -p /dev/cuaa1 -t auto
As mice can connect to different COM ports on different stations, you need to change this command for each diskless client and put it into /etc/rc2 in order to load it at boot time.
startx ApproachThe first alternative installs X on the server in a common way. Every
diskless client has its own XF86Config file (in the /etc/X11
directory). Thus the test station with IP address 192.168.1.101 has a file on the
server in /diskless_rw/192.168.1.101/etc/X11. In this case, running
startx on the client starts X.
If you also need access to a Microsoft Windows Terminal Server, install
rdesktop on the server in order to support the RDP protocol:
server# cd /usr/ports/net/rdesktop
server# make install clean
To start rdesktop automatically when loading the X Window
System, create the file .xsession or .xinitrc in the home
directory of all users on all diskless stations. Add to it this line:
rdesktop -f mswinserver
Here the key -f specifies the use of full-screen mode.
mswinserver is a hostname or an IP address of the Microsoft Windows
Terminal Server.
xdm ApproachThe second way to configure X uses the XDMCP protocol. It's more suitable when many users need access to the Unix server to run graphical programs. This approach also uses the XF86Config file, but it requires additional server configuration.
Create the file /usr/X11R6/lib/X11/xdm/xdm-config similar to:
DisplayManager.errorLogFile: /var/log/xdm.log
DisplayManager.pidFile: /var/run/xdm.pid
DisplayManager.keyFile: /usr/X11R6/lib/X11/xdm/xdm-keys
DisplayManager.servers: /usr/X11R6/lib/X11/xdm/Xservers
DisplayManager.accessFile: /usr/X11R6/lib/X11/xdm/Xaccess
DisplayManager.willing: su -m nobody -c /usr/X11R6/lib/X11/xdm/Xwilling
DisplayManager*authorize: true
DisplayManager*resources: /usr/X11R6/lib/X11/xdm/Xresources
DisplayManager*session: /usr/X11R6/lib/X11/xdm/Xsession
DisplayManager*authComplain: true
The Xservers file will be empty; Xaccess will contain only a single
*, which permits all hosts to connect to xdm to
receive the log-in screen. Finally, load xdm with the command:
server# xdm
To start xdm at boot time, place this call in a script named
xdm.sh and place it in the server's /usr/local/etc/rc.d directory.
After xdm has successfully started on the server, you can run X
server on the clients. For example:
diskless-101# X -query 192.168.1.2
If you need to load X at boot time, place this command in the
rc2 script for each diskless client:
X -query 192.168.1.2 &
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.