diff options
Diffstat (limited to 'third_party/nix/scripts')
-rwxr-xr-x | third_party/nix/scripts/build.sh | 24 | ||||
-rwxr-xr-x | third_party/nix/scripts/daemon.sh | 24 | ||||
-rwxr-xr-x | third_party/nix/scripts/eval.sh | 23 | ||||
-rw-r--r-- | third_party/nix/scripts/install-darwin-multi-user.sh | 144 | ||||
-rw-r--r-- | third_party/nix/scripts/install-multi-user.sh | 798 | ||||
-rw-r--r-- | third_party/nix/scripts/install-nix-from-closure.sh | 180 | ||||
-rwxr-xr-x | third_party/nix/scripts/install-systemd-multi-user.sh | 188 | ||||
-rw-r--r-- | third_party/nix/scripts/install.in | 66 | ||||
-rwxr-xr-x | third_party/nix/scripts/nix-http-export.cgi.in | 51 | ||||
-rw-r--r-- | third_party/nix/scripts/nix-profile-daemon.sh.in | 29 | ||||
-rw-r--r-- | third_party/nix/scripts/nix-profile.sh.in | 39 | ||||
-rwxr-xr-x | third_party/nix/scripts/nix-reduce-build.in | 171 | ||||
-rwxr-xr-x | third_party/nix/scripts/repl.sh | 23 | ||||
-rwxr-xr-x | third_party/nix/scripts/setup_store.sh | 11 |
14 files changed, 1771 insertions, 0 deletions
diff --git a/third_party/nix/scripts/build.sh b/third_party/nix/scripts/build.sh new file mode 100755 index 000000000000..759c9e9f2c12 --- /dev/null +++ b/third_party/nix/scripts/build.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Run `nix build` using a local store, for use during development. Intended to +# be run from the cmake build directory + +set -eo pipefail + +if [ $1 = "--debug" ]; then + run=(gdb --args) + shift 1 +elif [ "$1" = "--rr" ]; then + run=(rr record) + shift 1 +else + run=() +fi + +make -j 10 +NIX_STORE_DIR=$(pwd)/nix/store \ + NIX_LOG_DIR=$(pwd)/nix/var/log/nix \ + NIX_STATE_DIR=$(pwd)/nix/var/nix \ + XDG_CACHE_HOME=$(pwd)/cache \ + NIX_REMOTE=daemon \ + ${run[*]} ./src/nix build "$@" diff --git a/third_party/nix/scripts/daemon.sh b/third_party/nix/scripts/daemon.sh new file mode 100755 index 000000000000..3daa0f139097 --- /dev/null +++ b/third_party/nix/scripts/daemon.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Run a nix daemon using a local store, for use during development. Intended to +# be run from the cmake build directory + +if [ $1 = "--debug" ]; then + run=(gdb --args) + shift 1 +elif [ "$1" = "--rr" ]; then + run=(rr record) + shift 1 +else + run=() +fi + +make -j 10 +NIX_STORE_DIR=$(pwd)/nix/store \ + NIX_LOG_DIR=$(pwd)/nix/var/log/nix \ + NIX_STATE_DIR=$(pwd)/nix/var/nix \ + XDG_CACHE_HOME=$(pwd)/cache \ + NIX_LIBEXEC_DIR=$(pwd) \ + GRPC_TRACE=all \ + ${gdb[*]} ./src/nix-daemon/nix-daemon diff --git a/third_party/nix/scripts/eval.sh b/third_party/nix/scripts/eval.sh new file mode 100755 index 000000000000..f71d9f7931fe --- /dev/null +++ b/third_party/nix/scripts/eval.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Run `nix eval` using a local store, for use during development. Intended to +# be run from the cmake build directory + +if [ "$#" -gt 0 ] && [ "$1" = "--debug" ]; then + gdb=(gdb --args) + shift 1 +elif [ "$1" = "--rr" ]; then + gdb=(rr record) + shift 1 +else + gdb=() +fi + +make -j 10 +NIX_STORE_DIR=$(pwd)/nix/store \ + NIX_LOG_DIR=$(pwd)/nix/var/log/nix \ + NIX_STATE_DIR=$(pwd)/nix/var/nix \ + XDG_CACHE_HOME=$(pwd)/cache \ + NIX_REMOTE=daemon \ + ${gdb[*]} ./src/nix eval "$@" diff --git a/third_party/nix/scripts/install-darwin-multi-user.sh b/third_party/nix/scripts/install-darwin-multi-user.sh new file mode 100644 index 000000000000..49076bd5c03f --- /dev/null +++ b/third_party/nix/scripts/install-darwin-multi-user.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +readonly PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist + +dsclattr() { + /usr/bin/dscl . -read "$1" \ + | awk "/$2/ { print \$2 }" +} + +poly_validate_assumptions() { + if [ "$(uname -s)" != "Darwin" ]; then + failure "This script is for use with macOS!" + fi +} + +poly_service_installed_check() { + [ -e "$PLIST_DEST" ] +} + +poly_service_uninstall_directions() { + cat <<EOF +$1. Delete $PLIST_DEST + + sudo launchctl unload $PLIST_DEST + sudo rm $PLIST_DEST + +EOF +} + +poly_service_setup_note() { + cat <<EOF + - load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon + +EOF +} + +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" + + _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 + +} + +poly_group_exists() { + /usr/bin/dscl . -read "/Groups/$1" > /dev/null 2>&1 +} + +poly_group_id_get() { + dsclattr "/Groups/$1" "PrimaryGroupID" +} + +poly_create_build_group() { + _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 +} + +poly_user_exists() { + /usr/bin/dscl . -read "/Users/$1" > /dev/null 2>&1 +} + +poly_user_id_get() { + dsclattr "/Users/$1" "UniqueID" +} + +poly_user_hidden_get() { + dsclattr "/Users/$1" "IsHidden" +} + +poly_user_hidden_set() { + _sudo "in order to make $1 a hidden user" \ + /usr/bin/dscl . -create "/Users/$1" "IsHidden" "1" +} + +poly_user_home_get() { + dsclattr "/Users/$1" "NFSHomeDirectory" +} + +poly_user_home_set() { + _sudo "in order to give $1 a safe home directory" \ + /usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2" +} + +poly_user_note_get() { + dsclattr "/Users/$1" "RealName" +} + +poly_user_note_set() { + _sudo "in order to give $username a useful note" \ + /usr/bin/dscl . -create "/Users/$1" "RealName" "$2" +} + +poly_user_shell_get() { + dsclattr "/Users/$1" "UserShell" +} + +poly_user_shell_set() { + _sudo "in order to give $1 a safe home directory" \ + /usr/bin/dscl . -create "/Users/$1" "UserShell" "$2" +} + +poly_user_in_group_check() { + username=$1 + group=$2 + dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1 +} + +poly_user_in_group_set() { + username=$1 + group=$2 + + _sudo "Add $username to the $group group"\ + /usr/sbin/dseditgroup -o edit -t user \ + -a "$username" "$group" +} + +poly_user_primary_group_get() { + dsclattr "/Users/$1" "PrimaryGroupID" +} + +poly_user_primary_group_set() { + _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 "/Users/$1" "PrimaryGroupID" "$2" +} + +poly_create_build_user() { + username=$1 + uid=$2 + builder_num=$3 + + _sudo "Creating the Nix build user (#$builder_num), $username" \ + /usr/bin/dscl . create "/Users/$username" \ + UniqueID "${uid}" +} diff --git a/third_party/nix/scripts/install-multi-user.sh b/third_party/nix/scripts/install-multi-user.sh new file mode 100644 index 000000000000..5233762fa649 --- /dev/null +++ b/third_party/nix/scripts/install-multi-user.sh @@ -0,0 +1,798 @@ +#!/usr/bin/env 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[1m' +readonly BLUE='\033[34m' +readonly BLUE_UL='\033[4;34m' +readonly GREEN='\033[32m' +readonly GREEN_UL='\033[4;32m' +readonly RED='\033[31m' + +readonly NIX_USER_COUNT="32" +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 PROFILE_TARGETS=("/etc/bashrc" "/etc/profile.d/nix.sh" "/etc/zshrc") +readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix" +readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" + +readonly NIX_INSTALLED_NIX="@nix@" +readonly NIX_INSTALLED_CACERT="@cacert@" +readonly EXTRACTED_NIX_PATH="$(dirname "$0")" + +readonly ROOT_HOME=$(echo ~root) + +if [ -t 0 ]; then + readonly IS_HEADLESS='no' +else + readonly IS_HEADLESS='yes' +fi + +headless() { + if [ "$IS_HEADLESS" = "yes" ]; then + return 0 + else + return 1 + fi +} + +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=0 + + if poly_service_installed_check; then + step=$((step + 1)) + poly_service_uninstall_directions "$step" + fi + + for profile_target in "${PROFILE_TARGETS[@]}"; do + if [ -e "$profile_target" ] && [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then + step=$((step + 1)) + cat <<EOF +$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target + + 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)) +} + +_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" + + if headless; then + echo "No TTY, assuming you would say yes :)" + return 0 + fi + + 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 "" + printf " $ sudo %s\\n" "$cmd" + echo "" + echo "$expl" + echo "" + + return 0 +} + +_sudo() { + local expl="$1" + shift + if ! headless; then + __sudo "$expl" "$*" + fi + sudo "$@" +} + + +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 + +channel_update_failed=0 +function finish_success { + finish_cleanup + + ok "Alright! We're done!" + if [ "x$channel_update_failed" = x1 ]; then + echo "" + echo "But fetching the nixpkgs channel failed. (Are you offline?)" + echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"." + fi + 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 +} + + +validate_starting_assumptions() { + poly_validate_assumptions + + 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. + +$(uninstall_directions) +EOF + fi + fi + done + + if [ -d /nix/store ] || [ -d /nix/var ]; 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 [ -e "$profile_target" ] && 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 + + danger_paths=("$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.nix-profile") + for danger_path in "${danger_paths[@]}"; do + if _sudo "making sure that $danger_path doesn't exist" \ + test -e "$danger_path"; then + failure <<EOF +I found a file at $danger_path, which is a relic of a previous +installation. You must first delete this file before continuing. + +$(uninstall_directions) +EOF + fi + done +} + +setup_report() { + 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" + if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" != "" ]; then + row "Preexisting Install" "Allowed" + fi + + 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 ! poly_group_exists "$NIX_BUILD_GROUP_NAME"; then + poly_create_build_group + row " Created" "Yes" + else + primary_group_id=$(poly_group_id_get "$NIX_BUILD_GROUP_NAME") + 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") + + task "Setting up the build user $username" + + if ! poly_user_exists "$username"; then + poly_create_build_user "$username" "$uid" "$coreid" + row " Created" "Yes" + else + actual_uid=$(poly_user_id_get "$username") + if [ "$actual_uid" != "$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 [ "$(poly_user_hidden_get "$username")" = "1" ]; then + row " Hidden" "Yes" + else + poly_user_hidden_set "$username" + row " Hidden" "Yes" + fi + + if [ "$(poly_user_home_get "$username")" = "/var/empty" ]; then + row " Home Directory" "/var/empty" + else + poly_user_home_set "$username" "/var/empty" + row " Home Directory" "/var/empty" + fi + + # We use grep instead of an equality check because it is difficult + # to extract _just_ the user's note, instead it is prefixed with + # some plist junk. This was causing the user note to always be set, + # even if there was no reason for it. + if ! poly_user_note_get "$username" | grep -q "Nix build user $coreid"; then + row " Note" "Nix build user $coreid" + else + poly_user_note_set "$username" "Nix build user $coreid" + row " Note" "Nix build user $coreid" + fi + + if [ "$(poly_user_shell_get "$username")" = "/sbin/nologin" ]; then + row " Logins Disabled" "Yes" + else + poly_user_shell_set "$username" "/sbin/nologin" + row " Logins Disabled" "Yes" + fi + + if poly_user_in_group_check "$username" "$NIX_BUILD_GROUP_NAME"; then + row " Member of $NIX_BUILD_GROUP_NAME" "Yes" + else + poly_user_in_group_set "$username" "$NIX_BUILD_GROUP_NAME" + row " Member of $NIX_BUILD_GROUP_NAME" "Yes" + fi + + if [ "$(poly_user_primary_group_get "$username")" = "$NIX_BUILD_GROUP_ID" ]; then + row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID" + else + poly_user_primary_group_set "$username" "$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() { + # FIXME: remove all of this because it duplicates LocalStore::LocalStore(). + + _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} /nix/var/nix/{gcroots,profiles}/per-user + + _sudo "to make the basic directory structure of Nix (part 2)" \ + mkdir -pv -m 1775 /nix/store + + _sudo "to make the basic directory structure of Nix (part 3)" \ + chgrp "$NIX_BUILD_GROUP_NAME" /nix/store + + _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" +} + +welcome_to_nix() { + ok "Welcome to the Multi-User Nix Installation" + + cat <<EOF + +This installation tool will set up your computer with the Nix package +manager. This will happen in a few stages: + +1. Make sure your computer doesn't already have Nix. If it does, I + will show you instructions on how to clean up your old one. + +2. Show you what we are going to install and where. Then we will ask + if you are ready to continue. + +3. Create the system users and groups that the Nix daemon uses to run + builds. + +4. Perform the basic installation of the Nix files daemon. + +5. Configure your shell to import special Nix Profile files, so you + can use Nix. + +6. Start the Nix daemon. + +EOF + + if ui_confirm "Would you like to see a more detailed list of what we will do?"; then + cat <<EOF + +We will: + + - make sure your computer doesn't already have Nix files + (if it does, I will tell you how to clean them up.) + - 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 +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 $profile_target to include some Nix configuration +EOF + fi + done + poly_service_setup_note + if ! ui_confirm "Ready to continue?"; then + failure <<EOF +Okay, maybe you would like to talk to the team. +EOF + fi + fi +} + +chat_about_sudo() { + header "let's talk about sudo" + + if headless; then + cat <<EOF +This script is going to call sudo a lot. Normally, it would show you +exactly what commands it is running and why. However, the script is +run in a headless fashion, like this: + + $ curl https://nixos.org/nix/install | sh + +or maybe in a CI pipeline. Because of that, we're going to skip the +verbose output in the interest of brevity. + +If you would like to +see the output, try like this: + + $ curl -o install-nix https://nixos.org/nix/install + $ sh ./install-nix + +EOF + return 0 + fi + + 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 + +This might look scary, but everything can be undone by running just a +few commands. 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 -rlpt ./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 + + 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() { + # 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" + + 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" \ + HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX" + + if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ]; then + _sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \ + HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT" + export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt + fi + + # Have to explicitly pass NIX_SSL_CERT_FILE as part of the sudo call, + # otherwise it will be lost in environments where sudo doesn't pass + # all the environment variables by default. + _sudo "to update the default channel in the default profile" \ + HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs \ + || channel_update_failed=1 + +} + + +place_nix_configuration() { + cat <<EOF > "$SCRATCH/nix.conf" +build-users-group = $NIX_BUILD_GROUP_NAME +EOF + _sudo "to place the default nix daemon configuration (part 2)" \ + install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf +} + +main() { + if [ "$(uname -s)" = "Darwin" ]; then + # shellcheck source=./install-darwin-multi-user.sh + . "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh" + elif [ "$(uname -s)" = "Linux" ]; then + if [ -e /run/systemd/system ]; then + # shellcheck source=./install-systemd-multi-user.sh + . "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh" + else + failure "Sorry, the multi-user installation requires systemd on Linux (detected using /run/systemd/system)" + fi + else + failure "Sorry, I don't know what to do on $(uname)" + fi + + welcome_to_nix + chat_about_sudo + + if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" = "" ]; 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 + + 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 + poly_configure_nix_daemon_service + + trap finish_success EXIT +} + + +main diff --git a/third_party/nix/scripts/install-nix-from-closure.sh b/third_party/nix/scripts/install-nix-from-closure.sh new file mode 100644 index 000000000000..3f15818547ab --- /dev/null +++ b/third_party/nix/scripts/install-nix-from-closure.sh @@ -0,0 +1,180 @@ +#!/bin/sh + +set -e + +dest="/nix" +self="$(dirname "$0")" +nix="@nix@" +cacert="@cacert@" + + +if ! [ -e "$self/.reginfo" ]; then + echo "$0: incomplete installer (.reginfo is missing)" >&2 +fi + +if [ -z "$USER" ] && ! USER=$(id -u -n); then + echo "$0: \$USER is not set" >&2 + exit 1 +fi + +if [ -z "$HOME" ]; then + echo "$0: \$HOME is not set" >&2 + exit 1 +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 + echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher" + exit 1 + fi +fi + +# Determine if we could use the multi-user installer or not +if [ "$(uname -s)" = "Darwin" ]; then + echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2 +elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then + echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2 +fi + +INSTALL_MODE=no-daemon +# Trivially handle the --daemon / --no-daemon options +if [ "x${1:-}" = "x--no-daemon" ]; then + INSTALL_MODE=no-daemon +elif [ "x${1:-}" = "x--daemon" ]; then + INSTALL_MODE=daemon +elif [ "x${1:-}" != "x" ]; then + ( + echo "Nix Installer [--daemon|--no-daemon]" + + 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 "" + ) >&2 + exit +fi + +if [ "$INSTALL_MODE" = "daemon" ]; then + printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n' + exec "$self/install-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 + +echo "performing a single-user installation of Nix..." >&2 + +if ! [ -e $dest ]; then + cmd="mkdir -m 0755 $dest && chown $USER $dest" + 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 + exit 1 + fi +fi + +if ! [ -w $dest ]; then + echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see http://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2 + exit 1 +fi + +mkdir -p $dest/store + +printf "copying Nix to %s..." "${dest}/store" >&2 + +for i in $(cd "$self/store" >/dev/null && echo ./*); do + printf "." >&2 + i_tmp="$dest/store/$i.$$" + if [ -e "$i_tmp" ]; then + rm -rf "$i_tmp" + fi + if ! [ -e "$dest/store/$i" ]; then + cp -Rp "$self/store/$i" "$i_tmp" + chmod -R a-w "$i_tmp" + chmod +w "$i_tmp" + mv "$i_tmp" "$dest/store/$i" + chmod -w "$dest/store/$i" + fi +done +echo "" >&2 + +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" + +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" ] || ! [ -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 +fi +if [ -z "$_NIX_INSTALLER_TEST" ]; then + if ! $nix/bin/nix-channel --update nixpkgs; then + echo "Fetching the nixpkgs channel failed. (Are you offline?)" + echo "To try again later, run \"nix-channel --update nixpkgs\"." + fi +fi + +added= +p=$HOME/.nix-profile/etc/profile.d/nix.sh +if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then + # Make the shell source nix.sh during login. + for i in .bash_profile .bash_login .profile; do + fn="$HOME/$i" + 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" + fi + added=1 + break + fi + done +fi + +if [ -z "$added" ]; then + cat >&2 <<EOF + +Installation finished! To ensure that the necessary environment +variables are set, please add the line + + . $p + +to your shell profile (e.g. ~/.profile). +EOF +else + cat >&2 <<EOF + +Installation finished! To ensure that the necessary environment +variables are set, either log in again, or type + + . $p + +in your shell. +EOF +fi diff --git a/third_party/nix/scripts/install-systemd-multi-user.sh b/third_party/nix/scripts/install-systemd-multi-user.sh new file mode 100755 index 000000000000..bef3ac4f991f --- /dev/null +++ b/third_party/nix/scripts/install-systemd-multi-user.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service +readonly SERVICE_DEST=/etc/systemd/system/nix-daemon.service + +readonly SOCKET_SRC=/lib/systemd/system/nix-daemon.socket +readonly SOCKET_DEST=/etc/systemd/system/nix-daemon.socket + + +# Path for the systemd override unit file to contain the proxy settings +readonly SERVICE_OVERRIDE=${SERVICE_DEST}.d/override.conf + +create_systemd_override() { + header "Configuring proxy for the nix-daemon service" + _sudo "create directory for systemd unit override" mkdir -p "$(dirname $SERVICE_OVERRIDE)" + cat <<EOF | _sudo "create systemd unit override" tee "$SERVICE_OVERRIDE" +[Service] +$1 +EOF +} + +# Gather all non-empty proxy environment variables into a string +create_systemd_proxy_env() { + vars="http_proxy https_proxy ftp_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY" + for v in $vars; do + if [ "x${!v:-}" != "x" ]; then + echo "Environment=${v}=${!v}" + fi + done +} + +handle_network_proxy() { + # Create a systemd unit override with proxy environment variables + # if any proxy environment variables are not empty. + PROXY_ENV_STRING=$(create_systemd_proxy_env) + if [ -n "${PROXY_ENV_STRING}" ]; then + create_systemd_override "${PROXY_ENV_STRING}" + fi +} + +poly_validate_assumptions() { + if [ "$(uname -s)" != "Linux" ]; then + failure "This script is for use with Linux!" + fi +} + +poly_service_installed_check() { + [ "$(systemctl is-enabled nix-daemon.service)" = "linked" ] \ + || [ "$(systemctl is-enabled nix-daemon.socket)" = "enabled" ] +} + +poly_service_uninstall_directions() { + cat <<EOF +$1. Delete the systemd service and socket units + + sudo systemctl stop nix-daemon.socket + sudo systemctl stop nix-daemon.service + sudo systemctl disable nix-daemon.socket + sudo systemctl disable nix-daemon.service + sudo systemctl daemon-reload +EOF +} + +poly_service_setup_note() { + cat <<EOF + - load and start a service (at $SERVICE_DEST + and $SOCKET_DEST) for nix-daemon + +EOF +} + +poly_configure_nix_daemon_service() { + _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" + + handle_network_proxy + + _sudo "to load the systemd unit for nix-daemon" \ + systemctl daemon-reload + + _sudo "to start the nix-daemon.socket" \ + systemctl start nix-daemon.socket + + _sudo "to start the nix-daemon.service" \ + systemctl start nix-daemon.service + +} + +poly_group_exists() { + getent group "$1" > /dev/null 2>&1 +} + +poly_group_id_get() { + getent group "$1" | cut -d: -f3 +} + +poly_create_build_group() { + _sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \ + groupadd -g "$NIX_BUILD_GROUP_ID" --system \ + "$NIX_BUILD_GROUP_NAME" >&2 +} + +poly_user_exists() { + getent passwd "$1" > /dev/null 2>&1 +} + +poly_user_id_get() { + getent passwd "$1" | cut -d: -f3 +} + +poly_user_hidden_get() { + echo "1" +} + +poly_user_hidden_set() { + true +} + +poly_user_home_get() { + getent passwd "$1" | cut -d: -f6 +} + +poly_user_home_set() { + _sudo "in order to give $1 a safe home directory" \ + usermod --home "$2" "$1" +} + +poly_user_note_get() { + getent passwd "$1" | cut -d: -f5 +} + +poly_user_note_set() { + _sudo "in order to give $1 a useful comment" \ + usermod --comment "$2" "$1" +} + +poly_user_shell_get() { + getent passwd "$1" | cut -d: -f7 +} + +poly_user_shell_set() { + _sudo "in order to prevent $1 from logging in" \ + usermod --shell "$2" "$1" +} + +poly_user_in_group_check() { + groups "$1" | grep -q "$2" > /dev/null 2>&1 +} + +poly_user_in_group_set() { + _sudo "Add $1 to the $2 group"\ + usermod --append --groups "$2" "$1" +} + +poly_user_primary_group_get() { + getent passwd "$1" | cut -d: -f4 +} + +poly_user_primary_group_set() { + _sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \ + usermod --gid "$2" "$1" + +} + +poly_create_build_user() { + username=$1 + uid=$2 + builder_num=$3 + + _sudo "Creating the Nix build user, $username" \ + useradd \ + --home-dir /var/empty \ + --comment "Nix build user $builder_num" \ + --gid "$NIX_BUILD_GROUP_ID" \ + --groups "$NIX_BUILD_GROUP_NAME" \ + --no-user-group \ + --system \ + --shell /sbin/nologin \ + --uid "$uid" \ + --password "!" \ + "$username" +} diff --git a/third_party/nix/scripts/install.in b/third_party/nix/scripts/install.in new file mode 100644 index 000000000000..902758b138a5 --- /dev/null +++ b/third_party/nix/scripts/install.in @@ -0,0 +1,66 @@ +#!/bin/sh + +# This script installs the Nix package manager on your system by +# downloading a binary distribution and running its installer script +# (which in turn creates and populates /nix). + +{ # Prevent execution if this script was only partially downloaded +oops() { + echo "$0:" "$@" >&2 + exit 1 +} + +tmpDir="$(mktemp -d -t nix-binary-tarball-unpack.XXXXXXXXXX || \ + oops "Can't create temporary directory for downloading the Nix binary tarball")" +cleanup() { + rm -rf "$tmpDir" +} +trap cleanup EXIT INT QUIT TERM + +require_util() { + command -v "$1" > /dev/null 2>&1 || + oops "you do not have '$1' installed, which I need to $2" +} + +case "$(uname -s).$(uname -m)" in + Linux.x86_64) system=x86_64-linux; hash=@binaryTarball_x86_64-linux@;; + Linux.i?86) system=i686-linux; hash=@binaryTarball_i686-linux@;; + Linux.aarch64) system=aarch64-linux; hash=@binaryTarball_aarch64-linux@;; + Darwin.x86_64) system=x86_64-darwin; hash=@binaryTarball_x86_64-darwin@;; + *) oops "sorry, there is no binary distribution of Nix for your platform";; +esac + +url="https://nixos.org/releases/nix/nix-@nixVersion@/nix-@nixVersion@-$system.tar.xz" + +tarball="$tmpDir/$(basename "$tmpDir/nix-@nixVersion@-$system.tar.xz")" + +require_util curl "download the binary tarball" +require_util tar "unpack the binary tarball" + +echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..." +curl -L "$url" -o "$tarball" || oops "failed to download '$url'" + +if command -v sha256sum > /dev/null 2>&1; then + hash2="$(sha256sum -b "$tarball" | cut -c1-64)" +elif command -v shasum > /dev/null 2>&1; then + hash2="$(shasum -a 256 -b "$tarball" | cut -c1-64)" +elif command -v openssl > /dev/null 2>&1; then + hash2="$(openssl dgst -r -sha256 "$tarball" | cut -c1-64)" +else + oops "cannot verify the SHA-256 hash of '$url'; you need one of 'shasum', 'sha256sum', or 'openssl'" +fi + +if [ "$hash" != "$hash2" ]; then + oops "SHA-256 hash mismatch in '$url'; expected $hash, got $hash2" +fi + +unpack=$tmpDir/unpack +mkdir -p "$unpack" +tar -xf "$tarball" -C "$unpack" || oops "failed to unpack '$url'" + +script=$(echo "$unpack"/*/install) + +[ -e "$script" ] || oops "installation script is missing from the binary tarball!" +"$script" "$@" + +} # End of wrapping diff --git a/third_party/nix/scripts/nix-http-export.cgi.in b/third_party/nix/scripts/nix-http-export.cgi.in new file mode 100755 index 000000000000..19a505af1c50 --- /dev/null +++ b/third_party/nix/scripts/nix-http-export.cgi.in @@ -0,0 +1,51 @@ +#! /bin/sh + +export HOME=/tmp +export NIX_REMOTE=daemon + +TMP_DIR="${TMP_DIR:-/tmp/nix-export}" + +@coreutils@/mkdir -p "$TMP_DIR" || true +@coreutils@/chmod a+r "$TMP_DIR" + +needed_path="?$QUERY_STRING" +needed_path="${needed_path#*[?&]needed_path=}" +needed_path="${needed_path%%&*}" +#needed_path="$(echo $needed_path | ./unhttp)" +needed_path="${needed_path//%2B/+}" +needed_path="${needed_path//%3D/=}" + +echo needed_path: "$needed_path" >&2 + +NIX_STORE="${NIX_STORE_DIR:-/nix/store}" + +echo NIX_STORE: "${NIX_STORE}" >&2 + +full_path="${NIX_STORE}"/"$needed_path" + +if [ "$needed_path" != "${needed_path%.drv}" ]; then + echo "Status: 403 You should create the derivation file yourself" + echo "Content-Type: text/plain" + echo + echo "Refusing to disclose derivation contents" + exit +fi + +if @bindir@/nix-store --check-validity "$full_path"; then + if ! [ -e nix-export/"$needed_path".nar.gz ]; then + @bindir@/nix-store --export "$full_path" | @gzip@ > "$TMP_DIR"/"$needed_path".nar.gz + @coreutils@/ln -fs "$TMP_DIR"/"$needed_path".nar.gz nix-export/"$needed_path".nar.gz + fi; + echo "Status: 301 Moved" + echo "Location: nix-export/"$needed_path".nar.gz" + echo +else + echo "Status: 404 No such path found" + echo "Content-Type: text/plain" + echo + echo "Path not found:" + echo "$needed_path" + echo "checked:" + echo "$full_path" +fi + diff --git a/third_party/nix/scripts/nix-profile-daemon.sh.in b/third_party/nix/scripts/nix-profile-daemon.sh.in new file mode 100644 index 000000000000..47655080a674 --- /dev/null +++ b/third_party/nix/scripts/nix-profile-daemon.sh.in @@ -0,0 +1,29 @@ +# Only execute this file once per shell. +if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi +__ETC_PROFILE_NIX_SOURCED=1 + +export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER" +export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile" + +# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. +if [ ! -z "${NIX_SSL_CERT_FILE:-}" ]; then + : # Allow users to override the NIX_SSL_CERT_FILE +elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch + export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt +elif [ -e /etc/ssl/ca-bundle.pem ]; then # openSUSE Tumbleweed + export NIX_SSL_CERT_FILE=/etc/ssl/ca-bundle.pem +elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS + export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt +elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS + export NIX_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt +else + # Fall back to what is in the nix profiles, favouring whatever is defined last. + for i in $NIX_PROFILES; do + if [ -e $i/etc/ssl/certs/ca-bundle.crt ]; then + export NIX_SSL_CERT_FILE=$i/etc/ssl/certs/ca-bundle.crt + fi + done +fi + +export NIX_PATH="nixpkgs=@localstatedir@/nix/profiles/per-user/root/channels/nixpkgs:@localstatedir@/nix/profiles/per-user/root/channels" +export PATH="$HOME/.nix-profile/bin:@localstatedir@/nix/profiles/default/bin:$PATH" diff --git a/third_party/nix/scripts/nix-profile.sh.in b/third_party/nix/scripts/nix-profile.sh.in new file mode 100644 index 000000000000..e15f7cd46b76 --- /dev/null +++ b/third_party/nix/scripts/nix-profile.sh.in @@ -0,0 +1,39 @@ +if [ -n "$HOME" ] && [ -n "$USER" ]; then + + # Set up the per-user profile. + # This part should be kept in sync with nixpkgs:nixos/modules/programs/shell.nix + + NIX_LINK=$HOME/.nix-profile + + NIX_USER_PROFILE_DIR=@localstatedir@/nix/profiles/per-user/$USER + + # Append ~/.nix-defexpr/channels to $NIX_PATH so that <nixpkgs> + # paths work when the user has fetched the Nixpkgs channel. + export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels + + # Set up environment. + # This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix + export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile" + + # Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. + if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch + export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + elif [ -e /etc/ssl/ca-bundle.pem ]; then # openSUSE Tumbleweed + export NIX_SSL_CERT_FILE=/etc/ssl/ca-bundle.pem + elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS + export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt + elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS + export NIX_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt + elif [ -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" ]; then # fall back to cacert in Nix profile + export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ssl/certs/ca-bundle.crt" + elif [ -e "$NIX_LINK/etc/ca-bundle.crt" ]; then # old cacert in Nix profile + export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt" + fi + + if [ -n "${MANPATH-}" ]; then + export MANPATH="$NIX_LINK/share/man:$MANPATH" + fi + + export PATH="$NIX_LINK/bin:$PATH" + unset NIX_LINK NIX_USER_PROFILE_DIR +fi diff --git a/third_party/nix/scripts/nix-reduce-build.in b/third_party/nix/scripts/nix-reduce-build.in new file mode 100755 index 000000000000..50beb9d10b16 --- /dev/null +++ b/third_party/nix/scripts/nix-reduce-build.in @@ -0,0 +1,171 @@ +#! @bash@ + +WORKING_DIRECTORY=$(mktemp -d "${TMPDIR:-/tmp}"/nix-reduce-build-XXXXXX); +cd "$WORKING_DIRECTORY"; + +if test -z "$1" || test "a--help" = "a$1" ; then + echo 'nix-reduce-build (paths or Nix expressions) -- (package sources)' >&2 + echo As in: >&2 + echo nix-reduce-build /etc/nixos/nixos -- ssh://user@somewhere.nowhere.example.org >&2 + echo nix-reduce-build /etc/nixos/nixos -- \\ + echo " " \''http://somewhere.nowhere.example.org/nix/nix-http-export.cgi?needed_path='\' >&2 + echo " store path name will be added into the end of the URL" >&2 + echo nix-reduce-build /etc/nixos/nixos -- file://home/user/nar/ >&2 + echo " that should be a directory where gzipped 'nix-store --export' ">&2 + echo " files are located (they should have .nar.gz extension)" >&2 + echo " Or all together: " >&2 + echo -e nix-reduce-build /expr.nix /e2.nix -- \\\\\\\n\ + " ssh://a@b.example.com http://n.example.com/get-nar?q= file://nar/" >&2 + echo " Also supports best-effort local builds of failing expression set:" >&2 + echo "nix-reduce-build /e.nix -- nix-daemon:// nix-self://" >&2 + echo " nix-daemon:// builds using daemon" + echo " nix-self:// builds directly using nix-store from current installation" >&2 + echo " nix-daemon-fixed:// and nix-self-fixed:// do the same, but only for" >&2; + echo "derivations with specified output hash (sha256, sha1 or md5)." >&2 + echo " nix-daemon-substitute:// and nix-self-substitute:// try to substitute" >&2; + echo "maximum amount of paths" >&2; + echo " nix-daemon-build:// and nix-self-build:// try to build (not substitute)" >&2; + echo "maximum amount of paths" >&2; + echo " If no package sources are specified, required paths are listed." >&2; + exit; +fi; + +while ! test "$1" = "--" || test "$1" = "" ; do + echo "$1" >> initial; >&2 + shift; +done +shift; +echo Will work on $(cat initial | wc -l) targets. >&2 + +while read ; do + case "$REPLY" in + ${NIX_STORE_DIR:-/nix/store}/*) + echo "$REPLY" >> paths; >&2 + ;; + *) + ( + IFS=: ; + nix-instantiate $REPLY >> paths; + ); + ;; + esac; +done < initial; +echo Proceeding $(cat paths | wc -l) paths. >&2 + +while read; do + case "$REPLY" in + *.drv) + echo "$REPLY" >> derivers; >&2 + ;; + *) + nix-store --query --deriver "$REPLY" >>derivers; + ;; + esac; +done < paths; +echo Found $(cat derivers | wc -l) derivers. >&2 + +cat derivers | xargs nix-store --query -R > derivers-closure; +echo Proceeding at most $(cat derivers-closure | wc -l) derivers. >&2 + +cat derivers-closure | egrep '[.]drv$' | xargs nix-store --query --outputs > wanted-paths; +cat derivers-closure | egrep -v '[.]drv$' >> wanted-paths; +echo Prepared $(cat wanted-paths | wc -l) paths to get. >&2 + +cat wanted-paths | xargs nix-store --check-validity --print-invalid > needed-paths; +echo We need $(cat needed-paths | wc -l) paths. >&2 + +egrep '[.]drv$' derivers-closure > critical-derivers; + +if test -z "$1" ; then + cat needed-paths; +fi; + +refresh_critical_derivers() { + echo "Finding needed derivers..." >&2; + cat critical-derivers | while read; do + if ! (nix-store --query --outputs "$REPLY" | xargs nix-store --check-validity &> /dev/null;); then + echo "$REPLY"; + fi; + done > new-critical-derivers; + mv new-critical-derivers critical-derivers; + echo The needed paths are realized by $(cat critical-derivers | wc -l) derivers. >&2 +} + +build_here() { + cat critical-derivers | while read; do + echo "Realising $REPLY using nix-daemon" >&2 + @bindir@/nix-store -r "${REPLY}" + done; +} + +try_to_substitute(){ + cat needed-paths | while read ; do + echo "Building $REPLY using nix-daemon" >&2 + @bindir@/nix-store -r "${NIX_STORE_DIR:-/nix/store}/${REPLY##*/}" + done; +} + +for i in "$@"; do + sshHost="${i#ssh://}"; + httpHost="${i#http://}"; + httpsHost="${i#https://}"; + filePath="${i#file:/}"; + if [ "$i" != "$sshHost" ]; then + cat needed-paths | while read; do + echo "Getting $REPLY and its closure over ssh" >&2 + nix-copy-closure --from "$sshHost" --gzip "$REPLY" </dev/null || true; + done; + elif [ "$i" != "$httpHost" ] || [ "$i" != "$httpsHost" ]; then + cat needed-paths | while read; do + echo "Getting $REPLY over http/https" >&2 + curl ${BAD_CERTIFICATE:+-k} -L "$i${REPLY##*/}" | gunzip | nix-store --import; + done; + elif [ "$i" != "$filePath" ] ; then + cat needed-paths | while read; do + echo "Installing $REPLY from file" >&2 + gunzip < "$filePath/${REPLY##*/}".nar.gz | nix-store --import; + done; + elif [ "$i" = "nix-daemon://" ] ; then + NIX_REMOTE=daemon try_to_substitute; + refresh_critical_derivers; + NIX_REMOTE=daemon build_here; + elif [ "$i" = "nix-self://" ] ; then + NIX_REMOTE= try_to_substitute; + refresh_critical_derivers; + NIX_REMOTE= build_here; + elif [ "$i" = "nix-daemon-fixed://" ] ; then + refresh_critical_derivers; + + cat critical-derivers | while read; do + if egrep '"(md5|sha1|sha256)"' "$REPLY" &>/dev/null; then + echo "Realising $REPLY using nix-daemon" >&2 + NIX_REMOTE=daemon @bindir@/nix-store -r "${REPLY}" + fi; + done; + elif [ "$i" = "nix-self-fixed://" ] ; then + refresh_critical_derivers; + + cat critical-derivers | while read; do + if egrep '"(md5|sha1|sha256)"' "$REPLY" &>/dev/null; then + echo "Realising $REPLY using direct Nix build" >&2 + NIX_REMOTE= @bindir@/nix-store -r "${REPLY}" + fi; + done; + elif [ "$i" = "nix-daemon-substitute://" ] ; then + NIX_REMOTE=daemon try_to_substitute; + elif [ "$i" = "nix-self-substitute://" ] ; then + NIX_REMOTE= try_to_substitute; + elif [ "$i" = "nix-daemon-build://" ] ; then + refresh_critical_derivers; + NIX_REMOTE=daemon build_here; + elif [ "$i" = "nix-self-build://" ] ; then + refresh_critical_derivers; + NIX_REMOTE= build_here; + fi; + mv needed-paths wanted-paths; + cat wanted-paths | xargs nix-store --check-validity --print-invalid > needed-paths; + echo We still need $(cat needed-paths | wc -l) paths. >&2 +done; + +cd / +rm -r "$WORKING_DIRECTORY" diff --git a/third_party/nix/scripts/repl.sh b/third_party/nix/scripts/repl.sh new file mode 100755 index 000000000000..d068e807903a --- /dev/null +++ b/third_party/nix/scripts/repl.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -eo pipefail + +# Run `nix repl` using a local store, for use during development. Intended to +# be run from the cmake build directory + +if [ "$#" -gt 0 ] && [ "$1" = "--debug" ]; then + gdb=(gdb --args) + shift 1 +elif [ "$1" = "--rr" ]; then + gdb=(rr record) + shift 1 +else + gdb=() +fi + +make -j 10 +NIX_STORE_DIR=$(pwd)/nix/store \ + NIX_LOG_DIR=$(pwd)/nix/var/log/nix \ + NIX_STATE_DIR=$(pwd)/nix/var/nix \ + XDG_CACHE_HOME=$(pwd)/cache \ + NIX_REMOTE=daemon \ + ${gdb[*]} ./src/nix repl "$@" diff --git a/third_party/nix/scripts/setup_store.sh b/third_party/nix/scripts/setup_store.sh new file mode 100755 index 000000000000..ee96c8d3b853 --- /dev/null +++ b/third_party/nix/scripts/setup_store.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Setup a store for local development rooted at the current directory, and +# compatible with the scripts in this directory (repl.sh, build.sh, eval.sh, +# daemon.sh, etc). Intended to be run from the cmake build directory + +mkdir -p nix/store nix/var/nix nix/var/log/nix +ln -s $(pwd)/src/nix ./nix/build-remote +mkdir -p $(dirname "$(pwd)${SANDBOX_SHELL}") +cp "${SANDBOX_SHELL}" "$(pwd)${SANDBOX_SHELL}" |