Using local flake with configuration.nix with flake

Hi, I am a beginner of NixOS (about 2 weeks usage) and just experiencing flake from yesterday.
I want to use flake for my configuration.nix, but it keeps throwing an error when I run sudo nixos-rebuild switch:
error: cannot look up '<nixpkgs>' in pure evaluation mode (use '--impure' to override)
I appended the --impure flag and all run just fine, but I don’t want that.
I think it is caused by some of my local derivation .nix file, below is just one of the example.

Inside /etc/nixos/doasedit-1.0.6 directory, I have a script called doasedit which is installed with doasedit.nix as shown below:

with import <nixpkgs> {}; # bring all of Nixpkgs into scope
stdenv.mkDerivation rec {
  name = "doasedit-1.0.6";
  src = ./.;
  installPhase = ''
    mkdir -p $out/bin
    cp doasedit $out/bin
    '';
}

The above doasedit.nix file is imported and installed into /etc/nixos/doas-config.nix as shown below:

{ config, pkgs, ... }:
{
  environment.systemPackages = with pkgs; [
    doas-sudo-shim
    (import ./doasedit-1.0.6/doasedit.nix)
  ];
  security.doas.enable = true;
  security.sudo.enable = false;
  # some other doas config ...
}

The above /etc/nixos/doas-config.nix is imported into configuration.nix to set doas related changes.

Because of the --impure issue, now I am rewriting the doasedit.nix to be doasedit-flake.nix as below:

{
  description = "doasedit flake";
  inputs.nixpkgs.url = "nixpkgs/nixos-23.11";
  outputs = { self, nixpkgs }@inputs:
  let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
    inherit (pkgs) stdenv lib;
  in {
    packages.${system}.default = pkgs.stdenv.mkDerivation {
      name = "doasedit-1.0.6";
      src = ./.;
      installPhase = ''
        mkdir -p $out/bin
        cp doasedit $out/bin
        '';
    };
  };
}

The /etc/nixos/flake.nix I am using:

{
  description = "NixOS Flake";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs = { self , nixpkgs , nixpkgs-unstable , ... }@inputs: {
    nixosConfigurations = {
      "nixos" = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        specialArgs = { inherit inputs; };
        modules = [
        	./configuration.nix
        ];
      };
    };
  };
}

I do not know how to import the doasedit-flake.nix into doas-config.nix or configuration.nix or /etc/nixos/flake.nix

I googled and find something about specialArgs = { inherit inputs; }; in /etc/nixos/flake.nix, but I cannot get it to work. Or maybe it is just irrelevant.

Or is it not suitable to rewrite the doasedit.nix with flake in this case?

Please help!! Thank you very much!

Or can I just simply replace with import <nixpkgs> {}; with something so that I can use sudo nixos-rebuild without the --impure flag?

You want to add a derivation that depends on nixpkgs (stdenv) on top of nixpkgs. The way your doasedit.nix file is structured right now it calls nixpkgs from a channel <nixpkgs>. When using flakes nixpkgs does not come from a channel but is usually provided from the flake inputs.

A first step to make doasedit.nix flake compatible is to add a functional dependency on nixpkgs:

{ pkgs = import <nixpkgs> {} }:
with pkgs;
stdenv.mkDerivation rec {
  name = "doasedit-1.0.6";
  src = ./.;
  installPhase = ''
    mkdir -p $out/bin
    cp doasedit $out/bin
    '';
}

Now when adding doasedit to your system packages we call it with the nixpkgs provided from the flake, e.g:

{ config, pkgs, ... }:
{
  environment.systemPackages = with pkgs; [
    doas-sudo-shim
    (import ./doasedit-1.0.6/doasedit.nix  {inherit pkgs;}) 
  ];
  security.doas.enable = true;
  security.sudo.enable = false;
  # some other doas config ...
}

You could also define a separate flake for doasedit, you would then add it as an input in /etc/nixos/flake.nix. To have it available in configuration.nix you can add { _module.args = inputs;} to the modules list:



{
  description = "NixOS Flake";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs = { self , nixpkgs , nixpkgs-unstable , ... }@inputs: {
    nixosConfigurations = {
      "nixos" = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        specialArgs = { inherit inputs; };
        modules = [
            { _module.args = inputs;}
        	./configuration.nix
        ];
      };
    };
  };
}

The way I prefer to add my own packages is defining a flake mypkgs with all my own packages, defining an Overlay, and then adding a module using the overlay of my flake: ({ config, pkgs, ... }: { nixpkgs.overlays = [ mypkgs.overlays.default ]; }).

I hope this helps! If you have any further questions I am happy to help :slight_smile:.

1 Like

Thanks for your response and the explanation!
I think I understand a little bit more about it. (the functional dependency thing)

After your guide and playing with it a little bit,
I am now use this instead

{ pkgs }:
with pkgs;

at the beginning of doasedit.nix and --impure can be omitted, great!

I think I will later try the overlay method!

1 Like