install: configure and bootstrap synthetic.conf on darwin

Starting macOS 10.15 /nix can't be creasted directly anymore due to the
readonly filesystem, but synthetic.conf was introduced to enable
creating mountpoints or symlinks for special usecases like package
managers.
This commit is contained in:
Daiderd Jordan 2019-12-15 16:43:43 +01:00
parent 5d2d0a7b7f
commit 0726ad5825
No known key found for this signature in database
GPG key ID: D02435D05B810C96
3 changed files with 176 additions and 36 deletions

View file

@ -177,10 +177,10 @@ let
} }
'' ''
cp ${installerClosureInfo}/registration $TMPDIR/reginfo cp ${installerClosureInfo}/registration $TMPDIR/reginfo
cp ${./scripts/create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \ substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
--subst-var-by nix ${toplevel} \ --subst-var-by nix ${toplevel} \
--subst-var-by cacert ${cacert} --subst-var-by cacert ${cacert}
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \ substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
--subst-var-by nix ${toplevel} \ --subst-var-by nix ${toplevel} \
--subst-var-by cacert ${cacert} --subst-var-by cacert ${cacert}
@ -195,6 +195,7 @@ let
# SC1090: Don't worry about not being able to find # SC1090: Don't worry about not being able to find
# $nix/etc/profile.d/nix.sh # $nix/etc/profile.d/nix.sh
shellcheck --exclude SC1090 $TMPDIR/install shellcheck --exclude SC1090 $TMPDIR/install
shellcheck $TMPDIR/create-darwin-volume.sh
shellcheck $TMPDIR/install-darwin-multi-user.sh shellcheck $TMPDIR/install-darwin-multi-user.sh
shellcheck $TMPDIR/install-systemd-multi-user.sh shellcheck $TMPDIR/install-systemd-multi-user.sh
@ -210,6 +211,7 @@ let
fi fi
chmod +x $TMPDIR/install chmod +x $TMPDIR/install
chmod +x $TMPDIR/create-darwin-volume.sh
chmod +x $TMPDIR/install-darwin-multi-user.sh chmod +x $TMPDIR/install-darwin-multi-user.sh
chmod +x $TMPDIR/install-systemd-multi-user.sh chmod +x $TMPDIR/install-systemd-multi-user.sh
chmod +x $TMPDIR/install-multi-user chmod +x $TMPDIR/install-multi-user
@ -222,11 +224,15 @@ let
--absolute-names \ --absolute-names \
--hard-dereference \ --hard-dereference \
--transform "s,$TMPDIR/install,$dir/install," \ --transform "s,$TMPDIR/install,$dir/install," \
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \ --transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
--transform "s,$NIX_STORE,$dir/store,S" \ --transform "s,$NIX_STORE,$dir/store,S" \
$TMPDIR/install $TMPDIR/install-darwin-multi-user.sh \ $TMPDIR/install \
$TMPDIR/create-darwin-volume.sh \
$TMPDIR/install-darwin-multi-user.sh \
$TMPDIR/install-systemd-multi-user.sh \ $TMPDIR/install-systemd-multi-user.sh \
$TMPDIR/install-multi-user $TMPDIR/reginfo \ $TMPDIR/install-multi-user \
$TMPDIR/reginfo \
$(cat ${installerClosureInfo}/store-paths) $(cat ${installerClosureInfo}/store-paths)
''); '');

107
scripts/create-darwin-volume.sh Executable file
View file

@ -0,0 +1,107 @@
#!/bin/sh
set -e
root_disks() {
diskutil list -plist /
}
apfs_volumes_for() {
disk=$1
diskutil apfs list -plist "$disk"
}
disk_identifier() {
xpath "/plist/dict/key[text()='WholeDisks']/following-sibling::array[1]/string/text()" 2>/dev/null
}
volume_get() {
key=$1 i=$2
xpath "/plist/dict/array/dict/key[text()='Volumes']/following-sibling::array/dict[$i]/key[text()='$key']/following-sibling::string[1]/text()" 2> /dev/null
}
find_nix_volume() {
disk=$1
i=1
volumes=$(apfs_volumes_for "$disk")
while true; do
name=$(echo "$volumes" | volume_get "Name" "$i")
if [ -z "$name" ]; then
break
fi
case "$name" in
[Nn]ix*)
echo "$name"
break
;;
esac
i=$((i+1))
done
}
test_fstab() {
grep -q "/nix" /etc/fstab 2>/dev/null
}
test_synthetic_conf() {
grep -q "^nix" /etc/synthetic.conf 2>/dev/null
}
test_nix() {
test -d "/nix"
}
main() {
(
echo ""
echo " ------------------------------------------------------------------ "
echo " | This installer will create a volume for the nix store and |"
echo " | configure it to mount at /nix. Follow these steps to uninstall. |"
echo " ------------------------------------------------------------------ "
echo ""
echo " 1. Remove the entry from fstab using 'sudo vifs'"
echo " 2. Destroy the data volume using 'diskutil apfs deleteVolume'"
echo " 3. Delete /etc/synthetic.conf"
echo ""
) >&2
if [ -L "/nix" ]; then
echo "error: /nix is a symlink, please remove it or edit synthetic.conf (requires reboot)" >&2
echo " /nix -> $(readlink "/nix")" >&2
exit 2
fi
if ! test_synthetic_conf; then
echo "Configuring /etc/synthetic.conf..." >&2
echo nix | sudo tee /etc/synthetic.conf
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B
fi
if ! test_nix; then
echo "Creating mountpoint for /nix..." >&2
sudo mkdir /nix
fi
disk=$(root_disks | disk_identifier)
volume=$(find_nix_volume "$disk")
if [ -z "$volume" ]; then
echo "Creating a Nix Store volume..." >&2
sudo diskutil apfs addVolume "$disk" APFS 'Nix Store' -mountpoint /nix
volume="Nix Store"
else
echo "Using existing '$volume' volume" >&2
fi
if ! test_fstab; then
echo "Configuring /etc/fstab..." >&2
label=$(echo "$volume" | sed 's/ /\\040/g')
printf "\$a\nLABEL=%s /nix apfs rw\n.\nwq\n" "$label" | EDITOR=ed sudo vifs
fi
echo "The following options can be enabled to disable spotlight indexing" >&2
echo "of the volume, which might be desirable." >&2
echo "" >&2
echo " $ mdutil -i off /nix" >&2
echo "" >&2
}
main "$@"

View file

@ -40,18 +40,21 @@ elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then
fi fi
INSTALL_MODE=no-daemon INSTALL_MODE=no-daemon
CREATE_DARWIN_VOLUME=0
# handle the command line flags # handle the command line flags
while [ "x${1:-}" != "x" ]; do while [ $# -gt 0 ]; do
if [ "x${1:-}" = "x--no-daemon" ]; then case $1 in
INSTALL_MODE=no-daemon --daemon)
elif [ "x${1:-}" = "x--daemon" ]; then INSTALL_MODE=daemon;;
INSTALL_MODE=daemon --no-daemon)
elif [ "x${1:-}" = "x--no-channel-add" ]; then INSTALL_MODE=no-daemon;;
NIX_INSTALLER_NO_CHANNEL_ADD=1 --no-channel-add)
elif [ "x${1:-}" = "x--no-modify-profile" ]; then NIX_INSTALLER_NO_CHANNEL_ADD=1;;
NIX_INSTALLER_NO_MODIFY_PROFILE=1 --no-modify-profile)
elif [ "x${1:-}" != "x" ]; then NIX_INSTALLER_NO_MODIFY_PROFILE=1;;
--create-volume)
CREATE_DARWIN_VOLUME=1;;
*)
( (
echo "Nix Installer [--daemon|--no-daemon] [--no-channel-add] [--no-modify-profile]" echo "Nix Installer [--daemon|--no-daemon] [--no-channel-add] [--no-modify-profile]"
@ -73,11 +76,26 @@ while [ "x${1:-}" != "x" ]; do
echo " is installed by default." echo " is installed by default."
echo "" echo ""
) >&2 ) >&2
exit
if [ "$(uname -s)" = "Darwin" ]; then
(
echo " --create-volume: Create an APFS volume for the store and create the /nix"
echo " mountpoint for it using synthetic.conf."
echo " (required on macOS >=10.15)"
echo " See https://nixos.org/nix/manual/#sect-darwin-apfs-volume"
echo ""
) >&2
fi fi
exit;;
esac
shift shift
done done
if [ "$(uname -s)" = "Darwin" ] && [ "$CREATE_DARWIN_VOLUME" = 1 ]; then
printf '\e[1;31mCreating volume and mountpoint /nix.\e[0m\n'
"$self/create-darwin-volume.sh"
fi
if [ "$INSTALL_MODE" = "daemon" ]; then if [ "$INSTALL_MODE" = "daemon" ]; then
printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n' printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n'
exec "$self/install-multi-user" exec "$self/install-multi-user"
@ -95,6 +113,15 @@ if ! [ -e $dest ]; then
echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2 echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2
if ! sudo sh -c "$cmd"; then if ! sudo sh -c "$cmd"; then
echo "$0: please manually run '$cmd' as root to create $dest" >&2 echo "$0: please manually run '$cmd' as root to create $dest" >&2
if [ "$(uname -s)" = "Darwin" ]; then
(
echo ""
echo "Installing on macOS >=10.15 requires relocating the store to an apfs volume."
echo "Use --create-volume or run the preparation steps manually."
echo "See https://nixos.org/nix/manual/#sect-darwin-apfs-volume."
echo ""
) >&2
fi
exit 1 exit 1
fi fi
fi fi