3 Server setup

The server configuration is similar for both diskless clients and jumpstart installation, allthough for diskless operation we will use NFS to serve files and for jumpstart we will use FTP.

This section describes the configuration of the required services. The population of the directories with files to be served is covered in the following sections.

We will assume that the server and pxebooting clients are located on the 172.16.0.0/16 subnet. All services may be identified by DNS lookup, such that nfs.example.com is the nfs server and tftp.example.com is the tftp server.

3.1 DHCP

We will be using dhcpd v. 3.0 from the Internet Software Consortium (ISC) which can be installed from ports (net/isc-dhcp3-server). The configuration file, dhcpd.conf(5), should be something like this for the basic configuration:

# Configuration file for ISC's dhcpd v. 3.0
#
# Server is authoritative for the subnets.
authoritative; 

# Disable dynamic dns update
ddns-update-style none;

subnet 172.16.0.0 netmask 255.255.0.0 {
  range 172.16.128.0 172.16.255.254;
  default-lease-time 3600;
  max-lease-time 86400;
 
  option domain-name "example.com";
  option domain-name-servers ns.example.com;
  option routers gateway.example.com;

}

This will assign unknown clients IP in the specified range. For jumpstart installation we add the following section within the subnet block:

group { # jumpstart clients
  use-host-decl-names on;
  next-server tftp.example.com;
  filename "boot/pxeboot";
}

The line next-server tftp.example.com; tells the client where to fetch the bootloader, and filename "boot/pxeboot" tells which file to request. The path to the boot loader is relative to the root directory of the tftp server.

For diskless clients, the following section within the subnet block should replace the section above for jumpstart clients.

group { # diskless clients
  use-host-decl-names on;
  next-server tftp.example.com;
  filename "boot/pxeboot";
  option root-path "nfs.example.com:/var/diskless/FreeBSD";

  host diskless-1 {
    hardware ethernet 00:40:63:d4:89:73;
  }
}

For diskless client setup, we also need to specify the root device: option root-path "nfs.example.com:/var/diskless/FreeBSD" tells the client where to get an NFS root mount, if not set it will default to <next-server>:/pxeroot. An alternative is to edit loader.conf(5) to specify a root device (this method is not covered for diskless clients, but is used for jumpstart).

For each client a host declaration is included, this may be omitted. but in particular if the network also hosts non-diskless clients it may be used to tighten control.

To enable dhcpd, add the following lines to rc.conf:

dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_conf="/etc/dhcpd.conf"
dhcpd_ifaces=""
dhcpd_withumask="077"
dhcpd_chuser_enable="YES"
dhcpd_chroot_enable="NO"
dhcpd_rootdir="/var/db/dhcpd"

Then start dhcpd:

# /usr/local/etc/rc.d/dhcpd.sh start

Note: If you make any changes to dhcpd.conf you need to restart the dhcpd daemon, you cannot just send a SIGHUP.

3.2 TFTP

Unless you decide to serve all files with nfs you need to enable tftpd(8). tftp is supported in the FreeBSD base system, to enable tftp edit the file /etc/inetd.conf to enable the following line:

tftp  dgram  udp  wait  root  /usr/libexec/tftpd  tftpd  -l -s /var/tftp

The -l option tells tftpd to log to syslogd(8), the -s /var/tftp instructs tftpd to change its root directory into /var/tftp.

If you have not enabled inetd(8) in your /etc/rc.conf, first add the line:

inetd_enable="YES"

Then start (or restart) inetd:

# /etc/rc.d/inetd start

3.3 FTP

For jumpstart installation we want to install using ftp rather than nfs. Using a local ftp server speeds up the installation as the local network is faster, saves bandwidth on the external connection and reduces load on the public servers.

You can use the ftpd distributed with FreeBSD and enable it in inetd.conf. I prefer vsftpd which can be installed from ports. To enable the vfstpd you need to add the following two lines to the vsftpd.conf file:

listen=YES
background=YES

Then start the server with:

# /usr/local/etc/rc.d/vsftpd.sh start

You may want to toggle pasv_min_port and pasv_max_port to control which ports are used in pasive ftp-data. This is particularly important if there is a firewall between the client and the ftp server.

vsftpd will chroot into it's home directory as specified in the password file, usually /var/ftp. Now you need to fetch a release from a mirror and put it into some reasonable path, typically pub/FreeBSD/<RELEASE>.

3.4 NFS

NFS is a protocol for sharing file systems over the local network, it is an RPC service which makes it particularly difficult to handle, in particular across a firewall.

There are some limitations when exporting file systems. You can export an entire partition (disk label) or a specific directory. If you export a partition with the option -alldirs, then any sub-directory can be mounted, but with the permissions set for the partition. Alternatively you have to list each directory you wish to be exported and the permissions.

The latter should be preferred, although cumbersome, because it gives you more fine grained access control.

Enable nfs in /etc/rc.conf:

rpcbind_enable="YES"          # Run the portmapper service (YES/NO).
nfs_server_enable="YES"       # This host is an NFS server (or NO).
mountd_enable="YES"           # Run mountd (or NO).
mountd_flags="-r -p 59"       # Force mountd to bind on port 59

As a minimum you need to enable rpcbind, nfsserver and mountd as shown above.

By default, when mountd starts it binds to some arbitrary port, and rpc is used to discover which, making it impossible to filter. With option '-p' mountd can be forced to bind to a specific port. Port 59 is assigned to "any private file service", so it sounds reasonable to use this.

You may optionally want to enable lockd and statd which provides file locking and status monitoring. The problem with these services is that they cannot be forced to bind to specific ports making filtering impossible.

Before starting up nfs, we must export the file systems the diskless clients need to mount. Users wants more than a bare base system, in particular they want access to their files in their home directory. The exports(5) file should be something like this:

/var/diskless/FreeBSD -ro -maproot=root:wheel -network 172.16.0.0 -mask 255.255.0.0
/home -alldirs -network 172.16.0.0 -mask 255.255.0.0
/var/diskless/<hostname>/var <hostname> 
/var/diskless/<hostname>/tmp <hostname>

Note: If /var/diskless is a directory residing in /var then you cannot use the option -alldirs and you cannot mount subdirectories of /var/diskless. Instead, you will have to list each directory which will be mounted as shown above. The positive effect is that this will enforce a more strict access control.

The -maproot option specifies which privileges the root user on the client will have for accessing files on the server via nfs. By default root:wheel is mapped to nobody:nobody.

We will need to create var and (optionally) /tmp directories and a swap file for each diskless client. This is described in the section diskless clients. In the above, it is assumed that the hostname of the diskless clients can be looked up and fixed ip address is assigned. If you control the network, you may choose not to specify the hostname or ip address.

Then start nfsd:

# /etc/rc.d/rpcbind start
# /etc/rc.d/nfsd start
# /etc/rc.d/mountd start

You should be able to see the exported shares with the command showmount(8). The directories exported should be created if they do not exist. If you update the exports file, you need to restart mountd for the changes to take effect.

If you are on a closed and controlled network you need not protect your server by a firewall, although it is recommended always to be cautious. If you have a firewall enabled however, you need to open such that the clients can fetch the files needed.

3.5 Firewall

If you are on a closed and controlled network you need not protect your server by a firewall, although it is recommended always to be cautious. If you have a firewall enabled however, you need to open such that the clients can fetch the files needed.

3.5.1 DHCP

To enable DHCP, you must allow packets with source port 68 and destination port 67 in, and the reverse out for any ip. The reason is that when the first dhcp request is sent, the client don't know it's ip and source ip port 67 in, and the reverse out for any ip. The reason is that when the first dhcp request is sent, the client don't know it's ip and source ip is set to 0.0.0.0, nor does it know the ip of the server so the destination ip is also set to 0.0.0.0:

pass in quick proto udp from 0/32 port = 68 to 0/32 port = 67 keep state
pass in quick proto udp from 172.16.0.0/16 port = 68 to 172.16.0.2/32 port = 67 keep state

for inbound traffic and for outbound:

pass out quick proto udp from 172.16.0.2 port = 67 to 0/32 port = 68 keep state

3.5.2 TFTP

TFTP receives requests on udp port 69, but files are transfered from ports in the dynamic port range (ports > 49151). To allow tftp you must add the following rules:

pass in quick proto udp from 172.16.0.0/16 to 172.16.0.2 port = 69 keep state

for inbound, and for outbound traffic:

pass out quick proto udp from 172.16.0.2 port > 49151 to 172.16.0.0/16 port > 49151 keep state

3.5.3 FTP

FTP is more complicated. The server listens on port 21 for incoming connections, as with any other service. FTP specifies two data transfer modes, active and passive. In active ftp-data, the server connects back to the client from port 20 to some unprivileged port chosen by the client. In passive ftp-data the client connects to some unprivileged port chosen by the server, typically in the dynamic port range.

# ftp
pass in quick proto tcp from 172.16.0.0/16 to 172.16.0.2 port 21 flags S keep state
# ftp-data passive
pass in quick proto tcp from 172.16.0.0/16 to 172.16.0.2 port > 49151 flags S keep state

allows ftp-sessions and passive ftp-data, to allow active ftp-data, add the following line

# ftp-data active
pass out quick proto tcp from 172.16.0.2 port 20 to 172.16.0.0/16 port > 1023 flags S keep state

3.5.4 NFS

We forced mountd to bind to a specific port, 59, this makes firewalling easy:

pass in quick proto tcp from 172.16.0.0/16 to 172.16.0.2 port 59 flags S keep state
pass in quick proto tcp from 172.16.0.0/16 to 172.16.0.2 port 111 flags S keep state
pass in quick proto tcp from 172.16.0.0/16 to 172.16.0.2 port 2049 flags S keep state
pass in quick proto udp from 172.16.0.0/16 to 172.16.0.2 port 59 keep state
pass in quick proto udp from 172.16.0.0/16 to 172.16.0.2 port 111 keep state
pass in quick proto udp from 172.16.0.0/16 to 172.16.0.2 port 2049 keep state

Note: Originally, nfs was based on udp but FreeBSD's implementation supports tcp as well.

This, and other documents, can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

For questions about FreeBSD, read the documentation before contacting <questions@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.