Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macos big sur installer fixes #3996

Merged
merged 8 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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)
'');

Expand Down
62 changes: 23 additions & 39 deletions scripts/create-darwin-volume.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -55,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"
}
Expand Down Expand Up @@ -89,9 +74,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
Expand Down Expand Up @@ -132,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
Expand All @@ -143,12 +126,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
Expand Down Expand Up @@ -178,6 +161,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
}
Expand Down
7 changes: 7 additions & 0 deletions scripts/install-darwin-multi-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
56 changes: 14 additions & 42 deletions scripts/install-multi-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <<EOF

Before Nix will work in your existing shells, you'll need to close
them and open them again. Other than that, you should be ready to go.

Try it! Open a new terminal, and type:

$ nix-shell -p nix-info --run "nix-info -m"

Thank you for using this installer. If you have any feedback, don't
hesitate:

$(contactme)
EOF
else
cat <<EOF
cat <<EOF

Before Nix will work in your existing shells, you'll need to close
them and open them again. Other than that, you should be ready to go.

Try it! Open a new terminal, and type:

$ sudo nix-daemon
$(poly_extra_try_me_commands)
$ nix-shell -p nix-info --run "nix-info -m"

Additionally, you may want to add nix-daemon to your init-system.

$(poly_extra_setup_instructions)
Thank you for using this installer. If you have any feedback, don't
hesitate:

$(contactme)
EOF
fi

}

Expand Down Expand Up @@ -630,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"
Expand Down Expand Up @@ -725,9 +699,7 @@ main() {
setup_default_profile
place_nix_configuration

if [ -e /run/systemd/system ]; then
poly_configure_nix_daemon_service
fi
poly_configure_nix_daemon_service

trap finish_success EXIT
}
Expand Down
23 changes: 17 additions & 6 deletions scripts/install-nix-from-closure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,20 @@ 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
# 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"
exit 1
fi
Expand Down Expand Up @@ -88,7 +99,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"
Expand All @@ -108,8 +119,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 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."
Expand Down
45 changes: 33 additions & 12 deletions scripts/install-systemd-multi-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,45 @@ poly_service_setup_note() {
EOF
}

poly_configure_nix_daemon_service() {
_sudo "to set up the nix-daemon service" \
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"
poly_extra_try_me_commands(){
if [ -e /run/systemd/system ]; then
:
else
cat <<EOF
$ sudo nix-daemon
EOF
fi
}
poly_extra_setup_instructions(){
if [ -e /run/systemd/system ]; then
:
else
cat <<EOF
Additionally, you may want to add nix-daemon to your init-system.

_sudo "to set up the nix-daemon socket service" \
systemctl enable "/nix/var/nix/profiles/default$SOCKET_SRC"
EOF
fi
}

handle_network_proxy
poly_configure_nix_daemon_service() {
if [ -e /run/systemd/system ]; then
_sudo "to set up the nix-daemon service" \
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"

_sudo "to set up the nix-daemon socket service" \
systemctl enable "/nix/var/nix/profiles/default$SOCKET_SRC"

_sudo "to load the systemd unit for nix-daemon" \
systemctl daemon-reload
handle_network_proxy

_sudo "to start the nix-daemon.socket" \
systemctl start nix-daemon.socket
_sudo "to load the systemd unit for nix-daemon" \
systemctl daemon-reload

_sudo "to start the nix-daemon.service" \
systemctl restart nix-daemon.service
_sudo "to start the nix-daemon.socket" \
systemctl start nix-daemon.socket

_sudo "to start the nix-daemon.service" \
systemctl restart nix-daemon.service
fi
}

poly_group_exists() {
Expand Down