How to create flake.nix for nix shell loading a few packages?

How do I create a flake.nix that does the equivalent of this shell script?

foobar-shell.sh (76 chars):

#!/usr/bin/env bash
exec nix shell nixpkgs#{python312,sqlite,ffmpeg,nodejs}

Or is a shell script the way to go? It just seems so un-nix-y…

What would a flake.nix look like that does the same thing, so I can:

$ nix shell dir-containing-flake-nix

(and get my zsh shell)? Flakes - NixOS Wiki did not give many hints.

A shell.nix file that does something similar (for use with nix-shell):

foobar-shell.nix (244 chars)

let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-23.11";
  pkgs = import nixpkgs { config = {}; overlays = []; };
in
pkgs.mkShellNoCC {
  packages = with pkgs; [
    python312
    sqlite
    ffmpeg
    nodejs
  ];
}

The foobar-shell.nix file has 3.2 times more characters than foobar-shell.sh and does almost the exact same thing, which doesn’t seem very efficient, so I’m hoping for a tighter flake.nix.

And nix-shell gives me bash. I use and want zsh.

This is the wildest concern I’ve seen for a 10-line file of code.

Anyway you want nix develop not nix shell if you want such a shell env. Set devShells.<system>.default to your mkShell command, and pkgs should be nixpkgs.legacyPackages.<system>, but that will be even more boilerplate, because flakes are boilerplatey.

Thank you for the hints, @waffle8946!

This works:

{
  description = "A flake that loads some packages";

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

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      rec {
        devShells.default = pkgs.mkShellNoCC {
          packages = with pkgs; [
            python312
            sqlite
            ffmpeg
            nodejs
          ];
        };
      }
    );
}

But nix develop gives me a bash shell just like nix-shell does.

From nix develop --help:

nix develop - run a bash shell that provides the build environment of a derivation

For me, a zsh user, the benefit of nix shell over nix-shell is exactly that it respects my user’s shell shell configuration and creates a zsh shell for zsh users. But getting zsh is apparently not possible without workarounds:

I use direnv to keep my shell.

Which then assumes that I’m always in a particular folder when needing that particular combination of packages.

Which is sometimes true, sometimes not.

If I understand correctly, what you want is to have multiple devshells specified in the devShells. <system> attribute set, with one of them set as the default. E.g., I have a dev shell for compiling a project I work on with GCC, and another with Clang. One t. hen enters the specific dev env with nix develop ./path/to/flake/folder#<name-of-the-devshell> (or using the specified default dev env when the name of the shell is omitted). And the shell used in the dev env can be set using either additional parameter --command $SHELL, or with something like

which is what I use and prefer. I always want the same shell, but different environment (packages).

1 Like

Thank you @Adda for your helpful hint on using nix-your-shell for zsh with nix-shell and nix develop.

In fact I mostly use this machine as my everyday desktop and don’t do much development on it. So no, I don’t want to vary the compilers. Actually, I want one set of packages when configuring/running backups, another when I’m downloading subtitles, and yet another set when playing with docker. Which is also why I find it odd that the command is nix develop to get the package set for maintaining backups, since this has nothing to do with development.

I find it odd that you say it has nothing to do with development yet list off python, nodejs, etc?

Reality is this snippet (taken from a larger context):

        devShells.backup = pkgs.mkShellNoCC {
          packages = with pkgs; [
            awscli2
            borgbackup
            borgmatic
            ncdu
          ];
        };

The other packages I mentioned were just to create a small example with packages people would recognize.

packages.<system>.<name> = pkgs.buildEnv { name = "foobar"; paths = [ pkgs.awscli ... ]; }; might be of interest then, which would permit using nix shell.

The specific packages do matter, as development packages are not really guaranteed to work so well in such an environment, as any necessary hooks will not be run, necessary envvars wouldn’t be set, etc.