Running u9fs on macOS
I use the following technique to run u9fs on macOS. I’m currently running this on macOS 14 (Sonoma), but I believe I’ve used the same technique on several prior versions.
My primary use of this is to serve a root file system to Plan 9 running under qemu. I have it perform real Plan 9 authentication against my auth server.
Creating needed files
The u9fs binary
You’ll need a u9fs binary, of course.
I use the tree from https://github.com/unofficial-mirror/u9fs.
It should work as-is.
There’s a good argument for just deleting authrhosts.c
and removing it from authmethods
in u9fs.c
at this point,
but I haven’t done that.
Put the resulting binary somewhere stable.
The launchd file
In /Library/LaunchDaemons
I create a file 9pfs.plist
containing the following:
<?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>Label</key>
<string>org.p9f.u9fs</string>
<key>Program</key>
<string>/Users/a/bin/MacOSX/arm64/u9fs</string>
<key>ProgramArguments</key>
<array>
<string>u9fs</string>
<string>-l</string>
<string>/var/log/u9fs.log</string>
<string>-a</string>
<string>p9any</string>
<string>/opt/plan9</string>
</array>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockServiceName</key>
<string>9pfs</string>
</dict>
</dict>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<false/>
</dict>
</dict>
</plist>
A few things you’ll want to adjust:
- Make the
string
after theProgram
key reflect wherever you have the u9fs binary installed - Confirm you’re happy with the log file location
- Confirm the tree you want to serve (
/opt/plan9
in the example above)
Permissions on this file matter to launchd.
I’m not sure exactly what the criteria are, but mine is
mode 644
and owned by root:wheel
, and everything is happy.
The key file
If you’re doing real Plan 9 authentication, create a file /etc/u9fs.key
.
Note: this file will contain a sensitive key, so be cautious with permissions.
Mine is mode 640
and owned by root:wheel
.
It should not be world-readable.
This file contains exactly three lines. They are, in order:
- auth password
- auth user
- auth domain
The conventional way to do this is to put your Plan 9 hostowner info in there,
but I don’t like sticking that in additional places.
I create a new user, unixroot
, and use that.
So my file looks like:
YourSuperSecretPassword
unixroot
9srv.net
That user must exist on the auth server;
see auth/changeuser
in auth(8)
.
The user doesn’t need to exist on the mac.
Optional: symlink /usr
→ /Users
If you’re using this to serve Plan 9 qemu images like I am,
it’s very useful to create a symlink from usr
in the root of your tree
to your real /Users
directory.
This way your qemu images will get your real home directory.
Running the results
I’m not 100% clear on when launchd
re-reads its config information,
but I did the below, as root, to get it listening after setting things up like above.
:; cd /Library/LaunchDaemons
:; launchctl load org.p9f.u9fs
:; launchctl start org.p9f.u9fs
You should then see one instance returned if you run
launchctl list | grep u9fs
,
plus one instance with the name followed by a UUID for each active connection.
This should get picked up on subsequent reboots without your intervention.