makeSetupHook and shell.nix

I just discovered makeSetupHook and an interesting use for it in shell.nix files.

In a few projects, I had shell.nix files that used shellHook to run helper scripts I’d tucked away in a ./nix subdirectory.

For example, in a few cases I wanted to spin up a database upon entering the shell and spin it down upon exiting:

{ pkgs ? import <nixpkgs> {} }:

with pkgs; mkShell {
  name = "foo";
  buildInputs = [ postgresql ];
  shellHook = ''
    trap "'$PWD/nix/pgSetup' remove" EXIT
    nix/pgSetup
  '';
}

One problem with this approach is it relies on the presence of these random shell scripts that are not represented as part of the derivation itself. Another problem is that I end up duplicating these scripts across projects.

I was going to address this by packing the helper scripts with writeShellScript, but then I noticed makeSetupHook. It sounds like it was designed with a different use-case in mind, but it lets me package the setup script and automatically runs it upon entering the shell as long as I include it in my buildInputs:

{ pkgs ? import <nixpkgs> {} }:

let
  pgSetup = with pkgs; makeSetupHook { } ./nix/pgSetup;

in with pkgs; mkShell {
  name = "foo";
  buildInputs = [ postgresql pgSetup ];
  shellHook = ''
    trap '${pgSetup}/nix-support/setup-hook remove' EXIT
  '';
}

So ./nix/pgSetup needs to exist relative to the derivation, but it doesn’t need to exist relative to nix-shell invocation, allowing, for example, using it like:

nix-shell https://github.com/path/to/nix-shells/archive/master.tar.gz -A foo

I might actually switch to using writeShellScript, as it offers more flexibility and control, but I thought this was interesting.

6 Likes

Would you post your $PWD/nix/pgSetup? I am trying to create mongoSetup
with;

shell.nix:

with import <nixpkgs> {};
let
  mongoSetup = makeSetupHook { } ./nix/mongo-setup.sh;
in mkShell {

	buildInputs = [
		mongodb
	];

	shellHook = ''
		echo starting mongod in the current dir.
		echo 'mongod --dbpath $PWD/data > mongod.log'
		trap '${mongoSetup}/nix-support/setup-hook remove' EXIT
	'';

}

./nix/monog-setup.sh:

#!/bin/sh

mkdir -p data
mongod --dbpath data > mongod.log

But this is does not spin up the mongod as it does not kill with trap.