Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 294a4e6ea524^
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e88f28965a7d
Choose a head ref
  • 3 commits
  • 7 files changed
  • 1 contributor

Commits on Feb 5, 2018

  1. Copy the full SHA
    294a4e6 View commit details
  2. Add a "nixos-enter" command

    This factors out the functionality in nixos-install for running a
    command inside a NixOS installation (nixos-install --chroot).
    edolstra committed Feb 5, 2018
    Copy the full SHA
    60cb230 View commit details
  3. nixos-install: Make compatible with Nix 2.0

    The use of Nix 2.0 significantly simplifies the installer, since we
    can just pass a different store URI (--store /mnt) - it's no longer
    needed to set up a chroot environment for the build, and to bootstrap
    Nix into the chroot.
    
    Also, commands that need to run in the installation (namely boot
    loader installation and setting a root password) are now executed
    using nixos-enter.
    
    This also removes the need for nixos-prepare-root since any required
    initialisation is done by Nix or by the activation script.
    edolstra committed Feb 5, 2018
    Copy the full SHA
    e88f289 View commit details
6 changes: 4 additions & 2 deletions nixos/doc/manual/development/testing-installer.xml
Original file line number Diff line number Diff line change
@@ -11,15 +11,17 @@ tedious, so here is a quick way to see if the installer works
properly:

<screen>
$ nix-build -A config.system.build.nixos-install
# mount -t tmpfs none /mnt
# nixos-generate-config --root /mnt
$ nix-build '&lt;nixpkgs/nixos>' -A config.system.build.nixos-install
# ./result/bin/nixos-install</screen>

To start a login shell in the new NixOS installation in
<filename>/mnt</filename>:

<screen>
# ./result/bin/nixos-install --chroot
$ nix-build '&lt;nixpkgs/nixos>' -A config.system.build.nixos-enter
# ./result/bin/nixos-enter
</screen>

</para>
119 changes: 119 additions & 0 deletions nixos/doc/manual/man-nixos-enter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">

<refmeta>
<refentrytitle><command>nixos-enter</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>

<refnamediv>
<refname><command>nixos-enter</command></refname>
<refpurpose>run a command in a NixOS chroot environment</refpurpose>
</refnamediv>

<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-enter</command>
<arg>
<arg choice='plain'><option>--root</option></arg>
<replaceable>root</replaceable>
</arg>
<arg>
<arg choice='plain'><option>--system</option></arg>
<replaceable>system</replaceable>
</arg>
<arg>
<arg choice='plain'><option>-c</option></arg>
<replaceable>shell-command</replaceable>
</arg>
<arg>
<arg choice='plain'><option>--help</option></arg>
</arg>
<arg>
<arg choice='plain'><option>--</option></arg>
<replaceable>arguments</replaceable>
</arg>
</cmdsynopsis>
</refsynopsisdiv>


<refsection><title>Description</title>

<para>This command runs a command in a NixOS chroot environment, that
is, in a filesystem hierarchy previously prepared using
<command>nixos-install</command>.</para>

</refsection>

<refsection><title>Options</title>

<para>This command accepts the following options:</para>

<variablelist>

<varlistentry>
<term><option>--root</option></term>
<listitem>
<para>The path to the NixOS system you want to enter. It defaults to <filename>/mnt</filename>.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>--system</option></term>
<listitem>
<para>The NixOS system configuration to use. It defaults to
<filename>/nix/var/nix/profiles/system</filename>. You can enter
a previous NixOS configuration by specifying a path such as
<filename>/nix/var/nix/profiles/system-106-link</filename>.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>--command</option></term>
<term><option>-c</option></term>
<listitem>
<para>The bash command to execute.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>--</option></term>

<listitem><para>Interpret the remaining arguments as the program
name and arguments to be invoked. The program is not executed in a
shell.</para></listitem>

</varlistentry>

</variablelist>

</refsection>


<refsection><title>Examples</title>

<para>Start an interactive shell in the NixOS installation in
<filename>/mnt</filename>:</para>

<screen>
# nixos-enter /mnt
</screen>

<para>Run a shell command:</para>

<screen>
# nixos-enter -c 'ls -l /; cat /proc/mounts'
</screen>

<para>Run a non-shell command:</para>

<screen>
# nixos-enter -- cat /proc/mounts
</screen>

</refsection>

</refentry>
3 changes: 2 additions & 1 deletion nixos/doc/manual/man-pages.xml
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
</author>

<copyright>
<year>2007-2015</year>
<year>2007-2018</year>
<holder>Eelco Dolstra</holder>
</copyright>

@@ -25,6 +25,7 @@
<xi:include href="man-nixos-build-vms.xml" />
<xi:include href="man-nixos-generate-config.xml" />
<xi:include href="man-nixos-install.xml" />
<xi:include href="man-nixos-enter.xml" />
<xi:include href="man-nixos-option.xml" />
<xi:include href="man-nixos-rebuild.xml" />
<xi:include href="man-nixos-version.xml" />
58 changes: 58 additions & 0 deletions nixos/modules/installer/tools/nixos-enter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#! @shell@

set -e

# Re-exec ourselves in a private mount namespace so that our bind
# mounts get cleaned up automatically.
if [ "$(id -u)" = 0 ]; then
if [ -z "$NIXOS_ENTER_REEXEC" ]; then
export NIXOS_ENTER_REEXEC=1
exec unshare --mount --uts -- "$0" "$@"
else
mount --make-rprivate /
fi
fi

mountPoint=/mnt
command=("bash" "--login")
system=/nix/var/nix/profiles/system

while [ "$#" -gt 0 ]; do
i="$1"; shift 1
case "$i" in
--root)
mountPoint="$1"; shift 1
;;
--system)
system="$1"; shift 1
;;
--help)
exec man nixos-enter
exit 1
;;
--command|-c)
command=("bash" "-c" "$1")
shift 1
;;
--)
command=("$@")
break
;;
*)
echo "$0: unknown option \`$i'"
exit 1
;;
esac
done

# Set up some bind mounts we'll want regardless of chroot or not
mkdir -m 0755 -p "$mountPoint/dev" "$mountPoint/proc" "$mountPoint/sys" "$mountPoint/run"
mount --rbind /dev "$mountPoint/dev"
mount -t proc none "$mountPoint/proc"
mount -t sysfs none "$mountPoint/sys"
mount -t tmpfs none "$mountPoint/run"

# Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
LOCALE_ARCHIVE=$system/sw/lib/locale/locale-archive chroot "$mountPoint" "$system/activate" >&2

exec chroot "$mountPoint" "${command[@]}"
187 changes: 58 additions & 129 deletions nixos/modules/installer/tools/nixos-install.sh
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
#! @shell@

# - make Nix store etc.
# - copy closure of Nix to target device
# - register validity
# - with a chroot to the target device:
# * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
# * install the boot loader
set -e
shopt -s nullglob

export PATH=@path@:$PATH

# Ensure a consistent umask.
umask 0022

# Re-exec ourselves in a private mount namespace so that our bind
# mounts get cleaned up automatically.
if [ "$(id -u)" = 0 ]; then
if [ -z "$NIXOS_INSTALL_REEXEC" ]; then
export NIXOS_INSTALL_REEXEC=1
exec unshare --mount --uts -- "$0" "$@"
else
mount --make-rprivate /
fi
fi

# Parse the command line for the -I flag
extraBuildFlags=()
chrootCommand=(/run/current-system/sw/bin/bash)
buildUsersGroup="nixbld"

mountPoint=/mnt

while [ "$#" -gt 0 ]; do
i="$1"; shift 1
@@ -42,8 +29,8 @@ while [ "$#" -gt 0 ]; do
mountPoint="$1"; shift 1
;;
--closure)
closure="$1"; shift 1
buildUsersGroup=""
# FIXME: --closure is a misnomer
system="$1"; shift 1
;;
--no-channel-copy)
noChannelCopy=1
@@ -57,150 +44,92 @@ while [ "$#" -gt 0 ]; do
--show-trace)
extraBuildFlags+=("$i")
;;
--chroot)
runChroot=1
if [[ "$@" != "" ]]; then
chrootCommand=("$@")
fi
break
;;
--help)
exec man nixos-install
exit 1
;;
--debug)
set -x
;;
*)
echo "$0: unknown option \`$i'"
exit 1
;;
esac
done

set -e
shopt -s nullglob

if test -z "$mountPoint"; then
mountPoint=/mnt
fi

if ! test -e "$mountPoint"; then
echo "mount point $mountPoint doesn't exist"
exit 1
fi

# Get the path of the NixOS configuration file.
if test -z "$NIXOS_CONFIG"; then
NIXOS_CONFIG=/etc/nixos/configuration.nix
if [[ -z $NIXOS_CONFIG ]]; then
NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix
fi

if [ ! -e "$mountPoint/$NIXOS_CONFIG" ] && [ -z "$closure" ]; then
echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist"
if [[ ${NIXOS_CONFIG:0:1} != / ]]; then
echo "$0: \$NIXOS_CONFIG is not an absolute path"
exit 1
fi


# Builds will use users that are members of this group
extraBuildFlags+=(--option "build-users-group" "$buildUsersGroup")

# Inherit binary caches from the host
# TODO: will this still work with Nix 1.12 now that it has no perl? Probably not...
binary_caches="$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"binary-caches"};')"
extraBuildFlags+=(--option "binary-caches" "$binary_caches")

# We only need nixpkgs in the path if we don't already have a system closure to install
if [[ -z "$closure" ]]; then
nixpkgs="$(readlink -f "$(nix-instantiate --find-file nixpkgs)")"
export NIX_PATH="nixpkgs=$nixpkgs:nixos-config=$mountPoint/$NIXOS_CONFIG"
fi
unset NIXOS_CONFIG

# These get created in nixos-prepare-root as well, but we want to make sure they're here in case we're
# running with --chroot. TODO: --chroot should just be split into a separate tool.
mkdir -m 0755 -p "$mountPoint/dev" "$mountPoint/proc" "$mountPoint/sys"

# Set up some bind mounts we'll want regardless of chroot or not
mount --rbind /dev "$mountPoint/dev"
mount --rbind /proc "$mountPoint/proc"
mount --rbind /sys "$mountPoint/sys"

# If we asked for a chroot, that means we're not actually installing anything (yeah I was confused too)
# and we just want to run a command in the context of a $mountPoint that we're assuming has already been
# set up by a previous nixos-install invocation. In that case we set up some remaining bind mounts and
# exec the requested command, skipping the rest of the installation procedure.
if [ -n "$runChroot" ]; then
mount -t tmpfs -o "mode=0755" none $mountPoint/run
rm -rf $mountPoint/var/run
ln -s /run $mountPoint/var/run
for f in /etc/resolv.conf /etc/hosts; do rm -f $mountPoint/$f; [ -f "$f" ] && cp -Lf $f $mountPoint/etc/; done
for f in /etc/passwd /etc/group; do touch $mountPoint/$f; [ -f "$f" ] && mount --rbind -o ro $f $mountPoint/$f; done

if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then
echo "$0: installation not finished; cannot chroot into installation directory"
exit 1
fi
ln -s /nix/var/nix/profiles/system $mountPoint/run/current-system
exec chroot $mountPoint "${chrootCommand[@]}"
if [ ! -e "$NIXOS_CONFIG" ] && [ -z "$closure" ]; then
echo "configuration file $NIXOS_CONFIG doesn't exist"
exit 1
fi

# A place to drop temporary closures
# A place to drop temporary stuff.
trap "rm -rf $tmpdir" EXIT
tmpdir="$(mktemp -d)"

# Build a closure (on the host; we then copy it into the guest)
function closure() {
nix-build "${extraBuildFlags[@]}" --no-out-link -E "with import <nixpkgs> {}; runCommand \"closure\" { exportReferencesGraph = [ \"x\" (buildEnv { name = \"env\"; paths = [ ($1) stdenv ]; }) ]; } \"cp x \$out\""
}

system_closure="$tmpdir/system.closure"
# Use a FIFO for piping nix-store --export into nix-store --import, saving disk
# I/O and space. nix-store --import is run by nixos-prepare-root.
mkfifo $system_closure

if [ -z "$closure" ]; then
expr="(import <nixpkgs/nixos> {}).system"
system_root="$(nix-build -E "$expr")"
system_closure="$(closure "$expr")"
else
system_root=$closure
# Create a temporary file ending in .closure (so nixos-prepare-root knows to --import it) to transport the store closure
# to the filesytem we're preparing. Also delete it on exit!
# Run in background to avoid blocking while trying to write to the FIFO
# $system_closure refers to
nix-store --export $(nix-store -qR $closure) > $system_closure &
fi

channel_root="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")"
channel_closure="$tmpdir/channel.closure"
nix-store --export $channel_root > $channel_closure

# Populate the target root directory with the basics
@prepare_root@/bin/nixos-prepare-root "$mountPoint" "$channel_root" "$system_root" @nixClosure@ "$system_closure" "$channel_closure"

# nixos-prepare-root doesn't currently do anything with file ownership, so we set it up here instead
chown @root_uid@:@nixbld_gid@ $mountPoint/nix/store
subs="local?trusted=1 https://cache.nixos.org/"

# Build the system configuration in the target filesystem.
if [[ -z $system ]]; then
echo "building the configuration in $NIXOS_CONFIG..."
outLink="$tmpdir/system"
nix build --out-link "$outLink" --store "$mountPoint" "${extraBuildFlags[@]}" \
--substituters "$subs" \
-f '<nixpkgs/nixos>' system -I "nixos-config=$NIXOS_CONFIG"
system=$(readlink -f $outLink)
fi

# Set the system profile to point to the configuration. TODO: combine
# this with the previous step once we have a nix-env replacement with
# a progress bar.
nix-env --store "$mountPoint" "${extraBuildFlags[@]}" \
--substituters "$subs" \
-p $mountPoint/nix/var/nix/profiles/system --set "$system"

# Copy the NixOS/Nixpkgs sources to the target as the initial contents
# of the NixOS channel.
if [[ -z $noChannelCopy ]]; then
channelPath="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")"
if [[ -n $channelPath ]]; then
echo "copying channel..."
mkdir -p $mountPoint/nix/var/nix/profiles/per-user/root
nix-env --store "$mountPoint" --substituters 'local?trusted=1' "${extraBuildFlags[@]}" \
-p $mountPoint/nix/var/nix/profiles/per-user/root/channels --set "$channelPath" --quiet
fi
fi

# Grub needs an mtab.
ln -sfn /proc/mounts $mountPoint/etc/mtab
# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out.
touch "$mountPoint/etc/NIXOS"

# Switch to the new system configuration. This will install Grub with
# a menu default pointing at the kernel/initrd/etc of the new
# configuration.
echo "finalising the installation..."
if [ -z "$noBootLoader" ]; then
NIXOS_INSTALL_BOOTLOADER=1 chroot $mountPoint \
/nix/var/nix/profiles/system/bin/switch-to-configuration boot
if [[ -z $noBootLoader ]]; then
echo "installing the boot loader..."
# Grub needs an mtab.
ln -sfn /proc/mounts $mountPoint/etc/mtab
NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root "$mountPoint" -- /run/current-system/bin/switch-to-configuration boot
fi

# Run the activation script.
chroot $mountPoint /nix/var/nix/profiles/system/activate


# Ask the user to set a root password.
if [ -z "$noRootPasswd" ] && chroot $mountPoint [ -x /run/wrappers/bin/passwd ] && [ -t 0 ]; then
echo "setting root password..."
chroot $mountPoint /run/wrappers/bin/passwd
# Ask the user to set a root password, but only if the passwd command
# exists (i.e. when mutable user accounts are enabled).
if [[ -z $noRootPasswd ]] && [ -t 0 ]; then
nixos-enter --root "$mountPoint" -c '[[ -e /nix/var/nix/profiles/system/sw/bin/passwd ]] && echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd'
fi


echo "installation finished!"
23 changes: 11 additions & 12 deletions nixos/modules/installer/tools/tools.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# This module generates nixos-install, nixos-rebuild,
# nixos-generate-config, etc.

{ config, pkgs, modulesPath, ... }:
{ config, lib, pkgs, modulesPath, ... }:

with lib;

let
cfg = config.installer;
@@ -27,17 +29,8 @@ let
nixos-install = makeProg {
name = "nixos-install";
src = ./nixos-install.sh;

inherit (pkgs) perl pathsFromGraph rsync;
nix = config.nix.package.out;
cacert = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
root_uid = config.ids.uids.root;
nixbld_gid = config.ids.gids.nixbld;
prepare_root = nixos-prepare-root;

nixClosure = pkgs.runCommand "closure"
{ exportReferencesGraph = ["refs" config.nix.package.out]; }
"cp refs $out";
path = makeBinPath [ nixos-enter ];
};

nixos-rebuild =
@@ -69,6 +62,11 @@ let
inherit (config.system) nixosVersion nixosCodeName nixosRevision;
};

nixos-enter = makeProg {
name = "nixos-enter";
src = ./nixos-enter.sh;
};

in

{
@@ -83,10 +81,11 @@ in
nixos-generate-config
nixos-option
nixos-version
nixos-enter
];

system.build = {
inherit nixos-install nixos-prepare-root nixos-generate-config nixos-option nixos-rebuild;
inherit nixos-install nixos-prepare-root nixos-generate-config nixos-option nixos-rebuild nixos-enter;
};

};
2 changes: 1 addition & 1 deletion pkgs/tools/package-management/nix/default.nix
Original file line number Diff line number Diff line change
@@ -149,7 +149,7 @@ let

in rec {

nix = nixStable;
nix = nixUnstable;

nixStable = (common rec {
name = "nix-1.11.16";