about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraham Christensen <graham@grahamc.com>2017-07-09T17·07-0400
committerGraham Christensen <graham@grahamc.com>2017-07-14T16·10-0400
commitfb40d73e23383224fc541911da95a894bbbcc2a4 (patch)
tree53aeedbfc65b6bc8a39bee5624134461b17783e2
parenta0ad8ba12ee26edf0bf5f221b080a61c0d24a874 (diff)
Switch to a fancy multi-user installer on Darwin
-rw-r--r--release.nix7
-rw-r--r--scripts/install-darwin-multi-user.sh808
-rw-r--r--scripts/install-nix-from-closure.sh24
3 files changed, 831 insertions, 8 deletions
diff --git a/release.nix b/release.nix
index 86a7350d5ea5..796591cc1671 100644
--- a/release.nix
+++ b/release.nix
@@ -146,10 +146,15 @@ let
           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 \
+            --subst-var-by nix ${toplevel} \
+            --subst-var-by cacert ${cacert}
 
           shellcheck -e SC1090 $TMPDIR/install
+          shellcheck -e SC1091,SC2002 $TMPDIR/install-darwin-multi-user
 
           chmod +x $TMPDIR/install
+          chmod +x $TMPDIR/install-darwin-multi-user
           dir=nix-${version}-${system}
           fn=$out/$dir.tar.bz2
           mkdir -p $out/nix-support
@@ -161,7 +166,7 @@ let
             --transform "s,$TMPDIR/install,$dir/install," \
             --transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
             --transform "s,$NIX_STORE,$dir/store,S" \
-            $TMPDIR/install $TMPDIR/reginfo $storePaths
+            $TMPDIR/install $TMPDIR/install-darwin-multi-user $TMPDIR/reginfo $storePaths
         '');
 
 
diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh
new file mode 100644
index 000000000000..87d55b2f0172
--- /dev/null
+++ b/scripts/install-darwin-multi-user.sh
@@ -0,0 +1,808 @@
+#!/bin/bash
+
+set -eu
+set -o pipefail
+
+# Sourced from:
+# - https://github.com/LnL7/nix-darwin/blob/8c29d0985d74b4a990238497c47a2542a5616b3c/bootstrap.sh
+# - https://gist.github.com/expipiplus1/e571ce88c608a1e83547c918591b149f/ac504c6c1b96e65505fbda437a28ce563408ecb0
+# - https://github.com/NixOS/nixos-org-configurations/blob/a122f418797713d519aadf02e677fce0dc1cb446/delft/scripts/nix-mac-installer.sh
+# - https://github.com/matthewbauer/macNixOS/blob/f6045394f9153edea417be90c216788e754feaba/install-macNixOS.sh
+# - https://gist.github.com/LnL7/9717bd6cdcb30b086fd7f2093e5f8494/86b26f852ce563e973acd30f796a9a416248c34a
+#
+# however tracking which bits came from which would be impossible.
+
+readonly ESC='\033[0m'
+readonly BOLD='\033[38;1m'
+readonly BLUE='\033[38;34m'
+readonly BLUE_UL='\033[38;4;34m'
+readonly GREEN='\033[38;32m'
+readonly GREEN_UL='\033[38;4;32m'
+readonly RED='\033[38;31m'
+readonly RED_UL='\033[38;4;31m'
+readonly YELLOW='\033[38;33m'
+readonly YELLOW_UL='\033[38;4;33m'
+
+readonly CORES=$(sysctl -n hw.ncpu)
+readonly NIX_USER_COUNT="$CORES"
+readonly NIX_BUILD_GROUP_ID="30000"
+readonly NIX_BUILD_GROUP_NAME="nixbld"
+readonly NIX_FIRST_BUILD_UID="30001"
+# Please don't change this. We don't support it, because the
+# default shell profile that comes with Nix doesn't support it.
+readonly NIX_ROOT="/nix"
+readonly PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
+
+readonly PROFILE_TARGETS=("/etc/profile" "/etc/bashrc" "/etc/zshrc")
+readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix"
+readonly PROFILE_NIX_FILE_DIR="/etc/"
+readonly PROFILE_NIX_FILE_NAME="profile-nix.sh"
+readonly PROFILE_NIX_FILE="$PROFILE_NIX_FILE_DIR$PROFILE_NIX_FILE_NAME"
+
+
+
+readonly NIX_INSTALLED_NIX="@nix@"
+readonly NIX_INSTALLED_CACERT="@cacert@"
+readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
+
+readonly ROOT_HOME="/var/root"
+
+contactme() {
+    echo "We'd love to help if you need it."
+    echo ""
+    echo "If you can, open an issue at https://github.com/nixos/nix/issues"
+    echo ""
+    echo "Or feel free to contact the team,"
+    echo " - on IRC #nixos on irc.freenode.net"
+    echo " - on twitter @nixos_org"
+}
+
+uninstall_directions() {
+    subheader "Uninstalling nix:"
+    local step=1
+    cat <<EOF
+$step. If $PLIST_DEST exists:
+
+  sudo launchctl unload $PLIST_DEST
+  sudo rm $PLIST_DEST
+
+EOF
+    for profile_target in "${PROFILE_TARGETS[@]}"; do
+        if [ -e "$profile_target" ]; then
+            step=$((step + 1))
+            cat <<EOF
+$step. If $profile_target$PROFILE_BACKUP_SUFFIX exists:
+
+  sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
+
+(after this one, you may need to re-open any terminals that were
+opened while it existed.)
+
+EOF
+        fi
+    done
+    step=$((step + 1))
+
+    cat <<EOF
+$step. Delete the files Nix added to your system:
+
+  sudo rm -rf /etc/nix $NIX_ROOT $ROOT_HOME/.nix-profile $ROOT_HOME/.nix-defexpr $ROOT_HOME/.nix-channels $HOME/.nix-profile $HOME/.nix-defexpr $HOME/.nix-channels
+
+and that is it.
+
+EOF
+
+}
+
+nix_user_for_core() {
+    printf "nixbld%d" "$1"
+}
+
+nix_uid_for_core() {
+    echo $((NIX_FIRST_BUILD_UID + $1 - 1))
+}
+
+dsclattr() {
+    /usr/bin/dscl . -read "$1" \
+        | awk "/$2/ { print \$2 }"
+}
+
+_textout() {
+    echo -en "$1"
+    shift
+    if [ "$*" = "" ]; then
+        cat
+    else
+        echo "$@"
+    fi
+    echo -en "$ESC"
+}
+
+header() {
+    follow="---------------------------------------------------------"
+    header=$(echo "---- $* $follow$follow$follow" | head -c 80)
+    echo ""
+    _textout "$BLUE" "$header"
+}
+
+warningheader() {
+    follow="---------------------------------------------------------"
+    header=$(echo "---- $* $follow$follow$follow" | head -c 80)
+    echo ""
+    _textout "$RED" "$header"
+}
+
+subheader() {
+    echo ""
+    _textout "$BLUE_UL" "$*"
+}
+
+row() {
+    printf "$BOLD%s$ESC:\t%s\n" "$1" "$2"
+}
+
+task() {
+    echo ""
+    ok "~~> $1"
+}
+
+bold() {
+    echo "$BOLD$*$ESC"
+}
+
+ok() {
+    _textout "$GREEN" "$@"
+}
+
+warning() {
+    warningheader "warning!"
+    cat
+    echo ""
+}
+
+failure() {
+    header "oh no!"
+    _textout "$RED" "$@"
+    echo ""
+    _textout "$RED" "$(contactme)"
+    trap finish_cleanup EXIT
+    exit 1
+}
+
+ui_confirm() {
+    _textout "$GREEN$GREEN_UL" "$1"
+
+    local prompt="[y/n] "
+    echo -n "$prompt"
+    while read -r y; do
+        if [ "$y" = "y" ]; then
+            echo ""
+            return 0
+        elif [ "$y" = "n" ]; then
+            echo ""
+            return 1
+        else
+            _textout "$RED" "Sorry, I didn't understand. I can only understand answers of y or n"
+            echo -n "$prompt"
+        fi
+    done
+    echo ""
+    return 1
+}
+
+__sudo() {
+    local expl="$1"
+    local cmd="$2"
+    shift
+    header "sudo execution"
+
+    echo "I am executing:"
+    echo ""
+    echo "    $ sudo $cmd"
+    echo ""
+    echo "$expl"
+    echo ""
+
+    return 0
+}
+
+_sudo() {
+    local expl="$1"
+    shift
+    if __sudo "$expl" "$*"; then
+        sudo "$@"
+    fi
+}
+
+
+readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
+function finish_cleanup {
+    rm -rf "$SCRATCH"
+}
+
+function finish_fail {
+    finish_cleanup
+
+    failure <<EOF
+Jeeze, something went wrong. If you can take all the output and open
+an issue, we'd love to fix the problem so nobody else has this issue.
+
+:(
+EOF
+}
+trap finish_fail EXIT
+
+function finish_success {
+    finish_cleanup
+
+    ok "Alright! We're done!"
+    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 figlet -p lolcat --run "echo 'nix rules' | figlet | lolcat"
+
+Thank you for using this installer. If you have any feedback, don't
+hesitate:
+
+$(contactme)
+EOF
+}
+
+
+validate_starting_assumptions() {
+    if [ "$(uname -s)" != "Darwin" ]; then
+        failure "This script is for use with macOS!"
+    fi
+
+    if [ $EUID -eq 0 ]; then
+        failure <<EOF
+Please do not run this script with root privileges. We will call sudo
+when we need to.
+EOF
+    fi
+
+    if type nix-env 2> /dev/null >&2; then
+        failure <<EOF
+Nix already appears to be installed, and this tool assumes it is
+_not_ yet installed.
+
+$(uninstall_directions)
+EOF
+    fi
+
+    if [ "${NIX_REMOTE:-}" != "" ]; then
+        failure <<EOF
+For some reason, \$NIX_REMOTE is set. It really should not be set
+before this installer runs, and it hints that Nix is currently
+installed. Please delete the old Nix installation and start again.
+
+Note: You might need to close your shell window and open a new shell
+to clear the variable.
+EOF
+    fi
+
+    if echo "${SSL_CERT_FILE:-}" | grep -qE "(nix/var/nix|nix-profile)"; then
+        failure <<EOF
+It looks like \$SSL_CERT_FILE is set to a path that used to be part of
+the old Nix installation. Please unset that variable and try again:
+
+  $ unset SSL_CERT_FILE
+
+EOF
+    fi
+
+    for file in ~/.bash_profile ~/.bash_login ~/.profile ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin; do
+        if [ -f "$file" ]; then
+            if grep -l ".nix-profile" "$file"; then
+                failure <<EOF
+I found a reference to a ".nix-profile" in $file.
+This has a high chance of breaking a new nix installation. It was most
+likely put there by a previous Nix installer.
+
+Please remove this reference and try running this again. You should
+also look for similar references in:
+
+ - ~/.bash_profile
+ - ~/.bash_login
+ - ~/.profile
+
+or other shell init files that you may have.
+EOF
+            fi
+        fi
+    done
+
+    if [ -d /nix ]; then
+        failure <<EOF
+There are some relics of a previous installation of Nix at /nix, and
+this scripts assumes Nix is _not_ yet installed. Please delete the old
+Nix installation and start again.
+
+$(uninstall_directions)
+EOF
+    fi
+
+    if [ -d /etc/nix ]; then
+        failure <<EOF
+There are some relics of a previous installation of Nix at /etc/nix, and
+this scripts assumes Nix is _not_ yet installed. Please delete the old
+Nix installation and start again.
+
+$(uninstall_directions)
+EOF
+    fi
+
+    for profile_target in "${PROFILE_TARGETS[@]}"; do
+        if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
+        failure <<EOF
+When this script runs, it backs up the current $profile_target to
+$profile_target$PROFILE_BACKUP_SUFFIX. This backup file already exists, though.
+
+Please follow these instructions to clean up the old backup file:
+
+1. Copy $profile_target and $profile_target$PROFILE_BACKUP_SUFFIX to another place, just
+in case.
+
+2. Take care to make sure that $profile_target$PROFILE_BACKUP_SUFFIX doesn't look like
+it has anything nix-related in it. If it does, something is probably
+quite wrong. Please open an issue or get in touch immediately.
+
+3. Take care to make sure that $profile_target doesn't look like it has
+anything nix-related in it. If it does, and $profile_target _did not_,
+run:
+
+  $ /usr/bin/sudo /bin/mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
+
+and try again.
+EOF
+        fi
+
+        if grep -qi "nix" "$profile_target"; then
+            failure <<EOF
+It looks like $profile_target already has some Nix configuration in
+there. There should be no reason to run this again. If you're having
+trouble, please open an issue.
+EOF
+        fi
+    done
+
+    warning <<EOF
+I strongly recommend deleting all the following files, which are
+relics of a previous installation. You can check by running (yourself):
+
+  $ sudo find / -name .nix-profile  -o -name .nix-defexpr -o -name .nix-channels -o -name '*nix-daemon.plist'
+
+In particular, the following files and directories MUST NOT EXIST!
+
+ - $ROOT_HOME/.nix-profile
+ - $ROOT_HOME/.nix-defexpr
+ - $ROOT_HOME/.nix-channels
+
+If some relics are found and you want to keep them, it might be okay.
+If you're not sure, don't hesitate to ask for help.
+
+$(contactme)
+EOF
+
+    if ui_confirm "Does $ROOT_HOME/.nix-defexpr or $ROOT_HOME/.nix-channels or $ROOT_HOME/.nix-profile exist?"; then
+        failure <<EOF
+You must delete $ROOT_HOME/.nix-defexpr and $ROOT_HOME/.nix-channels
+before continuing.
+EOF
+    fi
+}
+
+setup_report() {
+    header "hardware report"
+    row "           Cores" "$CORES"
+
+    header "Nix config report"
+    row "        Temp Dir" "$SCRATCH"
+    row "        Nix Root" "$NIX_ROOT"
+    row "     Build Users" "$NIX_USER_COUNT"
+    row "  Build Group ID" "$NIX_BUILD_GROUP_ID"
+    row "Build Group Name" "$NIX_BUILD_GROUP_NAME"
+
+    subheader "build users:"
+
+    row "    Username" "UID"
+    for i in $(seq 1 "$NIX_USER_COUNT"); do
+        row "     $(nix_user_for_core "$i")" "$(nix_uid_for_core "$i")"
+    done
+    echo ""
+}
+
+create_build_group() {
+    local primary_group_id
+
+    task "Setting up the build group $NIX_BUILD_GROUP_NAME"
+    if ! /usr/bin/dscl . -read "/Groups/$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1; then
+        _sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
+              /usr/sbin/dseditgroup -o create \
+              -r "Nix build group for nix-daemon" \
+              -i "$NIX_BUILD_GROUP_ID" \
+              "$NIX_BUILD_GROUP_NAME" >&2
+        row "            Created" "Yes"
+    else
+        primary_group_id=$(dsclattr "/Groups/$NIX_BUILD_GROUP_NAME" "PrimaryGroupID")
+        if [ "$primary_group_id" -ne "$NIX_BUILD_GROUP_ID" ]; then
+            failure <<EOF
+It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
+with the UID $primary_group_id. This script can't really handle
+that right now, so I'm going to give up.
+
+You can fix this by editing this script and changing the
+NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
+to $primary_group_id and re-run.
+EOF
+        else
+            row "            Exists" "Yes"
+        fi
+    fi
+}
+
+create_build_user_for_core() {
+    local coreid
+    local username
+    local uid
+
+    coreid="$1"
+    username=$(nix_user_for_core "$coreid")
+    uid=$(nix_uid_for_core "$coreid")
+    dsclpath="/Users/$username"
+
+    task "Setting up the build user $username"
+
+    if ! /usr/bin/dscl . -read "$dsclpath" > /dev/null 2>&1; then
+        _sudo "Creating the Nix build user, $username" \
+              /usr/sbin/sysadminctl -addUser -fullName "Nix build user $coreid" \
+	      -home /var/empty \
+	      -UID "${uid}" \
+              -addUser "${username}"
+        row "           Created" "Yes"
+    else
+        actual_uid=$(dsclattr "$dsclpath" "UniqueID")
+        if [ "$actual_uid" -ne "$uid" ]; then
+            failure <<EOF
+It seems the build user $username already exists, but with the UID
+with the UID $actual_uid. This script can't really handle that right
+now, so I'm going to give up.
+
+If you already created the users and you know they start from
+$actual_uid and go up from there, you can edit this script and change
+NIX_FIRST_BUILD_UID near the top of the file to $actual_uid and try
+again.
+EOF
+        else
+            row "            Exists" "Yes"
+        fi
+    fi
+
+    if [ "$(dsclattr "$dsclpath" "IsHidden")" = "1" ]; then
+        row "          IsHidden" "Yes"
+    else
+        _sudo "in order to make $username a hidden user" \
+              /usr/bin/dscl . -create "$dsclpath" "IsHidden" "1"
+        row "          IsHidden" "Yes"
+    fi
+
+    if [ "$(dsclattr "$dsclpath" "UserShell")" = "/sbin/nologin" ]; then
+        row "   Logins Disabled" "Yes"
+    else
+        _sudo "in order to prevent $username from logging in" \
+              /usr/bin/dscl . -create "$dsclpath" "UserShell" "/sbin/nologin"
+        row "   Logins Disabled" "Yes"
+    fi
+
+    if dseditgroup -o checkmember -m "$username" "$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1 ; then
+        row "  Member of $NIX_BUILD_GROUP_NAME" "Yes"
+    else
+        _sudo "Add $username to the $NIX_BUILD_GROUP_NAME group"\
+            /usr/sbin/dseditgroup -o edit -t user \
+            -a "$username" "$NIX_BUILD_GROUP_NAME"
+        row "  Member of $NIX_BUILD_GROUP_NAME" "Yes"
+    fi
+
+    if [ "$(dsclattr "$dsclpath" "PrimaryGroupId")" = "$NIX_BUILD_GROUP_ID" ]; then
+        row "    PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
+    else
+        _sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
+              /usr/bin/dscl . -create "$dsclpath" "PrimaryGroupId" "$NIX_BUILD_GROUP_ID"
+        row "    PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
+
+    fi
+}
+
+create_build_users() {
+    for i in $(seq 1 "$NIX_USER_COUNT"); do
+        create_build_user_for_core "$i"
+    done
+}
+
+create_directories() {
+    _sudo "to make the basic directory structure of Nix (part 1)" \
+          mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool}
+
+    _sudo "to make the basic directory structure of Nix (part 2)" \
+          mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user
+
+    _sudo "to make the basic directory structure of Nix (part 3)" \
+          mkdir -pv -m 1775 /nix/store
+
+    _sudo "to make the basic directory structure of Nix (part 4)" \
+          chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
+
+    _sudo "to set up the root user's profile (part 1)" \
+          mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root
+
+    _sudo "to set up the root user's profile (part 2)" \
+          mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr"
+
+    _sudo "to place the default nix daemon configuration (part 1)" \
+          mkdir -pv -m 0555 /etc/nix
+}
+
+place_channel_configuration() {
+    echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
+    _sudo "to set up the default system channel (part 1)" \
+          install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
+}
+
+chat_about_sudo() {
+    header "let's talk about sudo"
+
+    cat <<EOF
+This script is going to call sudo a lot. Every time we do, it'll
+output exactly what it'll do, and why.
+
+Just like this:
+
+EOF
+
+    __sudo "to demonstrate how our sudo prompts look" \
+           echo "this is a sudo prompt"
+
+    cat <<EOF
+
+We're going to use sudo to set up Nix:
+
+ - create local users (see the list above for the users we'll make)
+ - create a local group ($NIX_BUILD_GROUP_NAME)
+ - install Nix in to $NIX_ROOT
+ - create a configuration file in /etc/nix
+ - set up the "default profile" by creating some Nix-related files in
+   $ROOT_HOME
+ - create $PROFILE_NIX_FILE
+EOF
+    for profile_target in "${PROFILE_TARGETS[@]}"; do
+        if [ -e "$profile_target" ]; then
+            cat <<EOF
+ - back up $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX
+ - update $ to include some Nix configuration
+EOF
+        fi
+    done
+    cat <<EOF
+ - load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon
+
+This might look scary, but everything can be undone by running just a
+few commands.
+
+$(uninstall_directions)
+
+We used to ask you to confirm each time sudo ran, but it was too many
+times. Instead, I'll just ask you this one time:
+
+EOF
+    if ui_confirm "Can we use sudo?"; then
+        ok "Yay! Thanks! Let's get going!"
+    else
+        failure <<EOF
+That is okay, but we can't install.
+EOF
+    fi
+}
+
+install_from_extracted_nix() {
+    (
+        cd "$EXTRACTED_NIX_PATH"
+
+        _sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
+              rsync -a "$(pwd)/store/" "$NIX_ROOT/store/"
+
+        if [ -d "$NIX_INSTALLED_NIX" ]; then
+            echo "      Alright! We have our first nix at $NIX_INSTALLED_NIX"
+        else
+            failure <<EOF
+Something went wrong, and I didn't find Nix installed at
+$NIX_INSTALLED_NIX.
+EOF
+        fi
+
+        _sudo "to initialize the Nix Database" \
+              $NIX_INSTALLED_NIX/bin/nix-store --init
+
+        cat ./.reginfo \
+            | _sudo "to load data for the first time in to the Nix Database" \
+                   "$NIX_INSTALLED_NIX/bin/nix-store" --load-db
+
+        echo "      Just finished getting the nix database ready."
+    )
+}
+
+shell_source_lines() {
+    cat <<EOF
+
+# Nix
+if [ -e '$PROFILE_NIX_FILE' ]; then
+  . '$PROFILE_NIX_FILE'
+fi
+# End Nix
+
+EOF
+}
+configure_shell_profile() {
+    cat <<'EOF' > "$SCRATCH/$PROFILE_NIX_FILE_NAME"
+# Only execute this file once per shell.
+if [ -n "$__ETC_PROFILE_NIX_SOURCED" ]; then return; fi
+__ETC_PROFILE_NIX_SOURCED=1
+
+# Set up secure multi-user builds: non-root users build through the
+# Nix daemon.
+if [ "$USER" != root -o ! -w /nix/var/nix/db ]; then
+    export NIX_REMOTE=daemon
+fi
+
+export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
+export NIX_PROFILES="/run/current-system/sw /nix/var/nix/profiles/default $HOME/.nix-profile"
+
+# Set up the per-user profile.
+mkdir -m 0755 -p $NIX_USER_PROFILE_DIR
+if test "$(stat -f '%u' $NIX_USER_PROFILE_DIR)" != "$(id -u)"; then
+    echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2
+fi
+
+if test -w $HOME; then
+  if ! test -L $HOME/.nix-profile; then
+      if test "$USER" != root; then
+          ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile
+      else
+          # Root installs in the system-wide profile by default.
+          ln -s /nix/var/nix/profiles/default $HOME/.nix-profile
+      fi
+  fi
+
+  # Subscribe the root user to the NixOS channel by default.
+  if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
+      echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels
+  fi
+
+  # Create the per-user garbage collector roots directory.
+  NIX_USER_GCROOTS_DIR=/nix/var/nix/gcroots/per-user/$USER
+  mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR
+  if test "$(stat -f '%u' $NIX_USER_GCROOTS_DIR)" != "$(id -u)"; then
+      echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2
+  fi
+
+  # Set up a default Nix expression from which to install stuff.
+  if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
+      rm -f $HOME/.nix-defexpr
+      mkdir -p $HOME/.nix-defexpr
+      if [ "$USER" != root ]; then
+          ln -s /nix/var/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
+      fi
+  fi
+fi
+
+export NIX_SSL_CERT_FILE="/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
+export NIX_PATH="/nix/var/nix/profiles/per-user/root/channels"
+export PATH="$HOME/.nix-profile/bin:$HOME/.nix-profile/sbin:$HOME/.nix-profile/lib/kde4/libexec:/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/nix/var/nix/profiles/default/lib/kde4/libexec:$PATH"
+
+EOF
+
+    _sudo "put our custom profile code at $PROFILE_NIX_FILE with nix-daemon settings" \
+          install -m 0444 "$SCRATCH/$PROFILE_NIX_FILE_NAME" "$PROFILE_NIX_FILE_DIR"
+
+
+    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"
+
+            shell_source_lines \
+                | _sudo "extend your $profile_target with nix-daemon settings" \
+                        tee -a "$profile_target"
+        fi
+    done
+
+}
+
+setup_default_profile() {
+    _sudo "to installing a bootstrapping Nix in to the default Profile" \
+          -i "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
+
+    _sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
+          -i "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
+
+    _sudo "to update the default channel in the default profile" \
+          -i NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs
+
+    _sudo "to replace the bootstrapping Nix with a real Nix" \
+          -i NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-env" -iA nixpkgs.nix
+}
+
+
+place_nix_configuration() {
+    cat <<EOF > "$SCRATCH/nix.conf"
+build-users-group = $NIX_BUILD_GROUP_NAME
+
+build-max-jobs = $NIX_USER_COUNT
+build-cores = 1
+build-use-sandbox = false
+
+binary-caches = https://cache.nixos.org/
+trusted-binary-caches =
+binary-cache-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
+signed-binary-caches = *
+
+trusted-users = root
+allowed-users = *
+EOF
+    _sudo "to place the default nix daemon configuration (part 2)" \
+          install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
+}
+
+configure_nix_daemon_plist() {
+    _sudo "to set up the nix-daemon as a LaunchDaemon" \
+          ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST"
+
+    _sudo "to load the LaunchDaemon plist for nix-daemon" \
+          launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist
+
+    _sudo "to start the nix-daemon" \
+          launchctl start org.nixos.nix-daemon
+
+}
+
+
+main() {
+    if [ "${PINCH_ME_IM_SILLY:-}" = "" ]; then
+        validate_starting_assumptions
+    fi
+
+    setup_report
+
+    if ! ui_confirm "Ready to continue?"; then
+        ok "Alright, no changes have been made :)"
+        contactme
+        trap finish_cleanup EXIT
+        exit 1
+    fi
+
+    chat_about_sudo
+
+    create_build_group
+    create_build_users
+    create_directories
+    place_channel_configuration
+    install_from_extracted_nix
+
+    configure_shell_profile
+
+    set +eu
+    . /etc/profile
+    set -eu
+
+    setup_default_profile
+    place_nix_configuration
+    configure_nix_daemon_plist
+
+    trap finish_success EXIT
+}
+
+
+main
diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh
index d4eb1c6fbeb9..dd826c423953 100644
--- a/scripts/install-nix-from-closure.sh
+++ b/scripts/install-nix-from-closure.sh
@@ -8,15 +8,8 @@ nix="@nix@"
 cacert="@cacert@"
 
 
-# macOS support for 10.10 or higher
-if [[ "$(uname -s)" = "Darwin" && $(($(sw_vers -productVersion | cut -d '.' -f 2))) -lt 10 ]]; then
-    echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.10 or higher"
-    exit 1
-fi
-
 if ! [ -e "$self/.reginfo" ]; then
     echo "$0: incomplete installer (.reginfo is missing)" >&2
-    exit 1
 fi
 
 if [ -z "$USER" ]; then
@@ -24,6 +17,23 @@ if [ -z "$USER" ]; then
     exit 1
 fi
 
+if [ -z "$HOME" ]; then
+    echo "$0: \$HOME is not set" >&2
+    exit 1
+fi
+
+# macOS support for 10.10 or higher
+if [ "$(uname -s)" = "Darwin" ]; then
+    if [ $(($(sw_vers -productVersion | cut -d '.' -f 2))) -lt 10 ]; then
+        echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.10 or higher"
+        exit 1
+    fi
+
+    printf '\e[1;31mSwitching to the Multi-User Darwin Installer\e[0m\n'
+    "$self/install-darwin-multi-user"
+    exit 0
+fi
+
 if [ "$(id -u)" -eq 0 ]; then
     printf '\e[1;31mwarning: installing Nix as root is not supported by this script!\e[0m\n'
 fi