How to convert this nix.shell file into a buildFHSUserEnv?

I have this nix.shell which is close to what I want:

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "node";
    buildInputs = [
        nodejs-16_x
        nodePackages.firebase-tools
        nodePackages.node-gyp
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
        export NPM_PACKAGES="$HOME/.npm-packages"
    '';
}

I want to convert it to buildFHSUserEnv. Reading the documentation, they indicate the following example:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "simple-x11-env";
  targetPkgs = pkgs: (with pkgs;
    [ udev
      alsaLib
    ]) ++ (with pkgs.xorg;
    [ libX11
      libXcursor
      libXrandr
    ]);
  multiPkgs = pkgs: (with pkgs;
    [ udev
      alsaLib
    ]);
  runScript = "bash";
}).env

How to introduce my nix.shell content into a FHS-compatible lightweight sandbox?

stdenv.mkDerivation {
  buildInputs = [
    (pkgs.buildFHSUserEnv {
      ...
    }).env
  ];
}
1 Like

Thanks, @Sandro.

Unfortunately, the system is retrieving the following error:

You need to tell it where stdenv comes from, eg:

let
  pkgs = import <nixpkgs> {};
  inherit (pkgs) stdenv; # and what else you need
in stdenv.mkDerivation { … }

Though for a shell using mkShell is much more common.

You probably wan to use with pkgs to not maintain a useless list of attributes.

I am not a friend of with.

And it also is a documented antipattern.

https://nix.dev/anti-patterns/language#with-attrset-expression

Perhaps something like:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "node";
  targetPkgs = pkgs: [
    pkgs.nodejs-16_x
    pkgs.nodePackages.firebase-tools
    pkgs.nodePackages.node-gyp
  ];
  
  runScript = pkgs.writeScript "init.sh" ''
    export PATH="$PWD/node_modules/.bin/:$PATH"
    export NPM_PACKAGES="$HOME/.npm-packages"
    exec bash
  '';
}).env

You don’t have the same inputs in a shell.nix as in a normal package’s default.nix. and emulating that with inherit has no real benefits except that you need to maintain that inherit.

And it also is a documented antipattern.

That’s not an official documentation. Also rec is fine to use and the example given on the page is almost twice in size of lines for nothing really.

Let’s agree to disagree, though I have to be honest, regardless of the language, whether you call it with, import or use, doing it “unqualified” or with a broad glob is considered an antipattern by the respective communities.

I will continue to not use with, and I will continue to propose alternatives. Of course I will not force anyone to use one or the other.