Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flake support #68897

Merged
merged 39 commits into from Feb 10, 2020
Merged

Flake support #68897

merged 39 commits into from Feb 10, 2020

Conversation

edolstra
Copy link
Member

@edolstra edolstra commented Sep 16, 2019

Motivation for this change

This PR:

  • Adds a flake.nix file to Nixpkgs, making Nixpkgs usable from other flakes.
  • Adds flake support to nixos-rebuild, enabling hermetic NixOS builds.
  • Adds flake support to nixos-container.

A typical NixOS system configuration flake looks like this:

{
  edition = 201909;

  outputs = { self, nixpkgs, dwarffs, hydra }: rec {

    nixosConfigurations.my-server = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules =
        [ dwarffs.nixosModules.dwarffs
          nixpkgs.nixosModules.notDetected
          hydra.nixosModules.hydra
          { system.configurationRevision = self.rev;
            /* typical configuration.nix stuff follows */
          }
        ];
    };

  };
}

which can be installed by doing

# nixos-rebuild switch --flake /path/to/flake --config my-server

(--config defaults to the host name so it can usually be omitted).

The option system.configurationRevision tracks the revision of the top-level flake. This allows the entire configuration to be reproduced reliably. In a running system, it can be queried using nixos-version:

$ nixos-version --json | jq -r .configurationRevision
2c475bc41c13e7a9ae5c16b6c10d8d328cd07ee7

Note: NIX_PATH is unavailable in flake-based builds. In particular this means that

imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];

in hardware-configuration.nix no longer works. Instead you have to use

modules = [ nixpkgs.nixosModules.notDetected ];

nixos-container also supports flakes. For example, the following command creates a container that serves the NixOS homepage:

$ nixos-container create homepage --flake nixos-homepage 
$ nixos-container start homepage 
$ curl http://$(nixos-container show-ip homepage)

TODO: add flake support to nixos-install, add tests.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nix-review --run "nix-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.
Notify maintainers

cc @

flake.nix Outdated

outputs = { self }:
let
pkgs = import ./. { system = "x86_64-linux"; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean we currently can't use the nixpkgs flake from any non-x86 system?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not from the nix command line. You can call it from other flakes with a non-x86_64-linux system argument though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use builtins.currentSystem?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, not in pure evaluation mode.

$ nix eval "(builtins.currentSystem)"
error: attribute 'currentSystem' missing, at (string):1:2
$ nix eval --impure "(builtins.currentSystem)"
"x86_64-linux"

@arianvp
Copy link
Member

arianvp commented Sep 17, 2019

I myself had a slightly different take on nixos-rebuild in the presence of flakes which I am using here: https://github.com/arianvp/nixos-stuff/blob/master/deployments.nix#L15-L46 (Though I'm still implementing the flake part, but the idea of calling lib.nixosSystem inside your package definition is the same to what I am doing).

The idea is that you ou can do:

nix run github:arianvp/nixos-stuff:deployments.arianvp-me -c deploy [switch|boot|test] [target*]

or in two steps:

nix build github:arianvp/nixos-stuff:deployments.arianvp-me
./result/deploy switch

# or deploy remotely
./result/deploy switch  root@arianvp.me

E.g. a nixos flake returns a nixos-rebuild-like command that can be called instead of having nixos-rebuild call nix build. Kind of an inversion of control thing.

Would such a thing be more ergonomic? It would also mean you don't need nixos-rebuild on your computer to be able to deploy a nixos derivation. (Because nixos-rebuild doesn't seem to be exposed as a package in nixpkgs. so I do this so I can deploy nixos servers from my non-nixos machines)

Of course this is a bit of a backwards incompatible change, but we could also keep the old nixos-rebuild for non-flake deployments, and use this "design pattern" for flake-like deployments.

What do you think?

@edolstra
Copy link
Member Author

edolstra commented Sep 19, 2019

@arianvp Well, you already don't need nixos-rebuild since you can build the top-level system derivation and then run its switch-to-configuration script, e.g.

$ nix build .:nixosConfigurations.vyr.config.system.build.toplevel
$ ./result/bin/switch-to-configuration test

which is just what nixos-rebuild does.

Edit: or indeed

$ nix run .:nixosConfigurations.vyr.config.system.build.toplevel -c switch-to-configuration test

as you suggested.

@edolstra
Copy link
Member Author

Update: added flake support to nixos-container.

@arianvp
Copy link
Member

arianvp commented Sep 19, 2019

Well and you have to nix-env --set it right? Would there be a way to do that in one step?

flake.nix Outdated Show resolved Hide resolved
flake.nix Outdated
legacyPackages = pkgs;

nixosModules = {
notDetected = ./nixos/modules/installer/scan/not-detected.nix;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why include this?

Copy link
Contributor

@jtojnar jtojnar Oct 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: NIX_PATH is unavailable in flake-based builds.


Should we add other modules as well? For example, I use the following imports on my server:

<nixpkgs/nixos/modules/profiles/minimal.nix>
<nixpkgs/nixos/modules/virtualisation/container-config.nix>
<nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>

@edolstra edolstra force-pushed the master branch 2 times, most recently from 1028bb3 to 4a4e146 Compare October 15, 2019 11:52
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/building-nixos-system-with-nix-build-and-a-channel-specifier/4747/2

Dirty trees no longer set 'rev', so we need to handle this.
@edolstra edolstra changed the title [WIP] Flake support Flake support Feb 5, 2020
Copy link
Contributor

@yorickvP yorickvP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be happy to see this merged. However, I'm afraid that the FIXME's in here will never get fixed once this is merged. We depend on the nixos-rebuild re'execing currently, so that fixme would be a blocker for moving to flakes for us, personally.

# 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important for my workflow

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The re-exec is fundamentally broken anyway, since it tries to build nixos-rebuild with the old Nix. (The code to upgrade Nix happens later.) We could do nix build $flake#nixosConfigurations.$flakeAttr.config.system.build.nixos-rebuild but I don't think it's useful currently.

nixos/modules/installer/tools/nixos-rebuild.sh Outdated Show resolved Hide resolved
@@ -296,7 +347,8 @@ prebuiltNix() {

remotePATH=

if [ -n "$buildNix" ]; then
# FIXME: get nix from the flake.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: get nix from the flake.

(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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixme: read the container config in a more sensible way

Copy link
Contributor

@yorickvP yorickvP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^

if [[ -z $flake ]]; then
pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
else
echo "TODO: not implemented" >&2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: not implemented

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not supporting nixos vm builds will ensure limited flake adoption.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't used build-vm in years.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use it almost all the time, to do integration tests of modules. It's fairly prominent in the documentation and one of nixos's selling points.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but nixos-rebuild build-vm is just a wrapper around nix build. It doesn't do anything you couldn't otherwise do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've used build-vm to test the many many PRs that I've reviewed, merged, and tested. It's a very very useful tool for me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean people can just do?

nix run vm -f '<nixpkgs/nixos>' --arg configuration "$PWD/configuration.nix" -c run-nixos-vm

if [[ -z $flake ]]; then
pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
else
echo "TODO: not implemented" >&2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: not implemented

@alyssais
Copy link
Member

alyssais commented Feb 6, 2020

I feel very conflicted about making this change now, when not only have we still not decided on the format for flake.nix, but the RFC seems to have been stalled for months…

"master" is not a valid SHA-1 commit hash, and it's not even
necessarily the branch used. 'nixos-version --revision' now returns an
error if the commit hash is not known.
@edolstra
Copy link
Member Author

Well and you have to nix-env --set it right? Would there be a way to do that in one step?

Yes, you can do nix build --profile /nix/var/nix/profiles/system $flake#nixosConfigurations.$hostname.config.system.build.toplevel to do the build and the profile update in one step.

Copy link
Member

@FRidh FRidh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to know how we deal on the stable with changes to e.g. the Flake format. Can it be relied on being stable during the lifetime of 20.03, or is it consider experimental? Probably needs a release note either way, clarifying this.

flake.nix Show resolved Hide resolved
@edolstra
Copy link
Member Author

I've added a note that it's experimental (so it shouldn't be relied on).

@edolstra edolstra merged commit 0e6ceb8 into NixOS:master Feb 10, 2020
@arianvp
Copy link
Member

arianvp commented Feb 13, 2020

Nixpkgs.lib.nixosSystem already exists as pkgs.nixos
It's confusing to have both. Can we remove one of the two?

Iirc nixpkgs.nixos is explicitly mentioned in our documentation too

I already noted this in November. But no reply. Could we still address this?

@edolstra
Copy link
Member Author

Ideally we would remove pkgs.nixos, since it's not a package, but I don't want to make incompatible changes since this is all experimental.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet