From 799f5adf79cf49d13c7a12e1ea15a2a3a9f34c30 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Sun, 9 Jul 2017 12:38:32 -0400 Subject: [PATCH 01/15] Shellcheck the existing installer --- release.nix | 5 ++++- scripts/install-nix-from-closure.sh | 31 +++++++++++++++++------------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/release.nix b/release.nix index f8ff01c2..8942d668 100644 --- a/release.nix +++ b/release.nix @@ -123,7 +123,7 @@ let runCommand "nix-binary-tarball-${version}" { exportReferencesGraph = [ "closure1" toplevel "closure2" cacert ]; - buildInputs = [ perl ]; + buildInputs = [ perl shellcheck ]; meta.description = "Distribution-independent Nix bootstrap binaries for ${system}"; } '' @@ -132,6 +132,9 @@ let substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \ --subst-var-by nix ${toplevel} \ --subst-var-by cacert ${cacert} + + shellcheck -e SC1090 $TMPDIR/install + chmod +x $TMPDIR/install dir=nix-${version}-${system} fn=$out/$dir.tar.bz2 diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index 92c3c80c..8c5b8222 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -7,7 +7,7 @@ self="$(dirname "$0")" nix="@nix@" cacert="@cacert@" -if ! [ -e $self/.reginfo ]; then +if ! [ -e "$self/.reginfo" ]; then echo "$0: incomplete installer (.reginfo is missing)" >&2 exit 1 fi @@ -23,6 +23,11 @@ if [ -z "$USER" ]; then exit 1 fi +if [ -z "$HOME" ]; then + echo "$0: \$HOME is not set" >&2 + exit 1 +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 @@ -47,7 +52,7 @@ mkdir -p $dest/store echo -n "copying Nix to $dest/store..." >&2 -for i in $(cd $self/store >/dev/null && echo *); do +for i in $(cd "$self/store" >/dev/null && echo ./*); do echo -n "." >&2 i_tmp="$dest/store/$i.$$" if [ -e "$i_tmp" ]; then @@ -61,39 +66,39 @@ done echo "" >&2 echo "initialising Nix database..." >&2 -if ! $nix/bin/nix-store --init; then +if ! "$nix/bin/nix-store" --init; then echo "$0: failed to initialize the Nix database" >&2 exit 1 fi -if ! $nix/bin/nix-store --load-db < $self/.reginfo; then +if ! "$nix/bin/nix-store" --load-db < "$self/.reginfo"; then echo "$0: unable to register valid paths" >&2 exit 1 fi -. $nix/etc/profile.d/nix.sh +. "$nix/etc/profile.d/nix.sh" -if ! $nix/bin/nix-env -i "$nix"; then +if ! "$nix/bin/nix-env" -i "$nix"; then echo "$0: unable to install Nix into your default profile" >&2 exit 1 fi # Install an SSL certificate bundle. -if [ -z "$NIX_SSL_CERT_FILE" -o ! -f "$NIX_SSL_CERT_FILE" ]; then - $nix/bin/nix-env -i "$cacert" +if [ -z "$NIX_SSL_CERT_FILE" ] || [ ! -f "$NIX_SSL_CERT_FILE" ]; then + "$nix/bin/nix-env" -i "$cacert" export NIX_SSL_CERT_FILE="$HOME/.nix-profile/etc/ssl/certs/ca-bundle.crt" fi # Subscribe the user to the Nixpkgs channel and fetch it. -if ! $nix/bin/nix-channel --list | grep -q "^nixpkgs "; then - $nix/bin/nix-channel --add https://nixos.org/channels/nixpkgs-unstable +if ! "$nix/bin/nix-channel" --list | grep -q "^nixpkgs "; then + "$nix/bin/nix-channel" --add https://nixos.org/channels/nixpkgs-unstable fi if [ -z "$_NIX_INSTALLER_TEST" ]; then - $nix/bin/nix-channel --update nixpkgs + "$nix/bin/nix-channel" --update nixpkgs fi # Make the shell source nix.sh during login. -p=$NIX_LINK/etc/profile.d/nix.sh +p="$NIX_LINK/etc/profile.d/nix.sh" added= for i in .bash_profile .bash_login .profile; do @@ -101,7 +106,7 @@ for i in .bash_profile .bash_login .profile; do if [ -w "$fn" ]; then if ! grep -q "$p" "$fn"; then echo "modifying $fn..." >&2 - echo "if [ -e $p ]; then . $p; fi # added by Nix installer" >> $fn + echo "if [ -e $p ]; then . $p; fi # added by Nix installer" >> "$fn" fi added=1 break From 218978154ae6b24997ec52e65e63edfd90c7ea96 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Sun, 9 Jul 2017 13:07:28 -0400 Subject: [PATCH 02/15] Switch to a fancy multi-user installer on Darwin --- release.nix | 7 +- scripts/install-darwin-multi-user.sh | 808 +++++++++++++++++++++++++++ scripts/install-nix-from-closure.sh | 18 +- 3 files changed, 826 insertions(+), 7 deletions(-) create mode 100644 scripts/install-darwin-multi-user.sh diff --git a/release.nix b/release.nix index 8942d668..6e4660e5 100644 --- a/release.nix +++ b/release.nix @@ -132,10 +132,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 @@ -147,7 +152,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 00000000..87d55b2f --- /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 < $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 < /dev/null >&2; then + failure < /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 < /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 <