Fixing custom DHCP after OS X Server app 2.1 update.

Apple released version 2.1 of Mountain Lion's Server app today. The most notable change is that you can now configure DHCP from the Server app. However, if you implemented custom DHCP due to the lack of this feature in the previous version, you will have to undo your work. As per a previous post, the file bootps.plist in /etc had to be configured to get DHCP functionality. The new Server app v2.1 also use this file and as expected, if you have a custom one, it tends to break Server app's DHCP function. You'll notice you can't configure DHCP in Server app or enable it.

To resolve this issue, simply move /etc/bootps.plist. Server app will re-create this file soon as you start configuring DHCP.

mv /etc/bootps.plist /etc/bootps.plist.custom

It does mean you'll have to re-create your DHCP scope in Server app. Fortunately this should be real quick given Server app's ease of use!

If you had any static IPs configured in /etc/bootptab, you might want to re-create them in Server app so you can see them! For consistency sake move your old bootptab file too.

mv /etc/bootptab /etc/bootptab.custom

Finally setting up DHCP in OS X Mountain Lion Server is how it should be, configured via the Server app!

Configuring DHCP in Mountain Lion Server

Apple made a somewhat confusing decision with OS X Mountain Lion Server by not creating a interface from which DHCP can be configured. In previous iterations of OS X Server, DHCP could be configured via Server Admin, now also 6 feet under. Personally I see no reason why Server app in Mountain Lion can't have a DHCP section, fortunately all is not lost, just a tad more complicated now! According to Apple's knowledge base, DHCP is still around, but you're directed to check out the man page for 'bootpd', thus DHCP is now configurable via CLI (command line interface) only. The exceptions to this rule: Enabling the NetInstall service or enabling Internet Sharing will still activate DHCP, but you have no control over it, unless you go dig around in CLI.

It's a bit more time consuming to create a config from scratch every time, so I decided to put together a template for future use. The template follows the structure in the man page for 'bootpd'.

Whats involved in creating a configuration? Just the following three files.

  • /etc/bootpd.plist (main configuration)
  • /etc/bootptab (static/reserved IP table)
  • /System/Library/LaunchDaemons/bootps.plist

We'll work these three files through from the top.

bootpd.plist Configuration

As per the man page, this file is an XML property list (plist). At the root of the plist is a dictionary which contain three main configuration areas. They are: Service Controls & Filters, Subnets & Netboot. I've structured my template according to these three areas in that order, so its easy to reference along with the man page should you add more advanced functionality to the file.

You can grab the correctly formatted and complete plist on Github.

I'll be using some sections from the plist and discuss them accordingly.

Looking at the root of the XML dictionary, we have Service Controls & Filters. Essentially this is where you enable/disable functionality of 'bootpd'. In this example, of the 4 main service controls, only DHCP is enabled on en0 (ignore the orange line, we're getting to that), the rest is disabled and denoted by the <false/> boolean values. No filters are specified here, such as denying DHCP for certain MAC addresses. Should you wish to add an additional interface you would simply add another string line such as the one in orange, inside the array. Alternatively, instead of using an array, simply specify <true/>, right below <key>dhcp_enabled</key>, which will enable for all interfaces.

<dict> <key>bootp_enabled</key> <false/> <key>dhcp_enabled</key> <array> <string>en0</string> <string>en1</string> </array> <key>netboot_enabled</key> <false/> <key>relay_enabled</key> <false/>

Subnets

Here we specify everything about the DHCP subnet and what information it will hand out to our clients. The keys we use are fairly self-explanatory. Only thing to note is that Subnets has its own dictionary in the XML plist that contains the subnet info. Service Controls & Filters were in the root dictionary. Read the man page for info on each key.

<key>Subnets</key> <array> <dict> <key>name</key> <string>192.168.5.0/24</string> <key>net_mask</key> <string>255.255.255.0</string> <key>net_address</key> <string>192.168.5.0</string> <key>net_range</key> <array> <string>192.168.5.2</string> <string>192.168.5.254</string> </array> <key>allocate</key> <true/> <key>lease_max</key> <integer>3600</integer> <key>dhcp_router</key> <string>192.168.5.1</string> <key>dhcp_domain_name_server</key> <array> <string>192.168.5.1</string> </array> <key>dhcp_domain_search</key> <array> <string>revolvingsq.net</string> </array> </dict>

bootptab Configuration

This file is used to reserve IPs for hosts based on MAC addresses and follows a very simple format, to get more info just type man bootptab in Terminal.

#
# bootptab for My Client
# %%
# Reservations have the following format:
#
#hostname    hwtype    hwaddr                           ipaddr
# iMac               1          00:00:74:85:53:85          192.168.5.10

Mixing everything together

Once you have configured the bootpd.plist and bootptab (optional), we have to fire up the bootpd daemon. To do this this we will run the following command:

sudo launchctl load -w /System/Library/LaunchDaemons/bootps.plist

To stop the daemon, change "load" to "unload".

To monitor what is happening, follow the system.log in either Console or in Terminal type (grep to limit output to bootpd only): tail -f /var/log/system.log | grep bootpd

Run at Startup

In order for bootpd to load at startup, you have to edit /System/Libary/LaunchDaemons/bootps.plist and make the following change: The text in orange is by default "true", simply change this to "false" and the daemon will launch at startup.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabled</key> <false/>

Troubleshooting

Should things not go quite according to plan, you can enable verbose mode for the bootpd daemon by editing the same file as above and adding the orange text in the array under the ProgramArguments key.

<key>ProgramArguments</key> <array> <string>/usr/libexec/bootpd</string> <string>-v</string> </array>

Should you be making changes to bootptab while the bootpd service is running, you can force it to reload the leases by sending a SIGHUP (-1) signal to the bootpd daemon.

sudo killall -1 bootpd

There you have it. All done!

ps. Most likely going to take more time reading this post than actually setting DHCP up :)