Recently I had an unfortunate and strange situation which resulted in my work Macbook not booting at all. It would stay stuck in a loop of trying to ping some sort of authentication server, but then failing. Over 2 days back and forth between my own troubleshooting and the Apple Genius Bar itself, I finally reached the sad conclusion: I would need to reset my entire Macbook.
I foolishly put off backing up my work laptop out of some vague notion that our IT department handled this (they do not).
Thankfully I wasn’t completely up a creek without a paddle, I was just about 60 yards from my paddle in a swiftly moving creek. Or… something like that.
Anyway, I, like many developers, keep a repository consisting solely of dotfiles, scripts, and other configuration settings that I need to make my computer feel like “mine”. This post isn’t about the dotfiles themselves, however. (Reminder to self: Write a post about my dotfiles!) This post is about the strange events that prevented by configuration .plist files from working.
In MacOS (and presumably other operating systems?) a .plist file is a configuration format that stores user preferences for a Variety of Things™. These things include native MacOS keyboard shortcuts, global preferences such as how Finder displays your files, and even app-specific configuration settings! This last piece is actually one of the coolest applications of this file format.
Almost all MacOS apps have a .plist file which stores your preferences for that specific app. Which means if you adjust your settings, you can save that .plist file and then have the app behave exactly the same on another MacOS computer!
This is ideal for keeping similar behaviors across multiple computers!
But something broke
So I had to completely reset my work laptop, which meant I needed to re-initialize my dotfiles repository. In this repository I have a script that operates like so:
# Install all the configured preferences for our various apps
ln -sfn ${DOTFILES_LOCATION}/prefs/*.plist "${HOME}/Library/Preferences"
ln -sfn ${DOTFILES_LOCATION}/prefs/.GlobalPreferences.plist "${HOME}/Library/Preferences"
This bit of logic simply says: “Copy all of my .plist files from my dotfiles/prefs directory, into my Library/Preferences directory”. Followed by “Also copy my MacOS Global preferences over as well”
Interestingly though, it’s not just copying those files over. It’s creating a symlink.
A symlink is an interesting concept to explain in layman’s terms. More or less, it’s a file that lives in 1 (or more) places at the same time! That means it could be on your desktop, in your photos album, and anywhere else and it’s the same exact file in each location.
This behavior is extremely useful if you want your dotfiles to constantly back up your configuration changes! If you update your app’s preferences, your dotfiles will see the change and let you know you should back them up.
But MacOS Sonoma broke symlinks
In several different places you can see tickets and issues caused by this change. My best guess is that the discovery of a CVE related to symlinking caused Apple to change this behavior. (Here are a couple other supporting links too).
At any rate, it’s very strange, because as one GitHub user astutely pointed out:
[…] surprising, given that symlinks should be transparent to most file reads
This was my understand as well. Most applications aren’t really aware of whether or not they’re accessing a symlink, which isn’t to say they can’t be aware. Weird at any rate.
So my solution
My solution was pretty dang simple: just copy the config files over instead of symlinking them.
¯\_(ツ)_/¯
That’s it.
Yeah, it’s not as elegant, but at least my dotfiles still work:
cp -R ${DOTFILES_LOCATION}/prefs/*.plist "${HOME}/Library/Preferences"
cp -R ${DOTFILES_LOCATION}/prefs/.GlobalPreferences.plist "${HOME}/Library/Preferences"
And just to sprinkle a bit of SEO Sauce on this post.
When you run this:
defaults read NSGlobalDomain
You’ll see something like this:
Domain Apple Global Domain does not exist
Despite being able to see it right there in the file system:
ls /User/youruser/Library/Preferences | grep NSGlobal
Other symptoms of this issue include things like:
- iTerm 2 not importing your configuration and/or preferences
- Karabiner not initializing your keybindings properly
- Entire configurations not working
Thanks for reading! If you enjoyed this, you may also enjoy following me on twitter!