aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiderd Jordan <daiderd@gmail.com>2019-12-15 16:43:43 +0100
committerDaiderd Jordan <daiderd@gmail.com>2020-05-21 19:58:10 +0200
commit0726ad5825f60e543d9cf535c62673685adbf5c8 (patch)
treec5a9e4bd5491b02d65c22b0c38e8d53204dcceba
parent5d2d0a7b7fbb3a5e665c1f4a7b232cd1c92fa0a4 (diff)
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.
-rw-r--r--release.nix12
-rwxr-xr-xscripts/create-darwin-volume.sh107
-rw-r--r--scripts/install-nix-from-closure.sh95
3 files changed, 177 insertions, 37 deletions
diff --git a/release.nix b/release.nix
index f5729cee3..2cc4bb4c0 100644
--- a/release.nix
+++ b/release.nix
@@ -177,10 +177,10 @@ let
}
''
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 \
--subst-var-by nix ${toplevel} \
--subst-var-by cacert ${cacert}
-
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
--subst-var-by nix ${toplevel} \
--subst-var-by cacert ${cacert}
@@ -195,6 +195,7 @@ let
# SC1090: Don't worry about not being able to find
# $nix/etc/profile.d/nix.sh
shellcheck --exclude SC1090 $TMPDIR/install
+ shellcheck $TMPDIR/create-darwin-volume.sh
shellcheck $TMPDIR/install-darwin-multi-user.sh
shellcheck $TMPDIR/install-systemd-multi-user.sh
@@ -210,6 +211,7 @@ let
fi
chmod +x $TMPDIR/install
+ chmod +x $TMPDIR/create-darwin-volume.sh
chmod +x $TMPDIR/install-darwin-multi-user.sh
chmod +x $TMPDIR/install-systemd-multi-user.sh
chmod +x $TMPDIR/install-multi-user
@@ -222,11 +224,15 @@ let
--absolute-names \
--hard-dereference \
--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,$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-multi-user $TMPDIR/reginfo \
+ $TMPDIR/install-multi-user \
+ $TMPDIR/reginfo \
$(cat ${installerClosureInfo}/store-paths)
'');
diff --git a/scripts/create-darwin-volume.sh b/scripts/create-darwin-volume.sh
new file mode 100755
index 000000000..f3e0d46f1
--- /dev/null
+++ b/scripts/create-darwin-volume.sh
@@ -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 "$@"
diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh
index e06530ddf..34be7ee6a 100644
--- a/scripts/install-nix-from-closure.sh
+++ b/scripts/install-nix-from-closure.sh
@@ -40,44 +40,62 @@ elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then
fi
INSTALL_MODE=no-daemon
-
+CREATE_DARWIN_VOLUME=0
# handle the command line flags
-while [ "x${1:-}" != "x" ]; do
- if [ "x${1:-}" = "x--no-daemon" ]; then
- INSTALL_MODE=no-daemon
- elif [ "x${1:-}" = "x--daemon" ]; then
- INSTALL_MODE=daemon
- elif [ "x${1:-}" = "x--no-channel-add" ]; then
- NIX_INSTALLER_NO_CHANNEL_ADD=1
- elif [ "x${1:-}" = "x--no-modify-profile" ]; then
- NIX_INSTALLER_NO_MODIFY_PROFILE=1
- elif [ "x${1:-}" != "x" ]; then
- (
- echo "Nix Installer [--daemon|--no-daemon] [--no-channel-add] [--no-modify-profile]"
-
- echo "Choose installation method."
- echo ""
- echo " --daemon: Installs and configures a background daemon that manages the store,"
- echo " providing multi-user support and better isolation for local builds."
- echo " Both for security and reproducibility, this method is recommended if"
- echo " supported on your platform."
- echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
- echo ""
- echo " --no-daemon: Simple, single-user installation that does not require root and is"
- echo " trivial to uninstall."
- echo " (default)"
- echo ""
- echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default."
- echo ""
- echo " --no-modify-profile: Skip channel installation. When not provided nixpkgs-unstable"
- echo " is installed by default."
- echo ""
- ) >&2
- exit
- fi
+while [ $# -gt 0 ]; do
+ case $1 in
+ --daemon)
+ INSTALL_MODE=daemon;;
+ --no-daemon)
+ INSTALL_MODE=no-daemon;;
+ --no-channel-add)
+ NIX_INSTALLER_NO_CHANNEL_ADD=1;;
+ --no-modify-profile)
+ 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 "Choose installation method."
+ echo ""
+ echo " --daemon: Installs and configures a background daemon that manages the store,"
+ echo " providing multi-user support and better isolation for local builds."
+ echo " Both for security and reproducibility, this method is recommended if"
+ echo " supported on your platform."
+ echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
+ echo ""
+ echo " --no-daemon: Simple, single-user installation that does not require root and is"
+ echo " trivial to uninstall."
+ echo " (default)"
+ echo ""
+ echo " --no-channel-add: Don't add any channels. nixpkgs-unstable is installed by default."
+ echo ""
+ echo " --no-modify-profile: Skip channel installation. When not provided nixpkgs-unstable"
+ echo " is installed by default."
+ echo ""
+ ) >&2
+
+ 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
+ exit;;
+ esac
shift
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
printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n'
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
if ! sudo sh -c "$cmd"; then
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
fi
fi