Best way to define common FHS environment?

I have the following definition in my systemPackages, which gives me an fhs binary which drops me into a shell which looks like a normal Linux:

  environment.systemPackages = with pkgs; [
    (pkgs.buildFHSUserEnv {
      name = "fhs";
      targetPkgs = pkgs: with pkgs; [
        alsa-lib atk cairo cups curl dbus expat file fish fontconfig freetype
        fuse glib gtk3 libGL libnotify libxml2 libxslt netcat nspr nss openjdk8
        openssl.dev pango pkg-config strace udev vulkan-loader watch wget which
        xorg.libX11 xorg.libxcb xorg.libXcomposite xorg.libXcursor
        xorg.libXdamage xorg.libXext xorg.libXfixes xorg.libXi xorg.libXrandr
        xorg.libXrender xorg.libXScrnSaver xorg.libxshmfence xorg.libXtst
        xorg.xcbutilkeysyms zlib fontconfig.lib
      ];
      profile = ''export FHS=1'';
      runScript = "fish";
    })
    # all of my other packages
  ];
$ ls /usr/lib
"/usr/lib": No such file or directory (os error 2)

$ fhs

(fhs) $ ls /usr/lib | head -n 5
dr-xr-xr-x   - nobody  1 Jan  1970 32
dr-xr-xr-x   - nobody  1 Jan  1970 audit
dr-xr-xr-x   - nobody  1 Jan  1970 bash
dr-xr-xr-x   - nobody  1 Jan  1970 cairo
lrwxrwxrwx  69 nobody  1 Jan  1970 crt1.o -> /nix/store/aji28kaprqnrkapmfyjnnnv3ffvlaq0a-fhs-usr-target/lib/crt1.o
(fhs) $ # I can now run various unpatched vanilla binaries here

It works great, except that there’s this frightening block of standard packages which I partially copied from somewhere, and partially append a bunch of random stuff myself.

Is there some maintained-by-someone-else package I can re-use here? I am essentially looking for buildFHSUserEnv specialized to a set of “standard” packages (whatever that set is at the current moment in time).

I’m not aware of any standard set of packages, but something like this can include most of what you want

builtins.concatMap (p: p.buildInputs) config.environment.systemPackages

I’m not super familiar with it, but I think there are various lists of packages for use with buildfhsuserenvs in nixpkgs.

For instance:

Used here for example (I think):

Thanks, this is exactly what I was looking for!

I wanted to share this little script:

nix shell --impure --expr '(builtins.getFlake "nixpkgs-current").legacyPackages.${builtins.currentSystem}.buildFHSUserEnv { name = "fhs"; targetPkgs = p: with p; ['"$*"' ]; }' --command fhs

Arguments accepted are simply packages. This can also be improved to include support for additional arguments to the shell itself etc…

Thank you so much for this solution, it’s been a huge help in setting up a development shell with Nix flakes.

If this can help someone else, here’s how I’ve used it in flake.nix:

{
  description = ".NET development environment based on the Filesystem Hierarchy Standard (FHS)";
  # https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs = { nixpkgs, ... } @ inputs:
  let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};

    # .NET SDKs
    dotnet_sdk = (with pkgs.dotnetCorePackages; combinePackages [
      # Install all the .NET SDK versions needed here...
      # sdk_8_0
      # sdk_7_0
      sdk_6_0
    ]);
  in
  {
    # Create development shell based on the Filesystem Hierarchy Standard (FHS) with a set of
    # standard packages based on the list maintained by the appimagetools package
    #
    # buildFHSEnv -> https://nixos.org/manual/nixpkgs/stable/#sec-fhs-environments
    #
    # The packages included in appimagetools.defaultFhsEnvArgs are:
    # https://github.com/NixOS/nixpkgs/blob/fd6a510ec7e84ccd7f38c2ad9a55a18bf076f738/pkgs/build-support/appimage/default.nix#L72-L208
    devShells.${system}.default = (pkgs.buildFHSEnv (pkgs.appimageTools.defaultFhsEnvArgs // {
          name = "dotnet-development-environment";
          # Packages installed in the development shell
          targetPkgs = pkgs: with pkgs; [
            # .NET SDK
            dotnet_sdk
            # Run PowerShell scripts, which are sometimes included in NuGet packages like Playwright
            powershell
            # Timezones
            tzdata
            # Locales
            glibcLocales
          ];
          # Commands to be executed in the development shell
          profile = ''
            # Ensure that dotnet tools can find the .NET location
            export DOTNET_ROOT="${dotnet_sdk}";

            # Set LANG for locales, otherwise it is unset when running "nix-shell --pure"
            export LANG="C.UTF-8"

            # Remove duplicate commands from Bash shell command history
            export HISTCONTROL=ignoreboth:erasedups

            # Do not pollute $HOME with config files (both paths are ignored in .gitignore)
            export DOTNET_CLI_HOME="$PWD/.net_cli_home";
            export NUGET_PACKAGES="$PWD/.nuget_packages";

            # Put dotnet tools in $PATH to be able to use them
            export PATH="$DOTNET_CLI_HOME/.dotnet/tools:$PATH"
          '';
        })).env;
  };
}