From 9c3dc9d7ca11555fbafe77e9ca8ed9fc214ab2f8 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Mon, 7 Sep 2020 23:53:31 -0500 Subject: [PATCH 1/8] update macOS version handling for Big Sur Keeping this commit narrow for reviewability, but some of these conditionals will change in subsequent commits in this PR. Fixes #3852. --- scripts/install-nix-from-closure.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index 6efd8af18..e7e063007 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -24,9 +24,11 @@ fi # macOS support for 10.12.6 or higher if [ "$(uname -s)" = "Darwin" ]; then - macos_major=$(sw_vers -productVersion | cut -d '.' -f 2) - macos_minor=$(sw_vers -productVersion | cut -d '.' -f 3) - if [ "$macos_major" -lt 12 ] || { [ "$macos_major" -eq 12 ] && [ "$macos_minor" -lt 6 ]; }; then + IFS='.' read macos_major macos_minor macos_patch << EOF +$(sw_vers -productVersion) +EOF + if [ "$macos_major" -lt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -lt 12 ]; } || { [ "$macos_minor" -eq 12 ] && [ "$macos_patch" -lt 6 ]; }; then + # patch may not be present; command substitution for simplicity echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher" exit 1 fi @@ -88,7 +90,7 @@ while [ $# -gt 0 ]; do ) >&2 # darwin and Catalina+ - if [ "$(uname -s)" = "Darwin" ] && [ "$macos_major" -gt 14 ]; then + if [ "$(uname -s)" = "Darwin" ] && { [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 14 ]; }; }; then ( echo " --darwin-use-unencrypted-nix-store-volume: Create an APFS volume for the Nix" echo " store and mount it at /nix. This is the recommended way to create" @@ -109,7 +111,7 @@ if [ "$(uname -s)" = "Darwin" ]; then fi info=$(diskutil info -plist / | xpath "/plist/dict/key[text()='Writable']/following-sibling::true[1]" 2> /dev/null) - if ! [ -e $dest ] && [ -n "$info" ] && [ "$macos_major" -gt 14 ]; then + if ! [ -e $dest ] && [ -n "$info" ] && { [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 14 ]; }; }; then ( echo "" echo "Installing on macOS >=10.15 requires relocating the store to an apfs volume." From 1f02b65c590b5a33c1b70dba186eacfe3f67f149 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 8 Sep 2020 00:07:53 -0500 Subject: [PATCH 2/8] fix xpath and conditional bugs; xpath -> xmllint - xpath -> xmllint: xpath's cli interface changed in Big Sur rather than add conditional logic for picking the correct syntax for xpath, I'm changing to xmllint --xpath, which appears to be consistent across versions I've tested... - /plist/dict/key[text()='Writable']/following-sibling::true[1] doesn't do quite what's expected. It was written to try to select a node paired with the Writable key, but it will also select the *next* node that appears even if it was paired with another key. - I think there's also a logic bug in the conditionals here. I'm not sure anyone ever actuall saw it, thanks to the xpath bug, though. With the xpath fix, this conditional passes if /nix does not exist, / IS writable, and the version is Catalina+. I think it meant to test for /nix does not exist, / is NOT writable, and the version is Catalina+. I reworked this lightly to make it a little clearer at the code level. --- scripts/install-nix-from-closure.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index e7e063007..4e64f3d43 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -110,8 +110,8 @@ if [ "$(uname -s)" = "Darwin" ]; then "$self/create-darwin-volume.sh" fi - info=$(diskutil info -plist / | xpath "/plist/dict/key[text()='Writable']/following-sibling::true[1]" 2> /dev/null) - if ! [ -e $dest ] && [ -n "$info" ] && { [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 14 ]; }; }; then + writable="$(diskutil info -plist / | xmllint --xpath "name(/plist/dict/key[text()='Writable']/following-sibling::*[1])" -)" + if ! [ -e $dest ] && [ "$writable" = "false" ]; then ( echo "" echo "Installing on macOS >=10.15 requires relocating the store to an apfs volume." From e736f8f6e44180d7ed7cc1975b48c603c6c4f611 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 8 Sep 2020 00:45:27 -0500 Subject: [PATCH 3/8] replace xpath with xmllint --xpath; simplify As mentioned in previous commit, Big Sur changes the syntax for the xpath command slightly. In the process of testing out replacements for these, I noticed a few small simplification wins. --- scripts/create-darwin-volume.sh | 46 ++++++--------------------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/scripts/create-darwin-volume.sh b/scripts/create-darwin-volume.sh index dac30d72d..8c4558c7f 100755 --- a/scripts/create-darwin-volume.sh +++ b/scripts/create-darwin-volume.sh @@ -5,42 +5,13 @@ root_disk() { diskutil info -plist / } -apfs_volumes_for() { - disk=$1 - diskutil apfs list -plist "$disk" -} - -disk_identifier() { - xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" 2>/dev/null -} - -volume_list_true() { - key=$1 - xpath "/plist/dict/array/dict/key[text()='Volumes']/following-sibling::array/dict/key[text()='$key']/following-sibling::true[1]" 2> /dev/null -} - -volume_get_string() { - 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 +# i.e., "disk1" +root_disk_identifier() { + diskutil info -plist / | xmllint --xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" - } find_nix_volume() { - disk=$1 - i=1 - volumes=$(apfs_volumes_for "$disk") - while true; do - name=$(echo "$volumes" | volume_get_string "Name" "$i") - if [ -z "$name" ]; then - break - fi - case "$name" in - [Nn]ix*) - echo "$name" - break - ;; - esac - i=$((i+1)) - done + diskutil apfs list -plist "$1" | xmllint --xpath "(/plist/dict/array/dict/key[text()='Volumes']/following-sibling::array/dict/key[text()='Name']/following-sibling::string[starts-with(translate(text(),'N','n'),'nix')]/text())[1]" - 2>/dev/null || true } test_fstab() { @@ -89,9 +60,7 @@ test_t2_chip_present(){ } test_filevault_in_use() { - disk=$1 - # list vols on disk | get value of Filevault key | value is true - apfs_volumes_for "$disk" | volume_list_true FileVault | grep -q true + fdesetup isactive >/dev/null } # use after error msg for conditions we don't understand @@ -143,12 +112,12 @@ main() { fi fi - disk=$(root_disk | disk_identifier) + disk="$(root_disk_identifier)" volume=$(find_nix_volume "$disk") if [ -z "$volume" ]; then echo "Creating a Nix Store volume..." >&2 - if test_filevault_in_use "$disk"; then + if test_filevault_in_use; then # TODO: Not sure if it's in-scope now, but `diskutil apfs list` # shows both filevault and encrypted at rest status, and it # may be the more semantic way to test for this? It'll show @@ -178,6 +147,7 @@ main() { if ! test_fstab; then echo "Configuring /etc/fstab..." >&2 label=$(echo "$volume" | sed 's/ /\\040/g') + # shellcheck disable=SC2209 printf "\$a\nLABEL=%s /nix apfs rw,nobrowse\n.\nwq\n" "$label" | EDITOR=ed sudo vifs fi } From fe807904e5e6e56b551f34f3586e69ea6498287c Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 8 Sep 2020 01:01:11 -0500 Subject: [PATCH 4/8] adapt to apfs.util flag diff in catalina/big sur Fixes #3957. Just runs both forms to minimize moving parts. --- scripts/create-darwin-volume.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/create-darwin-volume.sh b/scripts/create-darwin-volume.sh index 8c4558c7f..32fa577a8 100755 --- a/scripts/create-darwin-volume.sh +++ b/scripts/create-darwin-volume.sh @@ -26,6 +26,20 @@ test_synthetic_conf() { grep -q "^nix$" /etc/synthetic.conf 2>/dev/null } +# Create the paths defined in synthetic.conf, saving us a reboot. +create_synthetic_objects(){ + # Big Sur takes away the -B flag we were using and replaces it + # with a -t flag that appears to do the same thing (but they + # don't behave exactly the same way in terms of return values). + # This feels a little dirty, but as far as I can tell the + # simplest way to get the right one is to just throw away stderr + # and call both... :] + { + /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true # Big Sur + /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true # Catalina + } >/dev/null 2>&1 +} + test_nix() { test -d "/nix" } @@ -101,7 +115,7 @@ main() { if ! test_nix; then echo "Creating mountpoint for /nix..." >&2 - /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true + create_synthetic_objects # the ones we defined in synthetic.conf if ! test_nix; then sudo mkdir -p /nix 2>/dev/null || true fi From 3a8699ac4ffc0d9b611c471e2668e6b22cc65767 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Thu, 10 Sep 2020 18:21:04 -0500 Subject: [PATCH 5/8] restore create-darwin-volume to release tarball The move from release.nix to flake.nix appears to have lost some changes from #3628 / 1c56f18a8122b605c28000e295d5e223f272cccd, leaving create-darwin-volume.sh out of the release tarball. Under the assumption that this was just an accident/byproduct of when flake.nix split off and not intentional, I am restoring those edits. --- flake.nix | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index a50533a29..d0c3bfcd2 100644 --- a/flake.nix +++ b/flake.nix @@ -235,6 +235,7 @@ } '' 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 ${nix} \ --subst-var-by cacert ${cacert} @@ -253,6 +254,7 @@ # 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 @@ -268,6 +270,7 @@ 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 @@ -280,11 +283,15 @@ --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) ''); From b719f686a8c8936fe831ce730f28638d8b1e2982 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Fri, 11 Sep 2020 12:06:01 -0500 Subject: [PATCH 6/8] fix skipped multi-user install steps on macOS Some of the changes in #3788 to support non-systemd Nix installs don't appear to be aware that the darwin installer exists, which resulted in some skipped steps and inappropriate instructions. --- scripts/install-darwin-multi-user.sh | 7 +++++ scripts/install-multi-user.sh | 34 +++----------------- scripts/install-systemd-multi-user.sh | 45 ++++++++++++++++++++------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index 49076bd5c..a27be2a43 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -37,6 +37,13 @@ poly_service_setup_note() { EOF } +poly_extra_try_me_commands(){ + : +} +poly_extra_setup_instructions(){ + : +} + poly_configure_nix_daemon_service() { _sudo "to set up the nix-daemon as a LaunchDaemon" \ cp -f "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST" diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index e5cc4d7ed..54edfe40d 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -71,11 +71,9 @@ uninstall_directions() { subheader "Uninstalling nix:" local step=0 - if [ -e /run/systemd/system ] && poly_service_installed_check; then + if poly_service_installed_check; then step=$((step + 1)) poly_service_uninstall_directions "$step" - else - step=$((step + 1)) fi for profile_target in "${PROFILE_TARGETS[@]}"; do @@ -255,40 +253,20 @@ function finish_success { echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"." fi - if [ -e /run/systemd/system ]; then - cat < Date: Fri, 11 Sep 2020 16:45:58 -0500 Subject: [PATCH 7/8] create missing profile files to fix zsh envvars Env vars for ZSH were moved from /etc/zshrc to /etc/zshenv in #3608 to address an issue with zshrc getting clobbered by OS updates, but /etc/zshenv doesn't exist by default--so *nothing* would get set up for zsh users unless they already happened to have /etc/zshenv. Creating these files if they don't exist. Also cut separate creation of profile.d/nix.sh, which isn't needed now. --- scripts/install-multi-user.sh | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 54edfe40d..5e8b4ac18 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -608,24 +608,20 @@ EOF } configure_shell_profile() { - # If there is an /etc/profile.d directory, we want to ensure there - # is a nix.sh within it, so we can use the following loop to add - # the source lines to it. Note that I'm _not_ adding the source - # lines here, because we want to be using the regular machinery. - # - # If we go around that machinery, it becomes more complicated and - # adds complications to the uninstall instruction generator and - # old instruction sniffer as well. - if [ -d /etc/profile.d ]; then - _sudo "create a stub /etc/profile.d/nix.sh which will be updated" \ - touch /etc/profile.d/nix.sh - fi - for profile_target in "${PROFILE_TARGETS[@]}"; do if [ -e "$profile_target" ]; then _sudo "to back up your current $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX" \ cp "$profile_target" "$profile_target$PROFILE_BACKUP_SUFFIX" + else + # try to create the file if its directory exists + target_dir="$(dirname "$profile_target")" + if [ -d "$target_dir" ]; then + _sudo "to create a stub $profile_target which will be updated" \ + touch "$profile_target" + fi + fi + if [ -e "$profile_target" ]; then shell_source_lines \ | _sudo "extend your $profile_target with nix-daemon settings" \ tee -a "$profile_target" From f289bdb9d4e8432160c5dcdc037a930b2025d11b Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Mon, 19 Oct 2020 11:54:21 -0500 Subject: [PATCH 8/8] discourage casual Big Sur installs --- scripts/install-nix-from-closure.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index 4e64f3d43..ea2e47b7f 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -27,6 +27,15 @@ if [ "$(uname -s)" = "Darwin" ]; then IFS='.' read macos_major macos_minor macos_patch << EOF $(sw_vers -productVersion) EOF + # TODO: this is a temporary speed-bump to keep people from naively installing Nix + # on macOS Big Sur (11.0+, 10.16+) until nixpkgs updates are ready for them. + # *Ideally* this is gone before next Nix release. If you're intentionally working on + # Nix + Big Sur, just comment out this block and be on your way :) + if [ "$macos_major" -gt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -gt 15 ]; }; then + echo "$0: nixpkgs isn't quite ready to support macOS $(sw_vers -productVersion) yet" + exit 1 + fi + if [ "$macos_major" -lt 10 ] || { [ "$macos_major" -eq 10 ] && [ "$macos_minor" -lt 12 ]; } || { [ "$macos_minor" -eq 12 ] && [ "$macos_patch" -lt 6 ]; }; then # patch may not be present; command substitution for simplicity echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher"