Skip to content

Instantly share code, notes, and snippets.

@meeech
Last active June 5, 2024 11:14
Show Gist options
  • Save meeech/0b97a86f235d10bc4e2a1116eec38e7e to your computer and use it in GitHub Desktop.
Save meeech/0b97a86f235d10bc4e2a1116eec38e7e to your computer and use it in GitHub Desktop.
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/nix-daemon.sh' ]; then
  . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
# 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 - generate-volume-mount-plist.sh. This script is based off the nix install script create-darwin-volume.sh.

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 ./generate-volume-mount-plist.sh

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:
nix
  • 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

Done

Reboot.

#!/usr/bin/env bash
set -eu
set -o pipefail
# Script to regenerate the automount for Nix Store to /nix
# Cobbled together looking at https://raw.githubusercontent.com/NixOS/nix/master/scripts/create-darwin-volume.sh
readonly NIX_ROOT="${NIX_ROOT:-/nix}"
readonly NIX_VOLUME_LABEL="${NIX_VOLUME_LABEL:-Nix Store}"
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
readonly NIX_VOLUME_UUID="${NIX_VOLUME_UUID:-}"
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
else
echo "Sorry, I didn't understand. I can only understand answers of y or n"
echo -n "$prompt"
fi
done
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
fi
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
fi
return 0
}
check() {
uuid_set
volume_state_set
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
encrypted)
cmd=(/bin/sh -c "/usr/bin/security find-generic-password -s '$volume_uuid' -w | /usr/sbin/diskutil apfs unlockVolume '$volume_uuid' -mountpoint '$mountpoint' -stdinpassphrase");;
unencrypted)
cmd=(/usr/sbin/diskutil mount -mountPoint "$mountpoint" "$volume_uuid");;
*)
failure "Invalid first arg $cmd_type to generate_mount_command";;
esac
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" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>RunAtLoad</key>
<true/>
<key>Label</key>
<string>org.nixos.darwin-store</string>
<key>ProgramArguments</key>
<array>
$(generate_mount_command "$cmd_type" "$volume_uuid")
</array>
</dict>
</plist>
EOF
}
test_voldaemon() {
test -f "$NIX_VOLUME_MOUNTD_DEST"
}
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
:a
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
.
:x
EOF
# 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
fi
}
main() {
check
setup_volume_daemon $NIX_VOLUME_STATE $NIX_VOLUME_UUID
}
main
@mip29
Copy link

mip29 commented Sep 26, 2022

Nix never seemed to work properly on my machine, I didn't really understand why. After some digging online, I found this and I was able to fix my Nix installation. Thank you for compiling this list of things to check, it helped me out a lot!

@llaisdy
Copy link

llaisdy commented Jan 4, 2023

Thanks v much for this! This just happened to me upgrading from 12.6.1 to 12.6.2 -- just the /etc/zshrc.

@meeech
Copy link
Author

meeech commented Jan 9, 2023

great! glad it helped

@tkuwill
Copy link

tkuwill commented Apr 2, 2023

Thank you so much for this. Update to 12.6.4. Then fix /etc/zshrc everything went back.

@tihuang02
Copy link

Thanks you so much! I just upgraded macOS from 13.4 to 13.5 and my nix was gone. Followed this guide to restored it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment