at 16.09-beta 12 kB view raw
1#! @shell@ 2 3if [ -x "@shell@" ]; then export SHELL="@shell@"; fi; 4 5set -e 6 7showSyntax() { 8 exec man nixos-rebuild 9 exit 1 10} 11 12 13# Parse the command line. 14origArgs=("$@") 15extraBuildFlags=() 16action= 17buildNix=1 18rollback= 19upgrade= 20repair= 21profile=/nix/var/nix/profiles/system 22buildHost= 23targetHost= 24 25while [ "$#" -gt 0 ]; do 26 i="$1"; shift 1 27 case "$i" in 28 --help) 29 showSyntax 30 ;; 31 switch|boot|test|build|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader) 32 if [ "$i" = dry-run ]; then i=dry-build; fi 33 action="$i" 34 ;; 35 --install-grub) 36 echo "$0: --install-grub deprecated, use --install-bootloader instead" >&2 37 export NIXOS_INSTALL_BOOTLOADER=1 38 ;; 39 --install-bootloader) 40 export NIXOS_INSTALL_BOOTLOADER=1 41 ;; 42 --no-build-nix) 43 buildNix= 44 ;; 45 --rollback) 46 rollback=1 47 ;; 48 --upgrade) 49 upgrade=1 50 ;; 51 --repair) 52 repair=1 53 extraBuildFlags+=("$i") 54 ;; 55 --show-trace|--no-build-hook|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q) 56 extraBuildFlags+=("$i") 57 ;; 58 --max-jobs|-j|--cores|-I) 59 j="$1"; shift 1 60 extraBuildFlags+=("$i" "$j") 61 ;; 62 --option) 63 j="$1"; shift 1 64 k="$1"; shift 1 65 extraBuildFlags+=("$i" "$j" "$k") 66 ;; 67 --fast) 68 buildNix= 69 extraBuildFlags+=(--show-trace) 70 ;; 71 --profile-name|-p) 72 if [ -z "$1" ]; then 73 echo "$0: ‘--profile-name’ requires an argument" 74 exit 1 75 fi 76 if [ "$1" != system ]; then 77 profile="/nix/var/nix/profiles/system-profiles/$1" 78 mkdir -p -m 0755 "$(dirname "$profile")" 79 fi 80 shift 1 81 ;; 82 --build-host|h) 83 buildHost="$1" 84 shift 1 85 ;; 86 --target-host|t) 87 targetHost="$1" 88 shift 1 89 ;; 90 *) 91 echo "$0: unknown option \`$i'" 92 exit 1 93 ;; 94 esac 95done 96 97 98if [ -z "$buildHost" -a -n "$targetHost" ]; then 99 buildHost="$targetHost" 100fi 101if [ "$targetHost" = localhost ]; then 102 targetHost= 103fi 104if [ "$buildHost" = localhost ]; then 105 buildHost= 106fi 107 108buildHostCmd() { 109 if [ -z "$buildHost" ]; then 110 "$@" 111 elif [ -n "$remoteNix" ]; then 112 ssh $SSHOPTS "$buildHost" PATH="$remoteNix:$PATH" "$@" 113 else 114 ssh $SSHOPTS "$buildHost" "$@" 115 fi 116} 117 118targetHostCmd() { 119 if [ -z "$targetHost" ]; then 120 "$@" 121 else 122 ssh $SSHOPTS "$targetHost" "$@" 123 fi 124} 125 126copyToTarget() { 127 if ! [ "$targetHost" = "$buildHost" ]; then 128 if [ -z "$targetHost" ]; then 129 NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --from "$buildHost" "$1" 130 elif [ -z "$buildHost" ]; then 131 NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --to "$targetHost" "$1" 132 else 133 buildHostCmd nix-copy-closure --to "$targetHost" "$1" 134 fi 135 fi 136} 137 138nixBuild() { 139 if [ -z "$buildHost" ]; then 140 nix-build "$@" 141 else 142 local instArgs=() 143 local buildArgs=() 144 145 while [ "$#" -gt 0 ]; do 146 local i="$1"; shift 1 147 case "$i" in 148 -o) 149 local out="$1"; shift 1 150 buildArgs+=("--add-root" "$out" "--indirect") 151 ;; 152 -A) 153 local j="$1"; shift 1 154 instArgs+=("$i" "$j") 155 ;; 156 -I) # We don't want this in buildArgs 157 shift 1 158 ;; 159 --no-out-link) # We don't want this in buildArgs 160 ;; 161 "<"*) # nix paths 162 instArgs+=("$i") 163 ;; 164 *) 165 buildArgs+=("$i") 166 ;; 167 esac 168 done 169 170 local drv="$(nix-instantiate "${instArgs[@]}" "${extraBuildFlags[@]}")" 171 if [ -a "$drv" ]; then 172 NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --to "$buildHost" "$drv" 173 buildHostCmd nix-store -r "$drv" "${buildArgs[@]}" 174 else 175 echo "nix-instantiate failed" 176 exit 1 177 fi 178 fi 179} 180 181 182if [ -z "$action" ]; then showSyntax; fi 183 184# Only run shell scripts from the Nixpkgs tree if the action is 185# "switch", "boot", or "test". With other actions (such as "build"), 186# the user may reasonably expect that no code from the Nixpkgs tree is 187# executed, so it's safe to run nixos-rebuild against a potentially 188# untrusted tree. 189canRun= 190if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then 191 canRun=1 192fi 193 194 195# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’. 196if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then 197 nix-channel --update nixos 198 199 # If there are other channels that contain a file called 200 # ".update-on-nixos-rebuild", update them as well. 201 for channelpath in /nix/var/nix/profiles/per-user/root/channels/*; do 202 if [ -e "$channelpath/.update-on-nixos-rebuild" ]; then 203 nix-channel --update "$(basename "$channelpath")" 204 fi 205 done 206fi 207 208# Make sure that we use the Nix package we depend on, not something 209# else from the PATH for nix-{env,instantiate,build}. This is 210# important, because NixOS defaults the architecture of the rebuilt 211# system to the architecture of the nix-* binaries used. So if on an 212# amd64 system the user has an i686 Nix package in her PATH, then we 213# would silently downgrade the whole system to be i686 NixOS on the 214# next reboot. 215if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then 216 export PATH=@nix@/bin:$PATH 217fi 218 219# Re-execute nixos-rebuild from the Nixpkgs tree. 220if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" ]; then 221 if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then 222 export _NIXOS_REBUILD_REEXEC=1 223 exec $p/bin/nixos-rebuild "${origArgs[@]}" 224 exit 1 225 fi 226fi 227 228 229tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX) 230SSHOPTS="$NIX_SSHOPTS -o ControlMaster=auto -o ControlPath=$tmpDir/ssh-%n -o ControlPersist=60" 231 232cleanup() { 233 for ctrl in "$tmpDir"/ssh-*; do 234 ssh -o ControlPath="$ctrl" -O exit dummyhost 2>/dev/null || true 235 done 236 rm -rf "$tmpDir" 237} 238trap cleanup EXIT 239 240 241 242# If the Nix daemon is running, then use it. This allows us to use 243# the latest Nix from Nixpkgs (below) for expression evaluation, while 244# still using the old Nix (via the daemon) for actual store access. 245# This matters if the new Nix in Nixpkgs has a schema change. It 246# would upgrade the schema, which should only happen once we actually 247# switch to the new configuration. 248# If --repair is given, don't try to use the Nix daemon, because the 249# flag can only be used directly. 250if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then 251 export NIX_REMOTE=${NIX_REMOTE:-daemon} 252fi 253 254 255# First build Nix, since NixOS may require a newer version than the 256# current one. 257if [ -n "$rollback" -o "$action" = dry-build ]; then 258 buildNix= 259fi 260 261prebuiltNix() { 262 machine="$1" 263 if [ "$machine" = x86_64 ]; then 264 echo /nix/store/xryr9g56h8yjddp89d6dw12anyb4ch7c-nix-1.10 265 elif [[ "$machine" =~ i.86 ]]; then 266 echo /nix/store/2w92k5wlpspf0q2k9mnf2z42prx3bwmv-nix-1.10 267 else 268 echo "$0: unsupported platform" 269 exit 1 270 fi 271} 272 273remotePATH= 274 275if [ -n "$buildNix" ]; then 276 echo "building Nix..." >&2 277 nixDrv= 278 if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then 279 if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A nixFallback "${extraBuildFlags[@]}")"; then 280 if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then 281 nixStorePath="$(prebuiltNix "$(uname -m)")" 282 if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \ 283 --option extra-binary-caches https://cache.nixos.org/; then 284 echo "warning: don't know how to get latest Nix" >&2 285 fi 286 # Older version of nix-store -r don't support --add-root. 287 [ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix 288 if [ -n "$buildHost" ]; then 289 remoteNixStorePath="$(prebuiltNix "$(buildHostCmd uname -m)")" 290 remoteNix="$remoteNixStorePath/bin" 291 if ! buildHostCmd nix-store -r $remoteNixStorePath \ 292 --option extra-binary-caches https://cache.nixos.org/ >/dev/null; then 293 remoteNix= 294 echo "warning: don't know how to get latest Nix" >&2 295 fi 296 fi 297 fi 298 fi 299 fi 300 if [ -a "$nixDrv" ]; then 301 nix-store -r "$nixDrv"'!'"out" --add-root $tmpDir/nix --indirect >/dev/null 302 if [ -n "$buildHost" ]; then 303 nix-copy-closure --to "$buildHost" "$nixDrv" 304 # The nix build produces multiple outputs, we add them all to the remote path 305 for p in $(buildHostCmd nix-store -r "$(readlink "$nixDrv")" "${buildArgs[@]}"); do 306 remoteNix="$remoteNix${remoteNix:+:}$p/bin" 307 done 308 fi 309 fi 310 PATH="$tmpDir/nix/bin:$PATH" 311fi 312 313 314# Update the version suffix if we're building from Git (so that 315# nixos-version shows something useful). 316if [ -n "$canRun" ]; then 317 if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then 318 suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true) 319 if [ -n "$suffix" ]; then 320 echo -n "$suffix" > "$nixpkgs/.version-suffix" || true 321 fi 322 fi 323fi 324 325 326if [ "$action" = dry-build ]; then 327 extraBuildFlags+=(--dry-run) 328fi 329 330 331# Either upgrade the configuration in the system profile (for "switch" 332# or "boot"), or just build it and create a symlink "result" in the 333# current directory (for "build" and "test"). 334if [ -z "$rollback" ]; then 335 echo "building the system configuration..." >&2 336 if [ "$action" = switch -o "$action" = boot ]; then 337 pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")" 338 copyToTarget "$pathToConfig" 339 targetHostCmd nix-env -p "$profile" --set "$pathToConfig" 340 elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then 341 pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")" 342 elif [ "$action" = build-vm ]; then 343 pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")" 344 elif [ "$action" = build-vm-with-bootloader ]; then 345 pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")" 346 else 347 showSyntax 348 fi 349 # Copy build to target host if we haven't already done it 350 if ! [ "$action" = switch -o "$action" = boot ]; then 351 copyToTarget "$pathToConfig" 352 fi 353else # [ -n "$rollback" ] 354 if [ "$action" = switch -o "$action" = boot ]; then 355 targetHostCmd nix-env --rollback -p "$profile" 356 pathToConfig="$profile" 357 elif [ "$action" = test -o "$action" = build ]; then 358 systemNumber=$( 359 targetHostCmd nix-env -p "$profile" --list-generations | 360 sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h' 361 ) 362 pathToConfig="$profile"-${systemNumber}-link 363 if [ -z "$targetHost" ]; then 364 ln -sT "$pathToConfig" ./result 365 fi 366 else 367 showSyntax 368 fi 369fi 370 371 372# If we're not just building, then make the new configuration the boot 373# default and/or activate it now. 374if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then 375 if ! targetHostCmd $pathToConfig/bin/switch-to-configuration "$action"; then 376 echo "warning: error(s) occurred while switching to the new configuration" >&2 377 exit 1 378 fi 379fi 380 381 382if [ "$action" = build-vm ]; then 383 cat >&2 <<EOF 384 385Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm). 386EOF 387fi