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
22
23while [ "$#" -gt 0 ]; do
24 i="$1"; shift 1
25 case "$i" in
26 --help)
27 showSyntax
28 ;;
29 switch|boot|test|build|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
30 if [ "$i" = dry-run ]; then i=dry-build; fi
31 action="$i"
32 ;;
33 --install-grub)
34 export NIXOS_INSTALL_GRUB=1
35 ;;
36 --no-build-nix)
37 buildNix=
38 ;;
39 --rollback)
40 rollback=1
41 ;;
42 --upgrade)
43 upgrade=1
44 ;;
45 --repair)
46 repair=1
47 extraBuildFlags+=("$i")
48 ;;
49 --show-trace|--no-build-hook|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q)
50 extraBuildFlags+=("$i")
51 ;;
52 --max-jobs|-j|--cores|-I)
53 j="$1"; shift 1
54 extraBuildFlags+=("$i" "$j")
55 ;;
56 --option)
57 j="$1"; shift 1
58 k="$1"; shift 1
59 extraBuildFlags+=("$i" "$j" "$k")
60 ;;
61 --fast)
62 buildNix=
63 extraBuildFlags+=(--show-trace)
64 ;;
65 --profile-name|-p)
66 if [ -z "$1" ]; then
67 echo "$0: ‘--profile-name’ requires an argument"
68 exit 1
69 fi
70 if [ "$1" != system ]; then
71 profile="/nix/var/nix/profiles/system-profiles/$1"
72 mkdir -p -m 0755 "$(dirname "$profile")"
73 fi
74 shift 1
75 ;;
76 *)
77 echo "$0: unknown option \`$i'"
78 exit 1
79 ;;
80 esac
81done
82
83if [ -z "$action" ]; then showSyntax; fi
84
85# Only run shell scripts from the Nixpkgs tree if the action is
86# "switch", "boot", or "test". With other actions (such as "build"),
87# the user may reasonably expect that no code from the Nixpkgs tree is
88# executed, so it's safe to run nixos-rebuild against a potentially
89# untrusted tree.
90canRun=
91if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then
92 canRun=1
93fi
94
95
96# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
97if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then
98 nix-channel --update nixos
99
100 # If there are other channels that contain a file called
101 # ".update-on-nixos-rebuild", update them as well.
102 for channelpath in /nix/var/nix/profiles/per-user/root/channels/*; do
103 if [ -e "$channelpath/.update-on-nixos-rebuild" ]; then
104 nix-channel --update "$(basename "$channelpath")"
105 fi
106 done
107fi
108
109# Make sure that we use the Nix package we depend on, not something
110# else from the PATH for nix-{env,instantiate,build}. This is
111# important, because NixOS defaults the architecture of the rebuilt
112# system to the architecture of the nix-* binaries used. So if on an
113# amd64 system the user has an i686 Nix package in her PATH, then we
114# would silently downgrade the whole system to be i686 NixOS on the
115# next reboot.
116if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then
117 export PATH=@nix@/bin:$PATH
118fi
119
120# Re-execute nixos-rebuild from the Nixpkgs tree.
121if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" ]; then
122 if p=$(nix-instantiate --find-file nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh "${extraBuildFlags[@]}"); then
123 export _NIXOS_REBUILD_REEXEC=1
124 exec $SHELL -e $p "${origArgs[@]}"
125 exit 1
126 fi
127fi
128
129
130tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX)
131trap 'rm -rf "$tmpDir"' EXIT
132
133
134# If the Nix daemon is running, then use it. This allows us to use
135# the latest Nix from Nixpkgs (below) for expression evaluation, while
136# still using the old Nix (via the daemon) for actual store access.
137# This matters if the new Nix in Nixpkgs has a schema change. It
138# would upgrade the schema, which should only happen once we actually
139# switch to the new configuration.
140# If --repair is given, don't try to use the Nix daemon, because the
141# flag can only be used directly.
142if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then
143 export NIX_REMOTE=${NIX_REMOTE:-daemon}
144fi
145
146
147# First build Nix, since NixOS may require a newer version than the
148# current one.
149if [ -n "$rollback" -o "$action" = dry-build ]; then
150 buildNix=
151fi
152
153if [ -n "$buildNix" ]; then
154 echo "building Nix..." >&2
155 if ! nix-build '<nixpkgs/nixos>' -A config.nix.package -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
156 if ! nix-build '<nixpkgs/nixos>' -A nixFallback -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
157 if ! nix-build '<nixpkgs>' -A nix -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
158 machine="$(uname -m)"
159 if [ "$machine" = x86_64 ]; then
160 nixStorePath=/nix/store/664kxr14kfgx4dl095crvmr7pbh9xlh5-nix-1.9
161 elif [[ "$machine" =~ i.86 ]]; then
162 nixStorePath=/nix/store/p7xdvz72xx3rhm121jclsbdmmcds7xh6-nix-1.9
163 else
164 echo "$0: unsupported platform"
165 exit 1
166 fi
167 if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \
168 --option extra-binary-caches https://cache.nixos.org/; then
169 echo "warning: don't know how to get latest Nix" >&2
170 fi
171 # Older version of nix-store -r don't support --add-root.
172 [ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix
173 fi
174 fi
175 fi
176 PATH=$tmpDir/nix/bin:$PATH
177fi
178
179
180# Update the version suffix if we're building from Git (so that
181# nixos-version shows something useful).
182if [ -n "$canRun" ]; then
183 if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then
184 suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true)
185 if [ -n "$suffix" ]; then
186 echo -n "$suffix" > "$nixpkgs/.version-suffix" || true
187 fi
188 fi
189fi
190
191
192if [ "$action" = dry-build ]; then
193 extraBuildFlags+=(--dry-run)
194fi
195
196
197# Either upgrade the configuration in the system profile (for "switch"
198# or "boot"), or just build it and create a symlink "result" in the
199# current directory (for "build" and "test").
200if [ -z "$rollback" ]; then
201 echo "building the system configuration..." >&2
202 if [ "$action" = switch -o "$action" = boot ]; then
203 nix-env "${extraBuildFlags[@]}" -p "$profile" -f '<nixpkgs/nixos>' --set -A system
204 pathToConfig="$profile"
205 elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
206 nix-build '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}" > /dev/null
207 pathToConfig=./result
208 elif [ "$action" = build-vm ]; then
209 nix-build '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}" > /dev/null
210 pathToConfig=./result
211 elif [ "$action" = build-vm-with-bootloader ]; then
212 nix-build '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}" > /dev/null
213 pathToConfig=./result
214 else
215 showSyntax
216 fi
217else # [ -n "$rollback" ]
218 if [ "$action" = switch -o "$action" = boot ]; then
219 nix-env --rollback -p "$profile"
220 pathToConfig="$profile"
221 elif [ "$action" = test -o "$action" = build ]; then
222 systemNumber=$(
223 nix-env -p "$profile" --list-generations |
224 sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h'
225 )
226 ln -sT "$profile"-${systemNumber}-link ./result
227 pathToConfig=./result
228 else
229 showSyntax
230 fi
231fi
232
233
234# If we're not just building, then make the new configuration the boot
235# default and/or activate it now.
236if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then
237 if ! $pathToConfig/bin/switch-to-configuration "$action"; then
238 echo "warning: error(s) occured while switching to the new configuration" >&2
239 exit 1
240 fi
241fi
242
243
244if [ "$action" = build-vm ]; then
245 cat >&2 <<EOF
246
247Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm).
248EOF
249fi