Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Some steps to (hopefully) help you fix your Nix install on OS X after an upgrade.

Apple Borked my Nix!

Ok, so you've had nix (home-manager) working fine. Then Apple tells you it's time to update.

Ok. Reboot. Oops. It has now broken your Nix setup. Here's some stuff to work through. YMMV.

Note: This is what worked for me, who was just using nix + home-manager. The upgrade that I last did that caused all these issues was 12.3.X > 12.4

Useful Links

Nix setup will modify your /etc/zshrc. When OS X updates, it will sometimes restore the original /etc/zshrc.

Check the bottom of your etc/zshrc, you should see the following:

# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/' ]; then
  . '/nix/var/nix/profiles/default/etc/profile.d/'
# End Nix

If it is NOT there, you want to add this back to the bottom of your /etc/zshrc. Or you can try to future proof things a little, and add it to the top of your own ~/.zshrc.

Nix Store volume check

From terminal try diskutil list | grep Nix. You should see something like

7:                APFS Volume Nix Store               10.1 GB    disk3s7

So that means we have the volume. That last bit - disk3s7 is the disk identifier. So then try diskutil info disk3s7

   Device Identifier:         disk3s7
... snip ...
   Volume Name:               Nix Store
   Mounted:                   Yes
   Mount Point:               /nix
... snip ...
   Volume UUID:               53E764A4-140E-4980-9EE2-39CB2404DAFF
... snip ...
   FileVault:                 Yes
... snip ...

So if Mounted is No then you need to mount this. Probably means the auto-mount script is broken. Check if /Library/LaunchDaemons/org.nixos.darwin-store.plist exists. If not, you can recreate it with the provided script - This script is based off the nix install script

USE THE VOLUME UUID you found above. And use unencrypted if your volume is FileVault: No.

NIX_VOLUME_UUID=53E764A4-140E-4980-9EE2-39CB2404DAFF NIX_VOLUME_STATE=encrypted ./

Check you have /nix

If your /nix root level is missing, that means the mount point of your Nix Store got hosed. Let's rebuild it.

  • Check for /etc/synthetic.conf. If it exists, make sure you have an entry for nix. If you don't have one, then you will need to set it up. It should be as simple as a file that just says:
  • Check your /etc/fstab file. If it exists, check you have an entry for /nix. If it doesn't, you will need to create it. WITH YOUR UUID you found earlier.
# Warning - this file should only be modified with vifs(8)
# Failure to do so is unsupported and may be destructive.
UUID=53E764A4-140E-4980-9EE2-39CB2404DAFF /nix apfs rw,noauto,nobrowse,suid,owners



#!/usr/bin/env bash
set -eu
set -o pipefail
# Script to regenerate the automount for Nix Store to /nix
# Cobbled together looking at
readonly NIX_ROOT="${NIX_ROOT:-/nix}"
readonly NIX_VOLUME_MOUNTD_DEST="${NIX_VOLUME_MOUNTD_DEST:-/Library/LaunchDaemons/org.nixos.darwin-store.plist}"
readonly NIX_VOLUME_STATE=${NIX_VOLUME_STATE:-encrypted} # encrypted|unencrypted
ui_confirm() {
local prompt="[y/n] "
echo -n "$prompt"
while read -r y; do
if [ "$y" = "y" ]; then
echo ""
return 0
elif [ "$y" = "n" ]; then
echo "You said no. Exiting."
return 1
echo "Sorry, I didn't understand. I can only understand answers of y or n"
echo -n "$prompt"
echo ""
return 1
uuid_set() {
if [[ -z "$NIX_VOLUME_UUID" ]]; then
echo "You need to set the value of NIX_VOLUME_UUID. You can find this info with 'diskutil info -all' or using Disk Utility app."
return 1
return 0
volume_state_set() {
if [[ "$NIX_VOLUME_STATE" != "encrypted" && "$NIX_VOLUME_STATE" != "unencrypted" ]]; then
echo "Invalid value for NIX_VOLUME_STATE - must be encrypted or unencrypted"
return 1
return 0
check() {
echo "All checks passed."
generate_mount_command() {
local cmd_type="$1" # encrypted|unencrypted
local volume_uuid mountpoint cmd=()
printf -v volume_uuid "%q" "$2"
printf -v mountpoint "%q" "$NIX_ROOT"
case "$cmd_type" in
cmd=(/bin/sh -c "/usr/bin/security find-generic-password -s '$volume_uuid' -w | /usr/sbin/diskutil apfs unlockVolume '$volume_uuid' -mountpoint '$mountpoint' -stdinpassphrase");;
cmd=(/usr/sbin/diskutil mount -mountPoint "$mountpoint" "$volume_uuid");;
failure "Invalid first arg $cmd_type to generate_mount_command";;
printf " <string>%s</string>\n" "${cmd[@]}"
generate_mount_daemon() {
local cmd_type="$1" # encrypted|unencrypted
local volume_uuid="$2"
cat <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "">
<plist version="1.0">
$(generate_mount_command "$cmd_type" "$volume_uuid")
test_voldaemon() {
task() {
echo "$@"
_sudo() {
shift # throw away the 'explanation'
/usr/bin/sudo "$@"
setup_volume_daemon() {
local cmd_type="$1" # encrypted|unencrypted
local volume_uuid="$2"
if ! test_voldaemon; then
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
# Note: `-u NONE` disables vim plugins/rc; see note on --clean earlier
_sudo "to install the Nix volume mounter" /usr/bin/ex -u NONE "$NIX_VOLUME_MOUNTD_DEST" <<EOF
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
# TODO: should probably alert the user if this is disabled?
_sudo "to launch the Nix volume mounter" \
launchctl bootstrap system "$NIX_VOLUME_MOUNTD_DEST" || true
# TODO: confirm whether kickstart is necessesary?
# I feel a little superstitous, but it can guard
# against multiple problems (doesn't start, old
# version still running for some reason...)
_sudo "to launch the Nix volume mounter" \
launchctl kickstart -k system/org.nixos.darwin-store
main() {
setup_volume_daemon $NIX_VOLUME_STATE $NIX_VOLUME_UUID
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment