OpenBSD on Small Disks
As sys admins, we can automate a large number of tasks, including
installation. With Solaris, we use Jumpstart servers; with Red Hat,
we use their Kickstart feature. However, OpenBSD does not provide
an easy way to automate installation. Its installer is a very simple
one -- a few choices of generic packages are offered, and everything
else is done by hand. Recently, for a client, however, I needed
to perform a special type of installation on OpenBSD. The client
had just acquired new hardware that came with flash disks (instead
of the traditional hard drive), and they wanted to perform an installation
of OpenBSD that would allow them to run their nameserver on those
disks. However, the flash disks were only 128 MB in size. Since
the most basic possible installation of OpenBSD requires approximately
69 MB (without a current version of BIND or the compiler packages),
I knew this was not going to be an easy task. However, we believed
that the performance of the disks would be desirable (not to mention
the possible security benefits of removing all the excess binaries
from a system to lock it down). After I completed this task, I created
a script from my documentation, so that if I had ever had to do
it again, it would be easier. In this article, I will explain the
process that I used and the script I created.
There are three tasks involved in building this type of nameserver:
- Cut the system down to the appropriate size.
- Build the nameserver daemon.
- Configure the system and the nameserver.
As such, the script follows this basic path. First, it cuts itself
into multiple temporary files, then it removes all unnecessary files,
and, finally, builds and configures BIND. Although it may seem odd
to permanently remove the binaries first, this script is designed
to build the BIND (or DNS) server in under 128 MB of disk space.
Thus, because of the size of the compiler and ports packages (which
will be added to the system temporarily during the execution of
the script), the unessential system binaries are removed very near
the beginning of the script. (Listings for this article can be downloaded
from the Sys Admin Web site: www.sysadminmag.com.)
OpenBSD, like most modern operating systems, comes with a large
number of binaries and a large list of services enabled by default.
While OpenBSD is an extremely secure and efficient OS, these things
are not at all necessary for single task machines (like a nameserver).
Unfortunately, this install process has no option to select or deselect
individual packages (at least as far as I have been able to find).
So, when I attempted to reduce the footprint, I had to examine almost
all files placed on the system by default to determine whether they
could be removed without affecting functionality. For this reason,
the script includes the full pathnames of the files that are to
be removed from the system. Some of you may not like my choice of
files to be removed; for this reason, the script has a command-line
flag that allows you to choose a file containing your own list.
ex to the Rescue
This inclusion of the list of binaries in the file brought its
own set of problems of course. First among these problems was the
need to find an easy way for the script to read the list (without
the obvious method of placing the list in the middle of the script
as a variable). Doing it by hand, I would likely open the file in
vi, cut out all the extraneous lines, and pass the contents
of the leftover file into whatever I wanted to use. At that point,
I opened up the man page for vi, and remembered the ex
command set. For those of you that don't have much experience
with, or knowledge of ex, it is the line-based editor upon
which vi is built. Although most sys admins are familiar
with sed and awk for text parsing based on regular
expressions, not as many are familiar with ex. However, ex
is a useful tool that fits the way sys admins often deal with text:
line-by-line, regardless of the content of the lines. So, in this
case, I used the following syntax:
cp $MYDIR/$MYNAME /tmp/dep.files
These two commands allowed me to perform (automatically) the exact
set of tasks that I would have performed by hand; that is, they create
a copy of the script file in the /tmp directory. Then, ex
runs the command to delete the first 287 lines out of the file, and
waits for the user to issue the next command. I pass that command
(the vi command to save and quit, :wq) to ex
through the pipe.
echo ":wq" | ex -c "1,287 d" /tmp/dep.files
Patching the Files
The last step was to make sure that I had a working (if unconfigured)
nameserver running upon reboot. This step required moving all of
the named configuration files into the appropriate directory,
as well as editing the system's startup scripts. There are
sample versions of the files that must be set up in the installation
of BIND. To run the named daemon, these must be moved into
the /var/named directory, and a few edits made to the named.conf
file to inform BIND of the location of those files. These files
hold the information about the machines and networks that the nameserver
will distribute. Also, I edited the startup script /etc/rc.conf
to disable services like portmap and NFS (that OpenBSD starts by
default), and replaced the script /etc/rc to remove references
to binaries that had already been removed from the system.
This step required that I copy the sample named configuration
files into /var/named, then rewrite two files in the system:
the named.conf file and /etc/rc.conf, which controls
services started in OpenBSD. Again, I would simply open the files
in vi and edit them by hand. However, in attempting to automate
the process, I needed a way to replace selected lines in these files
easily and quickly (and without completely rewriting the file).
Here, the patch utility was my choice; it was simple to take the
files that I had changed by hand, and take a diff of those files
with the originals. Those diffs are also included in the script.
I cut them out of the script using ex in the same way as
above. These files are then used as input to patch the copies that
are on the local system, exactly as you would patch any other text
patch -p0 /etc/rc.conf < /tmp/patch.rc
The purpose of this script is not so that the client can do it again;
they could use dd for that. The real purpose here is to create
a script that allows me to do it again, for a different client, without
performing all the tasks by hand (because the act of selecting the
files to be removed was a very long job). This type of script will
save me a great deal of time next time I need to do this; I can instead
spend that time doing something more useful, and allow the script
to do the simple, repetitive tasks for me.
Mike Murray is a consultant for Taos, The Sys Admin Company
in San Francisco. He is currently assigned to Hiverworld, Inc. as
a member of their security appliance engineering team. Mike has
four years of systems administration experience on a variety of
platforms (but he's happiest on OpenBSD). He can be contacted