diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index 2b7a69a0c..42906ddff 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -40,7 +40,12 @@
The configuration files consist of
name =
-value pairs, one per line.
+value pairs, one per line. Other
+files can be included with a line like include
+path, where
+path is interpreted relative to the current
+conf file and a missing file is an error unless
+!include is used instead.
Comments start with a # character. Here is an
example configuration file:
diff --git a/src/libutil/config.cc b/src/libutil/config.cc
index d46ca65a3..0e502769e 100644
--- a/src/libutil/config.cc
+++ b/src/libutil/config.cc
@@ -80,7 +80,31 @@ void Config::applyConfigFile(const Path & path, bool fatal)
vector tokens = tokenizeString >(line);
if (tokens.empty()) continue;
- if (tokens.size() < 2 || tokens[1] != "=")
+ if (tokens.size() < 2)
+ throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
+
+ auto include = false;
+ auto ignoreMissing = false;
+ if (tokens[0] == "include")
+ include = true;
+ else if (tokens[0] == "!include") {
+ include = true;
+ ignoreMissing = true;
+ }
+
+ if (include) {
+ if (tokens.size() != 2)
+ throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
+ auto p = absPath(tokens[1], dirOf(path));
+ if (pathExists(p)) {
+ applyConfigFile(p, fatal);
+ } else if (!ignoreMissing) {
+ throw Error("file '%1%' included from '%2%' not found", p, path);
+ }
+ continue;
+ }
+
+ if (tokens[1] != "=")
throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
string name = tokens[0];
diff --git a/tests/init.sh b/tests/init.sh
index 41cca047d..e5353598b 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -16,7 +16,12 @@ mkdir "$NIX_CONF_DIR"
cat > "$NIX_CONF_DIR"/nix.conf < "$NIX_CONF_DIR"/nix.conf.extra <