1#! @shell@
2
3# - make Nix store etc.
4# - copy closure of Nix to target device
5# - register validity
6# - with a chroot to the target device:
7# * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
8# * install the boot loader
9
10# Ensure a consistent umask.
11umask 0022
12
13# Re-exec ourselves in a private mount namespace so that our bind
14# mounts get cleaned up automatically.
15if [ "$(id -u)" = 0 ]; then
16 if [ -z "$NIXOS_INSTALL_REEXEC" ]; then
17 export NIXOS_INSTALL_REEXEC=1
18 exec unshare --mount --uts -- "$0" "$@"
19 else
20 mount --make-rprivate /
21 fi
22fi
23
24# Parse the command line for the -I flag
25extraBuildFlags=()
26chrootCommand=(/run/current-system/sw/bin/bash)
27buildUsersGroup="nixbld"
28
29while [ "$#" -gt 0 ]; do
30 i="$1"; shift 1
31 case "$i" in
32 --max-jobs|-j|--cores|-I)
33 j="$1"; shift 1
34 extraBuildFlags+=("$i" "$j")
35 ;;
36 --option)
37 j="$1"; shift 1
38 k="$1"; shift 1
39 extraBuildFlags+=("$i" "$j" "$k")
40 ;;
41 --root)
42 mountPoint="$1"; shift 1
43 ;;
44 --closure)
45 closure="$1"; shift 1
46 buildUsersGroup=""
47 ;;
48 --no-channel-copy)
49 noChannelCopy=1
50 ;;
51 --no-root-passwd)
52 noRootPasswd=1
53 ;;
54 --no-bootloader)
55 noBootLoader=1
56 ;;
57 --show-trace)
58 extraBuildFlags+=("$i")
59 ;;
60 --chroot)
61 runChroot=1
62 if [[ "$@" != "" ]]; then
63 chrootCommand=("$@")
64 fi
65 break
66 ;;
67 --help)
68 exec man nixos-install
69 exit 1
70 ;;
71 *)
72 echo "$0: unknown option \`$i'"
73 exit 1
74 ;;
75 esac
76done
77
78set -e
79shopt -s nullglob
80
81if test -z "$mountPoint"; then
82 mountPoint=/mnt
83fi
84
85if ! test -e "$mountPoint"; then
86 echo "mount point $mountPoint doesn't exist"
87 exit 1
88fi
89
90# Get the path of the NixOS configuration file.
91if test -z "$NIXOS_CONFIG"; then
92 NIXOS_CONFIG=/etc/nixos/configuration.nix
93fi
94
95if [ ! -e "$mountPoint/$NIXOS_CONFIG" ] && [ -z "$closure" ]; then
96 echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist"
97 exit 1
98fi
99
100
101# Builds will use users that are members of this group
102extraBuildFlags+=(--option "build-users-group" "$buildUsersGroup")
103
104# Inherit binary caches from the host
105# TODO: will this still work with Nix 1.12 now that it has no perl? Probably not...
106binary_caches="$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"binary-caches"};')"
107extraBuildFlags+=(--option "binary-caches" "$binary_caches")
108
109nixpkgs="$(readlink -f "$(nix-instantiate --find-file nixpkgs)")"
110export NIX_PATH="nixpkgs=$nixpkgs:nixos-config=$mountPoint/$NIXOS_CONFIG"
111unset NIXOS_CONFIG
112
113# TODO: do I need to set NIX_SUBSTITUTERS here or is the --option binary-caches above enough?
114
115
116# A place to drop temporary closures
117trap "rm -rf $tmpdir" EXIT
118tmpdir="$(mktemp -d)"
119
120# Build a closure (on the host; we then copy it into the guest)
121function closure() {
122 nix-build "${extraBuildFlags[@]}" --no-out-link -E "with import <nixpkgs> {}; runCommand \"closure\" { exportReferencesGraph = [ \"x\" (buildEnv { name = \"env\"; paths = [ ($1) stdenv ]; }) ]; } \"cp x \$out\""
123}
124
125system_closure="$tmpdir/system.closure"
126
127if [ -z "$closure" ]; then
128 expr="(import <nixpkgs/nixos> {}).system"
129 system_root="$(nix-build -E "$expr")"
130 system_closure="$(closure "$expr")"
131else
132 system_root=$closure
133 # Create a temporary file ending in .closure (so nixos-prepare-root knows to --import it) to transport the store closure
134 # to the filesytem we're preparing. Also delete it on exit!
135 nix-store --export $(nix-store -qR $closure) > $system_closure
136fi
137
138channel_root="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")"
139channel_closure="$tmpdir/channel.closure"
140nix-store --export $channel_root > $channel_closure
141
142# Populate the target root directory with the basics
143@prepare_root@/bin/nixos-prepare-root "$mountPoint" "$channel_root" "$system_root" @nixClosure@ "$system_closure" "$channel_closure"
144
145# nixos-prepare-root doesn't currently do anything with file ownership, so we set it up here instead
146chown @root_uid@:@nixbld_gid@ $mountPoint/nix/store
147
148mount --rbind /dev $mountPoint/dev
149mount --rbind /proc $mountPoint/proc
150mount --rbind /sys $mountPoint/sys
151
152# Grub needs an mtab.
153ln -sfn /proc/mounts $mountPoint/etc/mtab
154
155# Switch to the new system configuration. This will install Grub with
156# a menu default pointing at the kernel/initrd/etc of the new
157# configuration.
158echo "finalising the installation..."
159if [ -z "$noBootLoader" ]; then
160 NIXOS_INSTALL_BOOTLOADER=1 chroot $mountPoint \
161 /nix/var/nix/profiles/system/bin/switch-to-configuration boot
162fi
163
164# Run the activation script.
165chroot $mountPoint /nix/var/nix/profiles/system/activate
166
167
168# Ask the user to set a root password.
169if [ -z "$noRootPasswd" ] && chroot $mountPoint [ -x /run/wrappers/bin/passwd ] && [ -t 0 ]; then
170 echo "setting root password..."
171 chroot $mountPoint /run/wrappers/bin/passwd
172fi
173
174
175echo "installation finished!"