Merge pull request #2026 from grahamc/multi-user-linux
Expand the multi-user installer to support Linuxes with systemd
This commit is contained in:
		
						commit
						3fbaa230a2
					
				
					 5 changed files with 1090 additions and 783 deletions
				
			
		
							
								
								
									
										34
									
								
								release.nix
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								release.nix
									
										
									
									
									
								
							|  | @ -127,17 +127,39 @@ let | ||||||
|           substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \ |           substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \ | ||||||
|             --subst-var-by nix ${toplevel} \ |             --subst-var-by nix ${toplevel} \ | ||||||
|             --subst-var-by cacert ${cacert} |             --subst-var-by cacert ${cacert} | ||||||
|           substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user \ | 
 | ||||||
|  |           substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \ | ||||||
|  |             --subst-var-by nix ${toplevel} \ | ||||||
|  |             --subst-var-by cacert ${cacert} | ||||||
|  |           substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \ | ||||||
|  |             --subst-var-by nix ${toplevel} \ | ||||||
|  |             --subst-var-by cacert ${cacert} | ||||||
|  |           substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \ | ||||||
|             --subst-var-by nix ${toplevel} \ |             --subst-var-by nix ${toplevel} \ | ||||||
|             --subst-var-by cacert ${cacert} |             --subst-var-by cacert ${cacert} | ||||||
| 
 | 
 | ||||||
|           if type -p shellcheck; then |           if type -p shellcheck; then | ||||||
|             shellcheck -e SC1090 $TMPDIR/install |             # SC1090: Don't worry about not being able to find | ||||||
|             shellcheck -e SC1091,SC2002 $TMPDIR/install-darwin-multi-user |             #         $nix/etc/profile.d/nix.sh | ||||||
|  |             shellcheck --exclude SC1090 $TMPDIR/install | ||||||
|  |             shellcheck $TMPDIR/install-darwin-multi-user.sh | ||||||
|  |             shellcheck $TMPDIR/install-systemd-multi-user.sh | ||||||
|  | 
 | ||||||
|  |             # SC1091: Don't panic about not being able to source | ||||||
|  |             #         /etc/profile | ||||||
|  |             # SC2002: Ignore "useless cat" "error", when loading | ||||||
|  |             #         .reginfo, as the cat is a much cleaner | ||||||
|  |             #         implementation, even though it is "useless" | ||||||
|  |             # SC2116: Allow ROOT_HOME=$(echo ~root) for resolving | ||||||
|  |             #         root's home directory | ||||||
|  |             shellcheck --external-sources \ | ||||||
|  |               --exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user | ||||||
|           fi |           fi | ||||||
| 
 | 
 | ||||||
|           chmod +x $TMPDIR/install |           chmod +x $TMPDIR/install | ||||||
|           chmod +x $TMPDIR/install-darwin-multi-user |           chmod +x $TMPDIR/install-darwin-multi-user.sh | ||||||
|  |           chmod +x $TMPDIR/install-systemd-multi-user.sh | ||||||
|  |           chmod +x $TMPDIR/install-multi-user | ||||||
|           dir=nix-${version}-${system} |           dir=nix-${version}-${system} | ||||||
|           fn=$out/$dir.tar.bz2 |           fn=$out/$dir.tar.bz2 | ||||||
|           mkdir -p $out/nix-support |           mkdir -p $out/nix-support | ||||||
|  | @ -149,7 +171,9 @@ let | ||||||
|             --transform "s,$TMPDIR/install,$dir/install," \ |             --transform "s,$TMPDIR/install,$dir/install," \ | ||||||
|             --transform "s,$TMPDIR/reginfo,$dir/.reginfo," \ |             --transform "s,$TMPDIR/reginfo,$dir/.reginfo," \ | ||||||
|             --transform "s,$NIX_STORE,$dir/store,S" \ |             --transform "s,$NIX_STORE,$dir/store,S" \ | ||||||
|             $TMPDIR/install $TMPDIR/install-darwin-multi-user $TMPDIR/reginfo \ |             $TMPDIR/install $TMPDIR/install-darwin-multi-user.sh \ | ||||||
|  |             $TMPDIR/install-systemd-multi-user.sh \ | ||||||
|  |             $TMPDIR/install-multi-user $TMPDIR/reginfo \ | ||||||
|             $(cat ${installerClosureInfo}/store-paths) |             $(cat ${installerClosureInfo}/store-paths) | ||||||
|         ''); |         ''); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,772 +1,43 @@ | ||||||
| #!/bin/bash | #!/usr/bin/env bash | ||||||
| 
 | 
 | ||||||
| set -eu | set -eu | ||||||
| set -o pipefail | 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="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 PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist | readonly PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist | ||||||
| 
 | 
 | ||||||
| readonly PROFILE_TARGETS=("/etc/bashrc" "/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="/var/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 [ -e "$PLIST_DEST" ]; then |  | ||||||
|         step=$((step + 1)) |  | ||||||
|         cat <<EOF |  | ||||||
| $step. Delete $PLIST_DEST |  | ||||||
| 
 |  | ||||||
|   sudo launchctl unload $PLIST_DEST |  | ||||||
|   sudo rm $PLIST_DEST |  | ||||||
| 
 |  | ||||||
| EOF |  | ||||||
|     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)) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| dsclattr() { | dsclattr() { | ||||||
|     /usr/bin/dscl . -read "$1" \ |     /usr/bin/dscl . -read "$1" \ | ||||||
|         | awk "/$2/ { print \$2 }" |         | awk "/$2/ { print \$2 }" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| _textout() { | poly_validate_assumptions() { | ||||||
|     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 |  | ||||||
| 
 |  | ||||||
| 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 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() { |  | ||||||
|     if [ "$(uname -s)" != "Darwin" ]; then |     if [ "$(uname -s)" != "Darwin" ]; then | ||||||
|         failure "This script is for use with macOS!" |         failure "This script is for use with macOS!" | ||||||
|     fi |     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. |  | ||||||
| 
 |  | ||||||
| $(uninstall_directions) |  | ||||||
| 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 |  | ||||||
| 
 |  | ||||||
|     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() { | poly_service_installed_check() { | ||||||
|     header "hardware report" |     [ -e "$PLIST_DEST" ] | ||||||
|     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" |  | ||||||
|     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() { | poly_service_uninstall_directions() { | ||||||
|     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/bin/dscl . create "$dsclpath" \ |  | ||||||
|               UniqueID "${uid}" |  | ||||||
|         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" "NFSHomeDirectory")" = "/var/empty" ]; then |  | ||||||
|         row "          NFSHomeDirectory" "/var/empty" |  | ||||||
|     else |  | ||||||
|         _sudo "in order to give $username a safe home directory" \ |  | ||||||
|               /usr/bin/dscl . -create "$dsclpath" "NFSHomeDirectory" "/var/empty" |  | ||||||
|         row "          NFSHomeDirectory" "/var/empty" |  | ||||||
|     fi |  | ||||||
| 
 |  | ||||||
|     if [ "$(dsclattr "$dsclpath" "RealName")" = "Nix build user $coreid" ]; then |  | ||||||
|         row "          RealName" "Nix build user $coreid" |  | ||||||
|     else |  | ||||||
|         _sudo "in order to give $username a useful name" \ |  | ||||||
|               /usr/bin/dscl . -create "$dsclpath" "RealName" "Nix build user $coreid" |  | ||||||
|         row "          RealName" "Nix build user $coreid" |  | ||||||
|     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" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| welcome_to_nix() { |  | ||||||
|     ok "Welcome to the Multi-User Nix Installation" |  | ||||||
| 
 |  | ||||||
|         cat <<EOF |         cat <<EOF | ||||||
|  | $1. Delete $PLIST_DEST | ||||||
| 
 | 
 | ||||||
| This installation tool will set up your computer with the Nix package |   sudo launchctl unload $PLIST_DEST | ||||||
| manager. This will happen in a few stages: |   sudo rm $PLIST_DEST | ||||||
| 
 |  | ||||||
| 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 | EOF | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     if ui_confirm "Would you like to see a more detailed list of what we will do?"; then | poly_service_setup_note() { | ||||||
|         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 |  | ||||||
|     cat <<EOF |     cat <<EOF | ||||||
|  - load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon |  - load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon | ||||||
| 
 | 
 | ||||||
| EOF | EOF | ||||||
|         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() { | poly_configure_nix_daemon_service() { | ||||||
|     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 |  | ||||||
| 
 |  | ||||||
|         _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() { |  | ||||||
|     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" |  | ||||||
| 
 |  | ||||||
|     _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" |  | ||||||
| 
 |  | ||||||
|     _sudo "to update the default channel in the default profile" \ |  | ||||||
|           HOME=$ROOT_HOME NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| place_nix_configuration() { |  | ||||||
|     cat <<EOF > "$SCRATCH/nix.conf" |  | ||||||
| build-users-group = $NIX_BUILD_GROUP_NAME |  | ||||||
| 
 |  | ||||||
| max-jobs = $NIX_USER_COUNT |  | ||||||
| cores = 1 |  | ||||||
| sandbox = false |  | ||||||
| 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" \ |     _sudo "to set up the nix-daemon as a LaunchDaemon" \ | ||||||
|           ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST" |           ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST" | ||||||
| 
 | 
 | ||||||
|  | @ -778,42 +49,96 @@ configure_nix_daemon_plist() { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | poly_group_exists() { | ||||||
| main() { |     /usr/bin/dscl . -read "/Groups/$1" > /dev/null 2>&1 | ||||||
|     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 |  | ||||||
|     configure_nix_daemon_plist |  | ||||||
| 
 |  | ||||||
|     trap finish_success EXIT |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | poly_group_id_get() { | ||||||
|  |     dsclattr "/Groups/$1" "PrimaryGroupID" | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| main | 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}" | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										797
									
								
								scripts/install-multi-user.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										797
									
								
								scripts/install-multi-user.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,797 @@ | ||||||
|  | #!/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[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 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 | ||||||
|  | 
 | ||||||
|  | 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 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 ]; 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() { | ||||||
|  |     _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" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
|  |         _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() { | ||||||
|  |     # 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" | ||||||
|  | 
 | ||||||
|  |     _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" | ||||||
|  | 
 | ||||||
|  |     _sudo "to update the default channel in the default profile" \ | ||||||
|  |           HOME="$ROOT_HOME" NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | place_nix_configuration() { | ||||||
|  |     cat <<EOF > "$SCRATCH/nix.conf" | ||||||
|  | build-users-group = $NIX_BUILD_GROUP_NAME | ||||||
|  | 
 | ||||||
|  | max-jobs = $NIX_USER_COUNT | ||||||
|  | cores = 1 | ||||||
|  | sandbox = false | ||||||
|  | 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" ] && [ -e /run/systemd/system ]; then | ||||||
|  |         # shellcheck source=./install-systemd-multi-user.sh | ||||||
|  |         . "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh" | ||||||
|  |     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 | ||||||
|  | @ -29,8 +29,15 @@ if [ "$(uname -s)" = "Darwin" ]; then | ||||||
|         exit 1 |         exit 1 | ||||||
|     fi |     fi | ||||||
| 
 | 
 | ||||||
|     printf '\e[1;31mSwitching to the Multi-User Darwin Installer\e[0m\n' |     printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n' | ||||||
|     exec "$self/install-darwin-multi-user" |     exec "$self/install-multi-user" | ||||||
|  |     exit 0 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Linux & Systemd support | ||||||
|  | if [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then | ||||||
|  |     printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n' | ||||||
|  |     exec "$self/install-multi-user" | ||||||
|     exit 0 |     exit 0 | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										154
									
								
								scripts/install-systemd-multi-user.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								scripts/install-systemd-multi-user.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | ||||||
|  | #!/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 | ||||||
|  | 
 | ||||||
|  | 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" | ||||||
|  | 
 | ||||||
|  |     _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" | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue