Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor nixos-install to separate out filesystem build logic
The key distinction I'm drawing is that there's a component that deals with the store of the machine being built, and another component for the store building it. The inner part of it assumes nothing from the builder (doesn't need chroot or root powers) so it can run comfortably inside a Nix build, as well as nixos-rebuild. I have some upcoming work that will use that to significantly speed up and streamline image builds for NixOS, especially on virtualized hosts like EC2, but it's also a reasonable speedup on native hosts.
- Loading branch information
Showing
5 changed files
with
164 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#! @shell@ | ||
|
||
# This script's goal is to perform all "static" setup of a filesystem structure from pre-built store paths. Everything | ||
# in here should run in a non-root context and inside a Nix builder. It's designed primarily to be called from image- | ||
# building scripts and from nixos-install, but because it makes very few assumptions about the context in which it runs, | ||
# it could be useful in other contexts as well. | ||
# | ||
# Current behavior: | ||
# - set up basic filesystem structure | ||
# - make Nix store etc. | ||
# - copy Nix, system, channel, and misceallaneous closures to target Nix store | ||
# - register validity of all paths in the target store | ||
# - set up channel and system profiles | ||
|
||
# Ensure a consistent umask. | ||
umask 0022 | ||
|
||
set -e | ||
|
||
mountPoint="$1" | ||
channel="$2" | ||
system="$3" | ||
shift 3 | ||
closures="$@" | ||
|
||
PATH="@coreutils@/bin:@nix@/bin:@perl@/bin:@utillinux@/bin:@rsync@/bin" | ||
|
||
if ! test -e "$mountPoint"; then | ||
echo "mount point $mountPoint doesn't exist" | ||
exit 1 | ||
fi | ||
|
||
# Create a few of the standard directories in the target root directory. | ||
mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/etc $mountPoint/run $mountPoint/home | ||
mkdir -m 01777 -p $mountPoint/tmp | ||
mkdir -m 0755 -p $mountPoint/tmp/root | ||
mkdir -m 0755 -p $mountPoint/var | ||
mkdir -m 0700 -p $mountPoint/root | ||
|
||
ln -s /run $mountPoint/var/run | ||
|
||
# Create the necessary Nix directories on the target device | ||
mkdir -m 0755 -p \ | ||
$mountPoint/nix/var/nix/gcroots \ | ||
$mountPoint/nix/var/nix/temproots \ | ||
$mountPoint/nix/var/nix/userpool \ | ||
$mountPoint/nix/var/nix/profiles \ | ||
$mountPoint/nix/var/nix/db \ | ||
$mountPoint/nix/var/log/nix/drvs | ||
|
||
mkdir -m 1775 -p $mountPoint/nix/store | ||
|
||
# All Nix operations below should operate on our target store, not /nix/store. | ||
# N.B: this relies on Nix 1.12 or higher | ||
export NIX_REMOTE=local?root=$mountPoint | ||
|
||
# Copy our closures to the Nix store on the target mount point, unless they're already there. | ||
for i in $closures; do | ||
# We support closures both in the format produced by `nix-store --export` and by `exportReferencesGraph`, | ||
# mostly because there doesn't seem to be a single format that can be produced outside of a nix build and | ||
# inside one. See https://github.com/NixOS/nix/issues/1242 for more discussion. | ||
if [[ "$i" =~ \.closure$ ]]; then | ||
echo "importing serialized closure $i to $mountPoint..." | ||
nix-store --import < $i | ||
else | ||
# There has to be a better way to do this, right? | ||
echo "copying closure $i to $mountPoint..." | ||
for j in $(perl @pathsFromGraph@ $i); do | ||
echo " $j... " | ||
rsync -a $j $mountPoint/nix/store/ | ||
done | ||
|
||
nix-store --register-validity < $i | ||
fi | ||
done | ||
|
||
# Create the required /bin/sh symlink; otherwise lots of things | ||
# (notably the system() function) won't work. | ||
if [ ! -x $mountPoint/@shell@ ]; then | ||
echo "Error: @shell@ wasn't included in the closure" >&2 | ||
exit 1 | ||
fi | ||
mkdir -m 0755 -p $mountPoint/bin | ||
ln -sf @shell@ $mountPoint/bin/sh | ||
|
||
echo "setting the system closure to '$system'..." | ||
nix-env "${extraBuildFlags[@]}" -p $mountPoint/nix/var/nix/profiles/system --set "$system" | ||
|
||
ln -sfn /nix/var/nix/profiles/system $mountPoint/run/current-system | ||
|
||
# Copy the NixOS/Nixpkgs sources to the target as the initial contents of the NixOS channel. | ||
mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles | ||
mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user | ||
mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root | ||
|
||
if [ -z "$noChannelCopy" ] && [ -n "$channel" ]; then | ||
echo "copying channel..." | ||
nix-env --option build-use-substitutes false "${extraBuildFlags[@]}" -p $mountPoint/nix/var/nix/profiles/per-user/root/channels --set "$channel" --quiet | ||
fi | ||
mkdir -m 0700 -p $mountPoint/root/.nix-defexpr | ||
ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels | ||
|
||
# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out. | ||
touch $mountPoint/etc/NIXOS | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.