Integrating Mac OS in a NIS/NFS environment

[Last updated 2007-04-23.]

This week I acquired an unused Mac at work. It had been doing duty as a plant-pot holder, and I'd assumed it was something like a 400MHz G3. I was only there to lighten it of its USB keyboard and mouse, but I thought I'd have a quick look inside. The size of the disk made me realize it probably wasn't as old as I'd imagined, and indeed it turned out to be a dual 800MHz G4 with a decent amount of disk and memory.

Cool! (Though I now have to think of a use for my Mac mini when it arrives.)

I found and pressed the PRAM reset button so it would power up, booted from the 10.3 CD, reformatted the disk, and re-installed the OS. Any machine that's been used as a plant-pot holder so long it won't even power up probably isn't something you want to use without starting from scratch!

My first mistake was letting the Mac OS installer create me an "elliotth" account, which is the same name I have in NIS. I should probably have used a temporary name, but I wasn't certain I was going to (or going to be able to) integrate the Mac thoroughly.

To enable NIS, I followed the instructions in http://www.bresink.de/osx/nis.html. Note that the pictures correspond to 10.2, but the text tells you what's different in 10.3 (the other way round would make more sense, I think).

This was pretty easy, and I could ypcat(1) to my heart's content, but no-one could log in because their home directories weren't available. I was going to need NFS.

Experiments with mount(1) on the command-line (and Ethereal via Apple's X11.app) suggested that I was going to need a name in DNS or Linux's NFS server would refuse my attempts to mount with EPERM. I couldn't find any support for dynamic DNS in Mac OS, and Google seems to think it doesn't exist. So I changed to "Using DHCP with manual address" in System Preferences' network configuration, and added a DNS entry for a newly-allocated IP address.

Linux wasn't impressed. Ethereal showed that the DNS lookup was successful now, but I was still getting EPERM. It turns out that without the "insecure" export option, Linux won't accept mounts from ports >= 1024. Silly in these days of hand-held machines capable of running Unix (which you've installed yourself and so know the root password for), but what can you do? What you can do is use the "-P" option to mount.

I also had to use the NetInfo GUI to edit the local "elliotth" to have the same uid and gid as the user in NIS, to stop things getting too confused. While I was there, I chose "Enable Root User" just in case. (Interestingly, I found out later that even if you're logged in as root, the NetInfo GUI makes you authenticate with an administrator password before making changes.)

So, I knew that I could manually mount an exported home directory. What I needed now was to tell the automounter to make them all available, on demand.

Unfortunately, Mac OS has its own automounter, different from amd(1) and autofs(1) (see here). So I couldn't just use the local auto.home configuration.

Google offered an O'Reilly Mac OS X hack "Accessing NFS" showing how to manually configure one entry without using the NetInfo GUI. It was pretty easy given that (with the exception of working out the quoting!) to knock up a script to translate auto.home into NetInfo automounter configuration.

#!/usr/bin/ruby -w


def sudo(command)
puts("sudo #{command}")
system("sudo #{command}")

def restart_automount()
sudo("kill -HUP `cat /var/run/automount.pid`")

def remove_old_configuration()
sudo("niutil -destroy . /mounts && rm /home/*")

def add_entry(username, path)
# Based on information in O'Reilly's "Accessing NFS" Mac OS X hack.
# http://hacks.oreilly.com/pub/h/341
sudo("niutil -create . /mounts/temp#{$temp}")
sudo("niutil -createprop . /mounts/temp#{$temp} type 'nfs'")
sudo("niutil -createprop . /mounts/temp#{$temp} dir '/home/#{username}'")
sudo("niutil -createprop . /mounts/temp#{$temp} name '#{path}'")
sudo("nicl . create '/mounts/#{path.gsub('/', "\x5c\x5c/")}' opts \"-P\"")
$temp = $temp + 1

def configure_automount_from_NIS()

sudo("niutil -create . /mounts")

`ypcat -k auto.home`.split("\n").each() {
# "monkeyboy monkeyhouse.zoo.com:/tree/branch/&"
# We expand '&' ourselves.
if line =~ /^(\S+) \s+ (\S+:\S+)\/&$/x
username = $1
path = $2
add_entry(username, "#{path}/#{username}/")



You can check that it looks right with the NetInfo GUI, and you should be able to cd /home/monkeyboy (or whatever makes sense given your NIS users).

The final step was to log out, log in as root (I didn't have another local account; this was the mistake I referred to back at the beginning), move the useful stuff from /Users/elliotth into /home/elliotth (I was actually su(1)ed to elliotth to do this; my reason for logging out was so that nothing important would change in my home directory), remove /Users/elliotth, and use the NetInfo GUI to rename the local user.

Surprisingly, I could log back in as (NIS) elliotth with no problems.

Well, one problem: an Xcode project I'd moved failed to open, with no error message. The command-line xcodebuild tool suggested it was trying to access directories in /private/automounter/home/elliotth instead of /private/automounter/static/home/elliotth, but grep(1) doesn't think that's stored in the project. This may be indicative of some lurking problem with my automounter work-around. Or it might just be that Xcode is broken. It was a good excuse to convert the Xcode project into a normal make(1) project, anyway, and stick it under Subversion's control. "Why I can't stand Xcode" is a topic for another day...

Anyway, don't blame me if this leaves your Mac no more useful than a plant-pot holder, but having this post available would have saved me time, Google strain, and head-scratching this week. I imagine that the arrival of the Mac mini will mean a lot of curious Unix users who couldn't previously justify a Mac will now be facing exactly these problems. It's worth it, but that too is a topic for another day...

There's more information about NFS/NIS on Mac OS at sial.org's Using automount on Mac OS X.