TL;DR
If you're using symlinks in MacOS Sonoma to manage dotfiles (especially with something like mackup), it will not work on MacOS 14.
Like many developers, I keep a repository consisting of dotfiles, scripts, and other configuration settings that I need to make a computer feel like "mine".
I also keep a list of .plist
files for defining native MacOS keyboard shortcuts, global preferences such as how Finder displays files, and even app-specific configuration settings!
Almost all MacOS apps have a .plist
file which stores your preferences for that specific app. This means if you adjust your settings, you can save that .plist
file and then have the app behave exactly the same on a different MacOS computer!
This is ideal for keeping keyboard shortcuts and app defaults consistent across multiple computers.
But something broke
One day 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 copies all of my .plist files and MacOS global preferences into the Library/Preferences directory.
However, it doesn't just copy those files over. It's creating a symlink.
This behavior is extremely useful so that your dotfiles can easily back up your configuration changes! If you update your app's preferences, your dotfiles will see the change and let you know you should commit them.
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
My understanding was that 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, but that they usually aren't.
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