First of all, you need to create the directory structure itself. I created all the clients under /clients/hostname and I will use it for my examples listed below. This, however, can be changed to anything else. The first stage, then, is to create the relevant directories in the root directory. You should create the following directories:
bin , dev , etc , home , lib , mnt , proc , sbin , server , tmp , usr , var
and any other directories you might want to have on your system.
The local, proc, and dev directories will be used separately on each machine while the rest of the directories will be either partly or completely shared with the rest of the clients.
Although the dev dir can be shared, it is better to create a separate one for each client. You can create your client's dev directory with the appropriate MAKEDEV scripts, however in most cases it is simpler just to copy it from the server:
bash# cp -a /dev /clients/hostname |
You should keep in mind that /dev/mouse, /dev/cdrom and /dev/modem are symbolic links to actually devices, and therefore you should be sure that they are linked correctly to fit the client's hardware.
Although we mount everything from the server, there is a minimum that we need to copy to each client. First of all, we need "init", our system will not be able to run anything before init'ing (as the author found out in the hard way ;-). So first, you should copy /sbin/init to your client's sbin dir and then so that rc.S will run, you should copy /bin/sh to the client's bin directory. Also, in order to mount everything you need to copy /sbin/mount to the client's sbin directory. This is the minimum, assuming the first line in your rc.S is mount -av. However, I recommend copying a few more files: update, ls, rm, cp and umount, so that you will have the basic tools in case the client has problems mounting. If you choose to leave your swap on line before mount, you should also copy the swapon binary.
Since most of these binaries are by default dynamically linked, you will also need to copy a fair part of /lib:
bash# cp -a /lib/ld* /lib/libc.* /lib/libcursses.* /client/hostname/lib |
Hardlinking the binaries themselves, instead of copying them, should be considered. Please read my comments on this in Section 2.1 of this Howto.
Please notice, all of the information above assumes that the kernel has been given the network parameters while booting up. If you plan to use rarp or bootp, you will probably need the relevant binaries for these as well.
Generally, you will need the minimum of files that will enable you to configure the network and run rc.S up to the point where it mounts the rest of the file system. Make sure you looked into your /etc/init and rc.S files, making sure there are no "surprises" in any of them, which will require other files to be accessed, before the first mount will take place. If you do, however, find such files, you can either copy them as well, or remove the relevant parts from your init and your rc.S files.
The var directory, in most cases, should be separate for each client. However, a lot of the data can be shared. Create under the server directory a directory called var. We will mount the server's var directory there. To create the local var directory, simply type:
bash# cp -a /var /clients/hostname/ |
Now, you have a choice as to what you want to separate, and what you want to share. Any directory/file that you want to share, simply remove it from the client's var dir, and symlink it to the /server/var/ directory. However please note that you should either symlink it to /server/var or to ../server/var but NOT to /clients/hostname/server/var as this will not work when the root changes.
Generally, I would recommend separating /var/run, /var/lock, /var/spool, and /var/log.
etc is explained thoroughly in the next section.
mnt and proc are for local purposes.
usr and home are merely mount points.
tmp is up to you. You can create a different tmp directory for each client, or create some /clients/tmp directories, and mount it for each client under /tmp. I would recommend that you provide each client with a separate tmp directory.
Please Note -
this section refers to building the etc directory which is mostly shared among the clients. If your diskless clients have separate system administrators, it's best to set up for each client a separate etc directory. |
Although we separate the etc directories of the clients, we still want to share a large portion of the files there. Generally, I think sharing the etc files with the server's /etc is a bad idea, and therefore I recommend creating a /clients/etc directory, which will hold the information needed for the clients. To start with, simply copy the contents of the server's etc to the /clients/etc directory.
You should add to this directory all of the non-machine-specific configuration files, for instance motd, issue, etc. and not the clientspecific ones.(i.e. inittab or fstab)
The most important changes will be in your rc.d directory. First, you should change rc.inet1 to be suitable for your local setup. I pass all my network parameters to the kernel through the LILO/Loadlin, therefore I remove almost everything from rc.inet1 file. The only thing I leave there is the ifconfig and route of the localhost. If you use rarp or bootp, you will have to build it accordingly.
Secondly, you should edit your rc.S. First, remove all the parts that are responsible for the fsck check as fsck will occur when the server boots up. Then, you should find the line that mounts your fstab. This should look something like:
mount -avt nonfs
The -t nonfs is there since normal clients first run rc.S and only later on use rc.inet1 to configure the Ethernet. As this will cause no NFS partitions to be mounted this line should be deleted. Therefore, change it to mount -av. If you need to run rarp/bootp to configure your network, do it in rc.S (or call the appropriate script from rc.S), before the mount, and make sure your physical bin and sbin directories have the necessary files available.
After the mount -av is performed, you will have a working file system. Build a general fstab, so that you can later copy it to each client. Your fstab should look something like this:
Table 1. fstab
server:/clients/hostname | / | nfs | default | 1 | 1 |
server:/bin | /bin | nfs | default | 1 | 1 |
server:/usr | /usr | nfs | default | 1 | 1 |
server:/sbin | /sbin | nfs | default | 1 | 1 |
erver:/home | /home | nfs | default | 1 | 1 |
server:/lib | /lib | nfs | default | 1 | 1 |
server:/clients/etc | /server/etc | nfs | default | 1 | 1 |
server:/clients/var | /server/var | nfs | default | 1 | 1 |
none | /proc | proc | default | 1 | 1 |
Please notice, that the keyword default might not work on all versions of mount. You might change it to rw
or ro
or remove all of the default 1 1
part.
Also, make sure your server's /etc/exports looks like this:
Table 2. /etc/exports
/clients/hostname | hostname.domainname(rw,no_root_squash) |
/clients/etc | hostname.domainname(ro,no_root_squash) |
/clients/var | hostname.domainname(ro,no_root_squash) |
/usr | hostname.domainname(ro,no_root_squash) |
/sbin | hostname.domainname(ro,no_root_squash) |
/bin | hostname.domainname(ro,no_root_squash) |
/lib | hostname.domainname(ro,no_root_squash) |
/home | hostname.domainname(rw,no_root_squash) |
Other than the first line, which should be separate for each host, the rest of the lines can be replaced with a hostmask to fit all your hosts (like pc*.domain - keep in mind though, that * will substitue only strings without a dot in them). I suggest that you make most of the directories read only, but this is up to you. The no_root_squash
will make sure root users on the clients have actual root permissions on the nfsd as well. Check out man exports(5). If you want users to be able to run passwd from the clients also, make sure the /etc has rw
and not ro
permissions. However, this is not advisable.
Please note another thing concerning the rc.S file. In Slackware, by default, it creates a new /etc/issue and /etc/motd every time it runs. This function MUST be disabled if these files are mounted ro from the server, and I would recommend that they should be disabled in any case.
Lastly, if you want to have the same userbase on the server as on the clients, you should choose between 1), using NIS (Yellow Pages - check the yp-howto), and then each client will have a separate /etc/passwd and /etc/group as it receives it from the NIS server. 2) In most cases, a simple symbolic link will suffice. Therefore, you will need to either hardlink /clients/etc/passwd to /etc/passwd, or if you prefer a symlink, link /etc/passwd to /clients/etc/passwd (and not the other way around, since the clients do not mount the server's etc directory). Do the same for /etc/group.
Generally, most of the files in the client's etc should be symlinked to the /server/etc directory. However, some files are different for each machine, and some just have to be there when the kernel loads. The minimum you need from the etc dir is as follows:
resolv.conf |
hosts |
inittab |
rc.d/rc.S |
fstab |
Since these 5 files can be identical on all clients, you can simply hardlink them or copy them again. However, with the rc.S and fstab file it is advised to keep a separate copy for each client. You will also need a separate etc/HOSTNAME for each client. I personally recommend having all of the rc.d files separate for each client, as configuration and hardware might vary from one to another.
For each client, add to the fstab the proper swap line:
The rest of the /etc files of the client, you can either hardlink to the /clients/etc/* files, or symlink them to the /server/etc (which is the mount point of /clients/etc/).
Make sure your machine can resolve properly, either through a named or through etc/hosts. It is not a bad idea to keep the server's IP in the etc/hosts, instead of counting on resolving. If you will count only on named resolving, a problem in the named will prevent your clients from booting up.
Now, all you have to do is to boot up your machine, cross your fingers and hope everything works as it should :-).