Managing multiple FreeBSD servers

If you run multiple installations of FreeBSD sooner or later you will face with the issue of how to update them all in the most efficient and centralized way. Building kernel/world for a FreeBSD server with one CPU and couple of GB of RAM will take hours to complete. Fortunately, there is a way to optimize it.

In short: you build kernel/world on a powerful server and then expose /usr/src and /usr/obj via NFS for others to mount and install. In such case the time spent on upgrade is greatly reduced.

For example, in my case all FreeBSD servers are virtual. They use the same architecture (amd64), run the same version of FreeBSD (10+) and the same customized kernel. There is a separate, physical server (let’s call it the Master) with plenty of CPU and fast hard drives, where I build kernel and world for virtual FreeBSD servers (let’s call them Slaves). The master acts as a NFS server with /usr/src and /usr/obj exposed to the slaves. When I update the slave, I boot it to the single-user mode, mount /usr/src and /usr/obj from the master, and simply installkernel/installworld.

Note: it’s quite important to note that /etc/src.conf and /etc/make.conf files on the master must be identical to the one’s on the slaves.

Things to be done on the master:

Configure the master to act as a NFS server. Here is a relevant part from /etc/rc.conf file:

# nfs stuff
mountd_flags="-r -p 957"

Note: my NFS server is firewalled so I fix the mountd port to 957/tcp, otherwise it uses a random port after each restart.

Here is how /etc/exports file looks like:

/usr/src /usr/ports /usr/obj    -maproot=root           192.168.x.x 192.168.y.y

Note: 192.168.x.x/192.168.y.y are IP addresses of the slaves. Execute ‘service mountd onereload’ every time you modify /etc/exports file.

Update source files, build and install kernel/world on the master using the standard procedure. Once the master is up to date, get a copy of the kernel installed on the slave, copy it to the /usr/src/sys/arch/conf directory on the master, build it but do not install:

% cd /usr/src 
% make -j4 buildkernel KERNCONF=SLAVE01

Where SLAVE01 is the kernel name from the slave.

Things to be done on the slave:

Drop the slave into single-user mode:

% mount -u /
% mount -a -t ufs
% swapon -a
% adjkerntz -i

Start the network:

% /etc/rc.d/netif start
% /etc/rc.d/routing start

Mount /usr/src and /usr/obj directories:

% mount ip.of.the.master:/usr/src /usr/src
% mount ip.of.the.master:/usr/obj /usr/obj

Install the kernel, run mergemaster and installworld:

% cd /usr/src

% make installkernel KERNCONF=SLAVE01
% mergemaster -p
% make installworld
% mergemaster -iF
% make delete-old

Reboot the slave.

If you update between major versions (like 9 to 10, or 10 to 11) you have to rebuild all ports prior to deleting old libraries. Here is how you do it with portupgrade:

% mount ip.of.the.master:/usr/ports /usr/ports
% portupgrade -f pkg
% portupgrade -af

Finally, clean up old libraries:

% mount ip.of.the.master:/usr/src /usr/src
% cd /usr/src
% make delete-old-libs

Tags: , , ,

One Response to “Managing multiple FreeBSD servers”

  1. […] This is a follow up post on how to manage ports for multiple FreeBSD servers. If you’re looking for how to update the operating system itself, have a look at my almost three years old post: Managing multiple FreeBSD servers. […]

Leave a Reply