diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index 91aa910a2..cdfdc1a6e 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -227,24 +227,32 @@ flag, e.g. --option gc-keep-outputs false.
build-use-chrootIf set to true, builds will be
- performed in a chroot environment, i.e., the
- build will be isolated from the normal file system hierarchy and
- will only see its dependencies in the Nix store, the temporary
- build directory, private versions of /proc,
+ performed in a chroot environment, i.e.,
+ they’re isolated from the normal file system hierarchy and will
+ only see their dependencies in the Nix store, the temporary build
+ directory, private versions of /proc,
/dev, /dev/shm and
/dev/pts, and the paths configured with the
build-chroot-dirs
option. This is useful to prevent undeclared dependencies
- on files in directories such as
- /usr/bin.
+ on files in directories such as /usr/bin. In
+ addition, on Linux, builds run in rivate PID, mount, network, IPC
+ and UTS namespaces to isolate them from other processes in the
+ system (except that fixed-output derivations do not run in private
+ network namespace to ensure they can access the network).
- The use of a chroot requires that Nix is run as root (so you
- should use the “build
- users” feature to perform the actual builds under different
- users than root). Currently, chroot builds only work on Linux
- because Nix uses “bind mounts” to make the Nix store and other
- directories available inside the chroot. Kernel version 3.13 or later
- is needed.
+ Currently, chroots only work on Linux and Mac OS X. The use
+ of a chroot requires that Nix is run as root (so you should use
+ the “build users”
+ feature to perform the actual builds under different users
+ than root).
+
+ If this option is set to relaxed, then
+ fixed-output derivations and derivations that have the
+ __noChroot attribute set to
+ true do not run in chroots.
+
+ The default is false.
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index e64bd3fef..ac5ca7bc3 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1768,12 +1768,20 @@ void DerivationGoal::startBuilder()
functions like fetchurl (which needs a proper /etc/resolv.conf)
work properly. Purity checking for fixed-output derivations
is somewhat pointless anyway. */
- useChroot = settings.useChroot;
-
- if (fixedOutput) useChroot = false;
-
- /* Hack to allow derivations to disable chroot builds. */
- if (get(drv.env, "__noChroot") == "1") useChroot = false;
+ {
+ string x = settings.get("build-use-chroot", string("false"));
+ if (x != "true" && x != "false" && x != "relaxed")
+ throw Error("option ‘build-use-chroot’ must be set to one of ‘true’, ‘false’ or ‘relaxed’");
+ if (x == "true") {
+ if (get(drv.env, "__noChroot") == "1")
+ throw Error(format("derivation ‘%1%’ has ‘__noChroot’ set, but that's not allowed when ‘build-use-chroot’ is ‘true’") % drvPath);
+ useChroot = true;
+ }
+ else if (x == "false")
+ useChroot = false;
+ else if (x == "relaxed")
+ useChroot = !fixedOutput && get(drv.env, "__noChroot") != "1";
+ }
if (useChroot) {
/* Allow a user-configurable set of directories from the
@@ -1856,7 +1864,8 @@ void DerivationGoal::startBuilder()
% (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
/* Create /etc/hosts with localhost entry. */
- writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
+ if (!fixedOutput)
+ writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
/* Make the closure of the inputs available in the chroot,
rather than the whole Nix store. This prevents any access
@@ -1964,7 +1973,9 @@ void DerivationGoal::startBuilder()
- The private network namespace ensures that the builder
cannot talk to the outside world (or vice versa). It
- only has a private loopback interface.
+ only has a private loopback interface. (Fixed-output
+ derivations are not run in a private network namespace
+ to allow functions like fetchurl to work.)
- The IPC namespace prevents the builder from communicating
with outside processes using SysV IPC mechanisms (shared
@@ -1983,8 +1994,9 @@ void DerivationGoal::startBuilder()
*/
Pid helper = startProcess([&]() {
char stack[32 * 1024];
- pid_t child = clone(childEntry, stack + sizeof(stack) - 8,
- CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD, this);
+ int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
+ if (!fixedOutput) flags |= CLONE_NEWNET;
+ pid_t child = clone(childEntry, stack + sizeof(stack) - 8, flags, this);
if (child == -1) {
if (errno == EINVAL)
throw SysError("cloning builder process (Linux chroot builds require 3.13 or later)");
@@ -2081,10 +2093,10 @@ void DerivationGoal::runChild()
/* Set up a nearly empty /dev, unless the user asked to
bind-mount the host /dev. */
+ Strings ss;
if (dirsInChroot.find("/dev") == dirsInChroot.end()) {
createDirs(chrootRootDir + "/dev/shm");
createDirs(chrootRootDir + "/dev/pts");
- Strings ss;
ss.push_back("/dev/full");
#ifdef __linux__
if (pathExists("/dev/kvm"))
@@ -2095,13 +2107,24 @@ void DerivationGoal::runChild()
ss.push_back("/dev/tty");
ss.push_back("/dev/urandom");
ss.push_back("/dev/zero");
- foreach (Strings::iterator, i, ss) dirsInChroot[*i] = *i;
createSymlink("/proc/self/fd", chrootRootDir + "/dev/fd");
createSymlink("/proc/self/fd/0", chrootRootDir + "/dev/stdin");
createSymlink("/proc/self/fd/1", chrootRootDir + "/dev/stdout");
createSymlink("/proc/self/fd/2", chrootRootDir + "/dev/stderr");
}
+ /* Fixed-output derivations typically need to access the
+ network, so give them access to /etc/resolv.conf and so
+ on. */
+ if (fixedOutput) {
+ ss.push_back("/etc/resolv.conf");
+ ss.push_back("/etc/nsswitch.conf");
+ ss.push_back("/etc/services");
+ ss.push_back("/etc/hosts");
+ }
+
+ for (auto & i : ss) dirsInChroot[i] = i;
+
/* Bind-mount all the directories from the "host"
filesystem that we want in the chroot
environment. */
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index c5abeee28..e382b3aac 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -47,7 +47,6 @@ Settings::Settings()
syncBeforeRegistering = false;
useSubstitutes = true;
buildUsersGroup = getuid() == 0 ? "nixbld" : "";
- useChroot = false;
useSshSubstituter = true;
impersonateLinux26 = false;
keepLog = true;
@@ -158,7 +157,6 @@ void Settings::update()
_get(syncBeforeRegistering, "sync-before-registering");
_get(useSubstitutes, "build-use-substitutes");
_get(buildUsersGroup, "build-users-group");
- _get(useChroot, "build-use-chroot");
_get(impersonateLinux26, "build-impersonate-linux-26");
_get(keepLog, "build-keep-log");
_get(compressLog, "build-compress-log");
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index c17e10d7c..0230a540e 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -145,9 +145,6 @@ struct Settings {
/* The Unix group that contains the build users. */
string buildUsersGroup;
- /* Whether to build in chroot. */
- bool useChroot;
-
/* Set of ssh connection strings for the ssh substituter */
Strings sshSubstituterHosts;