at 24.11-pre 7.7 kB view raw
1#! @runtimeShell@ 2# shellcheck shell=bash 3 4set -e 5shopt -s nullglob 6 7export PATH=@path@:$PATH 8 9# Ensure a consistent umask. 10umask 0022 11 12# Parse the command line for the -I flag 13extraBuildFlags=() 14flakeFlags=() 15 16mountPoint=/mnt 17channelPath= 18system= 19verbosity=() 20 21while [ "$#" -gt 0 ]; do 22 i="$1"; shift 1 23 case "$i" in 24 --max-jobs|-j|--cores|-I|--substituters) 25 j="$1"; shift 1 26 extraBuildFlags+=("$i" "$j") 27 ;; 28 --option) 29 j="$1"; shift 1 30 k="$1"; shift 1 31 extraBuildFlags+=("$i" "$j" "$k") 32 ;; 33 --root) 34 mountPoint="$1"; shift 1 35 ;; 36 --system|--closure) 37 system="$1"; shift 1 38 ;; 39 --flake) 40 flake="$1" 41 flakeFlags=(--experimental-features 'nix-command flakes') 42 shift 1 43 ;; 44 --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file) 45 lockFlags+=("$i") 46 ;; 47 --update-input) 48 j="$1"; shift 1 49 lockFlags+=("$i" "$j") 50 ;; 51 --override-input) 52 j="$1"; shift 1 53 k="$1"; shift 1 54 lockFlags+=("$i" "$j" "$k") 55 ;; 56 --channel) 57 channelPath="$1"; shift 1 58 ;; 59 --no-channel-copy) 60 noChannelCopy=1 61 ;; 62 --no-root-password|--no-root-passwd) 63 noRootPasswd=1 64 ;; 65 --no-bootloader) 66 noBootLoader=1 67 ;; 68 --show-trace|--impure|--keep-going) 69 extraBuildFlags+=("$i") 70 ;; 71 --help) 72 exec man nixos-install 73 exit 1 74 ;; 75 --debug) 76 set -x 77 ;; 78 -v*|--verbose) 79 verbosity+=("$i") 80 ;; 81 *) 82 echo "$0: unknown option \`$i'" 83 exit 1 84 ;; 85 esac 86done 87 88if ! test -e "$mountPoint"; then 89 echo "mount point $mountPoint doesn't exist" 90 exit 1 91fi 92 93# Verify permissions are okay-enough 94checkPath="$(realpath "$mountPoint")" 95while [[ "$checkPath" != "/" ]]; do 96 mode="$(stat -c '%a' "$checkPath")" 97 if [[ "${mode: -1}" -lt "5" ]]; then 98 echo "path $checkPath should have permissions 755, but had permissions $mode. Consider running 'chmod o+rx $checkPath'." 99 exit 1 100 fi 101 checkPath="$(dirname "$checkPath")" 102done 103 104# Get the path of the NixOS configuration file. 105if [[ -z $NIXOS_CONFIG ]]; then 106 NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix 107fi 108 109if [[ ${NIXOS_CONFIG:0:1} != / ]]; then 110 echo "$0: \$NIXOS_CONFIG is not an absolute path" 111 exit 1 112fi 113 114if [[ -n $flake ]]; then 115 if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then 116 flake="${BASH_REMATCH[1]}" 117 flakeAttr="${BASH_REMATCH[2]}" 118 fi 119 if [[ -z "$flakeAttr" ]]; then 120 echo "Please specify the name of the NixOS configuration to be installed, as a URI fragment in the flake-uri." 121 echo "For example, to use the output nixosConfigurations.foo from the flake.nix, append \"#foo\" to the flake-uri." 122 exit 1 123 fi 124 flakeAttr="nixosConfigurations.\"$flakeAttr\"" 125fi 126 127# Resolve the flake. 128if [[ -n $flake ]]; then 129 flake=$(nix "${flakeFlags[@]}" flake metadata --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url) 130fi 131 132if [[ ! -e $NIXOS_CONFIG && -z $system && -z $flake ]]; then 133 echo "configuration file $NIXOS_CONFIG doesn't exist" 134 exit 1 135fi 136 137# A place to drop temporary stuff. 138tmpdir="$(mktemp -d -p "$mountPoint")" 139trap 'rm -rf $tmpdir' EXIT 140 141# store temporary files on target filesystem by default 142export TMPDIR=${TMPDIR:-$tmpdir} 143 144sub="auto?trusted=1" 145 146# Copy the NixOS/Nixpkgs sources to the target as the initial contents 147# of the NixOS channel. 148if [[ -z $noChannelCopy ]]; then 149 if [[ -z $channelPath ]]; then 150 channelPath="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")" 151 fi 152 if [[ -n $channelPath ]]; then 153 echo "copying channel..." 154 mkdir -p "$mountPoint"/nix/var/nix/profiles/per-user/root 155 nix-env --store "$mountPoint" "${extraBuildFlags[@]}" --extra-substituters "$sub" \ 156 -p "$mountPoint"/nix/var/nix/profiles/per-user/root/channels --set "$channelPath" --quiet \ 157 "${verbosity[@]}" 158 install -m 0700 -d "$mountPoint"/root/.nix-defexpr 159 ln -sfn /nix/var/nix/profiles/per-user/root/channels "$mountPoint"/root/.nix-defexpr/channels 160 fi 161fi 162 163# Build the system configuration in the target filesystem. 164if [[ -z $system ]]; then 165 outLink="$tmpdir/system" 166 if [[ -z $flake ]]; then 167 echo "building the configuration in $NIXOS_CONFIG..." 168 nix-build --out-link "$outLink" --store "$mountPoint" "${extraBuildFlags[@]}" \ 169 --extra-substituters "$sub" \ 170 '<nixpkgs/nixos>' -A system -I "nixos-config=$NIXOS_CONFIG" "${verbosity[@]}" 171 else 172 echo "building the flake in $flake..." 173 nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.toplevel" \ 174 --store "$mountPoint" --extra-substituters "$sub" "${verbosity[@]}" \ 175 "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link "$outLink" 176 fi 177 system=$(readlink -f "$outLink") 178fi 179 180# Set the system profile to point to the configuration. TODO: combine 181# this with the previous step once we have a nix-env replacement with 182# a progress bar. 183nix-env --store "$mountPoint" "${extraBuildFlags[@]}" \ 184 --extra-substituters "$sub" \ 185 -p "$mountPoint"/nix/var/nix/profiles/system --set "$system" "${verbosity[@]}" 186 187# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out. 188mkdir -m 0755 -p "$mountPoint/etc" 189touch "$mountPoint/etc/NIXOS" 190 191# Switch to the new system configuration. This will install Grub with 192# a menu default pointing at the kernel/initrd/etc of the new 193# configuration. 194if [[ -z $noBootLoader ]]; then 195 echo "installing the boot loader..." 196 # Grub needs an mtab. 197 ln -sfn /proc/mounts "$mountPoint"/etc/mtab 198 export mountPoint 199 NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root "$mountPoint" -c "$(cat <<'EOF' 200 # Create a bind mount for each of the mount points inside the target file 201 # system. This preserves the validity of their absolute paths after changing 202 # the root with `nixos-enter`. 203 # Without this the bootloader installation may fail due to options that 204 # contain paths referenced during evaluation, like initrd.secrets. 205 # when not root, re-execute the script in an unshared namespace 206 mount --rbind --mkdir / "$mountPoint" 207 mount --make-rslave "$mountPoint" 208 /run/current-system/bin/switch-to-configuration boot 209 umount -R "$mountPoint" && (rmdir "$mountPoint" 2>/dev/null || true) 210EOF 211)" 212fi 213 214# Ask the user to set a root password, but only if the passwd command 215# exists (i.e. when mutable user accounts are enabled). 216if [[ -z $noRootPasswd ]] && [ -t 0 ]; then 217 if nixos-enter --root "$mountPoint" -c 'test -e /nix/var/nix/profiles/system/sw/bin/passwd'; then 218 set +e 219 nixos-enter --root "$mountPoint" -c 'echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd' 220 exit_code=$? 221 set -e 222 223 if [[ $exit_code != 0 ]]; then 224 echo "Setting a root password failed with the above printed error." 225 echo "You can set the root password manually by executing \`nixos-enter --root ${mountPoint@Q}\` and then running \`passwd\` in the shell of the new system." 226 exit $exit_code 227 fi 228 fi 229fi 230 231echo "installation finished!"