diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000000..a6828c98fb5
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,50 @@
+# Experimental flake interface to Nixpkgs.
+# See https://github.com/NixOS/rfcs/pull/49 for details.
+{
+ edition = 201909;
+
+ description = "A collection of packages for the Nix package manager";
+
+ outputs = { self }:
+ let
+
+ jobs = import ./pkgs/top-level/release.nix {
+ nixpkgs = self;
+ };
+
+ lib = import ./lib;
+
+ systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ];
+
+ forAllSystems = f: lib.genAttrs systems (system: f system);
+
+ in
+ {
+ lib = lib // {
+ nixosSystem = { modules, ... } @ args:
+ import ./nixos/lib/eval-config.nix (args // {
+ modules = modules ++
+ [ { system.nixos.versionSuffix =
+ ".${lib.substring 0 8 self.lastModified}.${self.shortRev or "dirty"}";
+ system.nixos.revision = lib.mkIf (self ? rev) self.rev;
+ }
+ ];
+ });
+ };
+
+ checks.x86_64-linux.tarball = jobs.tarball;
+
+ htmlDocs = {
+ nixpkgsManual = jobs.manual;
+ nixosManual = (import ./nixos/release-small.nix {
+ nixpkgs = self;
+ }).nixos.manual.x86_64-linux;
+ };
+
+ legacyPackages = forAllSystems (system: import ./. { inherit system; });
+
+ nixosModules = {
+ notDetected = import ./nixos/modules/installer/scan/not-detected.nix;
+ };
+ };
+}
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 59ed1e507e2..01ff5ecf148 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -148,7 +148,7 @@ runTests {
"${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
in {
storePath = isStorePath goodPath;
- storePathDerivation = isStorePath (import ../.. {}).hello;
+ storePathDerivation = isStorePath (import ../.. { system = "x86_64-linux"; }).hello;
storePathAppendix = isStorePath
"${goodPath}/bin/python";
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
diff --git a/lib/tests/release.nix b/lib/tests/release.nix
index 737d142d253..069c015d783 100644
--- a/lib/tests/release.nix
+++ b/lib/tests/release.nix
@@ -2,7 +2,7 @@
pkgs.runCommandNoCC "nixpkgs-lib-tests" {
buildInputs = [ pkgs.nix (import ./check-eval.nix) ];
- NIX_PATH="nixpkgs=${pkgs.path}";
+ NIX_PATH = "nixpkgs=${toString pkgs.path}";
} ''
datadir="${pkgs.nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml
index 495dbc8859b..f4f663b84f0 100644
--- a/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixos/doc/manual/man-nixos-rebuild.xml
@@ -77,7 +77,14 @@
builder-spec
+
+
+
+ flake-uri
+
+
+
@@ -129,14 +136,17 @@
Description
- This command updates the system so that it corresponds to the configuration
- specified in /etc/nixos/configuration.nix. Thus, every
- time you modify /etc/nixos/configuration.nix or any
- NixOS module, you must run nixos-rebuild to make the
- changes take effect. It builds the new system in
- /nix/store, runs its activation script, and stop and
- (re)starts any system services if needed. Please note that user services need
- to be started manually as they aren't detected by the activation script at the moment.
+ This command updates the system so that it corresponds to the
+ configuration specified in
+ /etc/nixos/configuration.nix or
+ /etc/nixos/flake.nix. Thus, every time you
+ modify the configuration or any other NixOS module, you must run
+ nixos-rebuild to make the changes take
+ effect. It builds the new system in
+ /nix/store, runs its activation script, and
+ stop and (re)starts any system services if needed. Please note that
+ user services need to be started manually as they aren't detected
+ by the activation script at the moment.
@@ -508,6 +518,24 @@
+
+
+
+ flake-uri[name]
+
+
+
+ Build the NixOS system from the specified flake. It defaults to
+ the directory containing the target of the symlink
+ /etc/nixos/flake.nix, if it exists. The
+ flake must contain an output named
+ nixosConfigurations.name. If
+ name is omitted, it default to the
+ current host name.
+
+
+
+
@@ -554,6 +582,21 @@
+
+
+ /etc/nixos/flake.nix
+
+
+
+ If this file exists, then nixos-rebuild will
+ use it as if the option was given. This
+ file may be a symlink to a flake.nix in an
+ actual flake; thus /etc/nixos need not be a
+ flake.
+
+
+
+
/run/current-system
diff --git a/nixos/doc/manual/man-nixos-version.xml b/nixos/doc/manual/man-nixos-version.xml
index e9ad8bddcac..aada08c5b4a 100644
--- a/nixos/doc/manual/man-nixos-version.xml
+++ b/nixos/doc/manual/man-nixos-version.xml
@@ -12,16 +12,22 @@
- nixos-version
+ nixos-version
-
+
+
+
+
+
+
+
Description
@@ -84,12 +90,16 @@
+
Options
+
This command accepts the following options:
+
+
@@ -107,6 +117,21 @@
+
+
+
+
+
+
+
+ Print a JSON representation of the versions of NixOS and the
+ top-level configuration flake.
+
+
+
+
+
+
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 7db323d38e6..354274478a3 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -3,6 +3,9 @@
if [ -x "@shell@" ]; then export SHELL="@shell@"; fi;
set -e
+set -o pipefail
+
+export PATH=@path@:$PATH
showSyntax() {
exec man nixos-rebuild
@@ -13,6 +16,7 @@ showSyntax() {
# Parse the command line.
origArgs=("$@")
extraBuildFlags=()
+lockFlags=()
action=
buildNix=1
fast=
@@ -58,7 +62,7 @@ while [ "$#" -gt 0 ]; do
j="$1"; shift 1
extraBuildFlags+=("$i" "$j")
;;
- --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*)
+ --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*|-L|--refresh|--no-net)
extraBuildFlags+=("$i")
;;
--option)
@@ -93,6 +97,22 @@ while [ "$#" -gt 0 ]; do
--use-remote-sudo)
maybeSudo=(sudo --)
;;
+ --flake)
+ flake="$1"
+ shift 1
+ ;;
+ --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file)
+ lockFlags+=("$i")
+ ;;
+ --update-input)
+ j="$1"; shift 1
+ lockFlags+=("$i" "$j")
+ ;;
+ --override-input)
+ j="$1"; shift 1
+ k="$1"; shift 1
+ lockFlags+=("$i" "$j" "$k")
+ ;;
*)
echo "$0: unknown option \`$i'"
exit 1
@@ -202,7 +222,7 @@ fi
# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
-if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then
+if [[ -n $upgrade && -z $_NIXOS_REBUILD_REEXEC && -z $flake ]]; then
nix-channel --update nixos
# If there are other channels that contain a file called
@@ -225,8 +245,15 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then
export PATH=@nix@/bin:$PATH
fi
+# Use /etc/nixos/flake.nix if it exists. It can be a symlink to the
+# actual flake.
+if [[ -z $flake && -e /etc/nixos/flake.nix ]]; then
+ flake="$(dirname "$(readlink -f /etc/nixos/flake.nix)")"
+fi
+
# Re-execute nixos-rebuild from the Nixpkgs tree.
-if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
+# FIXME: get nixos-rebuild from $flake.
+if [[ -z $_NIXOS_REBUILD_REEXEC && -n $canRun && -z $fast && -z $flake ]]; then
if p=$(nix-build --no-out-link --expr 'with import {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then
export _NIXOS_REBUILD_REEXEC=1
exec $p/bin/nixos-rebuild "${origArgs[@]}"
@@ -234,10 +261,37 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
fi
fi
+# For convenience, use the hostname as the default configuration to
+# build from the flake.
+if [[ -n $flake ]]; then
+ if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
+ flake="${BASH_REMATCH[1]}"
+ flakeAttr="${BASH_REMATCH[2]}"
+ fi
+ if [[ -z $flakeAttr ]]; then
+ read -r hostname < /proc/sys/kernel/hostname
+ if [[ -z $hostname ]]; then
+ hostname=default
+ fi
+ flakeAttr="nixosConfigurations.\"$hostname\""
+ else
+ flakeAttr="nixosConfigurations.\"$flakeAttr\""
+ fi
+fi
+
+# Resolve the flake.
+if [[ -n $flake ]]; then
+ flake=$(nix flake info --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url)
+fi
+
# Find configuration.nix and open editor instead of building.
if [ "$action" = edit ]; then
- NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
- exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ if [[ -z $flake ]]; then
+ NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
+ exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ else
+ exec nix edit "${lockFlags[@]}" -- "$flake#$flakeAttr"
+ fi
exit 1
fi
@@ -296,7 +350,7 @@ prebuiltNix() {
remotePATH=
-if [ -n "$buildNix" ]; then
+if [[ -n $buildNix && -z $flake ]]; then
echo "building Nix..." >&2
nixDrv=
if ! nixDrv="$(nix-instantiate '' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then
@@ -337,7 +391,7 @@ fi
# Update the version suffix if we're building from Git (so that
# nixos-version shows something useful).
-if [ -n "$canRun" ]; then
+if [[ -n $canRun && -z $flake ]]; then
if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then
suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true)
if [ -n "$suffix" ]; then
@@ -358,15 +412,37 @@ fi
if [ -z "$rollback" ]; then
echo "building the system configuration..." >&2
if [ "$action" = switch -o "$action" = boot ]; then
- pathToConfig="$(nixBuild '' --no-out-link -A system "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '' --no-out-link -A system "${extraBuildFlags[@]}")"
+ else
+ outLink=$tmpDir/result
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" \
+ "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link $outLink
+ pathToConfig="$(readlink -f $outLink)"
+ fi
copyToTarget "$pathToConfig"
targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
- pathToConfig="$(nixBuild '' -A system -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '' -A system -k "${extraBuildFlags[@]}")"
+ else
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" "${extraBuildFlags[@]}" "${lockFlags[@]}"
+ pathToConfig="$(readlink -f ./result)"
+ fi
elif [ "$action" = build-vm ]; then
- pathToConfig="$(nixBuild '' -A vm -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '' -A vm -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm' is not supported with '--flake'" >&2
+ exit 1
+ fi
elif [ "$action" = build-vm-with-bootloader ]; then
- pathToConfig="$(nixBuild '' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm-with-bootloader' is not supported with '--flake'" >&2
+ exit 1
+ fi
else
showSyntax
fi
diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh
index 190c49a33ec..fb0fe26116a 100644
--- a/nixos/modules/installer/tools/nixos-version.sh
+++ b/nixos/modules/installer/tools/nixos-version.sh
@@ -6,8 +6,17 @@ case "$1" in
exit 1
;;
--hash|--revision)
+ if ! [[ @revision@ =~ ^[0-9a-f]+$ ]]; then
+ echo "$0: Nixpkgs commit hash is unknown"
+ exit 1
+ fi
echo "@revision@"
;;
+ --json)
+ cat < [--nixos-path ] [--system-path ] [--config-file ] [--config ] [--ensure-unique-name] [--auto-start] [--bridge ] [--port ] [--host-address ] [--local-address ]
+ nixos-container create
+ [--nixos-path ]
+ [--system-path ]
+ [--config ]
+ [--config-file ]
+ [--flake ]
+ [--ensure-unique-name]
+ [--auto-start]
+ [--bridge ]
+ [--port ]
+ [--host-address ]
+ [--local-address ]
nixos-container destroy
nixos-container start
nixos-container stop
nixos-container terminate
nixos-container status
- nixos-container update [--config ] [--config-file ]
+ nixos-container update
+ [--config ]
+ [--config-file ]
+ [--flake ]
nixos-container login
nixos-container root-login
nixos-container run -- args...
@@ -49,6 +63,8 @@ my $signal;
my $configFile;
my $hostAddress;
my $localAddress;
+my $flake;
+my $flakeAttr = "container";
GetOptions(
"help" => sub { showHelp() },
@@ -63,6 +79,7 @@ GetOptions(
"config-file=s" => \$configFile,
"host-address=s" => \$hostAddress,
"local-address=s" => \$localAddress,
+ "flake=s" => \$flake,
) or exit 1;
if (defined $hostAddress and !defined $localAddress or defined $localAddress and !defined $hostAddress) {
@@ -76,6 +93,11 @@ if (defined $configFile and defined $extraConfig) {
"Please define on or the other, but not both";
}
+if (defined $flake && $flake =~ /^(.*)#([^#"]+)$/) {
+ $flake = $1;
+ $flakeAttr = $2;
+}
+
# Execute the selected action.
mkpath("/etc/containers", 0, 0755);
@@ -97,8 +119,6 @@ sub writeNixOSConfig {
my $localExtraConfig = "";
-
-
if ($extraConfig) {
$localExtraConfig = $extraConfig
} elsif ($configFile) {
@@ -121,6 +141,14 @@ EOF
write_file($nixosConfigFile, $nixosConfig);
}
+sub buildFlake {
+ system("nix", "build", "-o", "$systemPath.tmp", "--",
+ "$flake#nixosConfigurations.\"$flakeAttr\".config.system.build.toplevel") == 0
+ or die "$0: failed to build container from flake '$flake'\n";
+ $systemPath = readlink("$systemPath.tmp") or die;
+ unlink("$systemPath.tmp");
+}
+
if ($action eq "create") {
# Acquire an exclusive lock to prevent races with other
# invocations of ‘nixos-container create’.
@@ -176,6 +204,7 @@ if ($action eq "create") {
push @conf, "HOST_BRIDGE=$bridge\n";
push @conf, "HOST_PORT=$port\n";
push @conf, "AUTO_START=$autoStart\n";
+ push @conf, "FLAKE=$flake\n" if defined $flake;
write_file($confFile, \@conf);
close($lock);
@@ -191,6 +220,10 @@ if ($action eq "create") {
mkpath($profileDir, 0, 0755);
# Build/set the initial configuration.
+ if (defined $flake) {
+ buildFlake();
+ }
+
if (defined $systemPath) {
system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
or die "$0: failed to set initial container configuration\n";
@@ -326,19 +359,35 @@ elsif ($action eq "status") {
}
elsif ($action eq "update") {
- my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
- # FIXME: may want to be more careful about clobbering the existing
- # configuration.nix.
- if ((defined $extraConfig && $extraConfig ne "") ||
- (defined $configFile && $configFile ne "")) {
- writeNixOSConfig $nixosConfigFile;
+ # Unless overriden on the command line, rebuild the flake recorded
+ # in the container config file. FIXME: read the container config
+ # in a more sensible way.
+ if (!defined $flake && !defined $configFile && !defined $extraConfig) {
+ my $s = read_file($confFile);
+ $s =~ /^FLAKE=(.*)$/m;
+ $flake = $1;
}
- system("nix-env", "-p", "$profileDir/system",
- "-I", "nixos-config=$nixosConfigFile", "-f", "",
- "--set", "-A", "system") == 0
- or die "$0: failed to build container configuration\n";
+ if (defined $flake) {
+ buildFlake();
+ system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
+ or die "$0: failed to set container configuration\n";
+ } else {
+ my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
+
+ # FIXME: may want to be more careful about clobbering the existing
+ # configuration.nix.
+ if ((defined $extraConfig && $extraConfig ne "") ||
+ (defined $configFile && $configFile ne "")) {
+ writeNixOSConfig $nixosConfigFile;
+ }
+
+ system("nix-env", "-p", "$profileDir/system",
+ "-I", "nixos-config=$nixosConfigFile", "-f", "",
+ "--set", "-A", "system") == 0
+ or die "$0: failed to build container configuration\n";
+ }
if (isContainerRunning) {
print STDERR "reloading container...\n";
diff --git a/pkgs/top-level/make-tarball.nix b/pkgs/top-level/make-tarball.nix
index 288971403f1..ff0b0568819 100644
--- a/pkgs/top-level/make-tarball.nix
+++ b/pkgs/top-level/make-tarball.nix
@@ -17,7 +17,10 @@ releaseTools.sourceTarball {
inherit officialRelease;
version = pkgs.lib.fileContents ../../.version;
- versionSuffix = "pre${toString nixpkgs.revCount}.${nixpkgs.shortRev}";
+ versionSuffix = "pre${
+ if nixpkgs ? lastModified
+ then builtins.substring 0 8 nixpkgs.lastModified
+ else toString nixpkgs.revCount}.${nixpkgs.shortRev or "dirty"}";
buildInputs = [ nix.out jq lib-tests ];
@@ -25,7 +28,7 @@ releaseTools.sourceTarball {
eval "$preConfigure"
releaseName=nixpkgs-$VERSION$VERSION_SUFFIX
echo -n $VERSION_SUFFIX > .version-suffix
- echo -n ${nixpkgs.rev or nixpkgs.shortRev} > .git-revision
+ echo -n ${nixpkgs.rev or nixpkgs.shortRev or "dirty"} > .git-revision
echo "release name is $releaseName"
echo "git-revision is $(cat .git-revision)"
'';
diff --git a/pkgs/top-level/release.nix b/pkgs/top-level/release.nix
index b8ce1fcbce5..78d70c0239a 100644
--- a/pkgs/top-level/release.nix
+++ b/pkgs/top-level/release.nix
@@ -14,9 +14,9 @@
, supportedSystems ? [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" ]
, limitedSupportedSystems ? [ "i686-linux" ]
# Strip most of attributes when evaluating to spare memory usage
-, scrubJobs ? true
+, scrubJobs ? true
# Attributes passed to nixpkgs. Don't build packages marked as unfree.
-, nixpkgsArgs ? { config = { allowUnfree = false; inHydra = true; }; }
+, nixpkgsArgs ? { config = { allowUnfree = false; inHydra = true; }; }
}:
with import ./release-lib.nix { inherit supportedSystems scrubJobs nixpkgsArgs; };