Load "nix develop" environment within a shell script

I’m writting a “runner script” of sorts to onboard a new team that is hesitant to try Nix. My goal is to have them only need to

  1. install nix
  2. run the runner script to run the application

This means additional installing direnv and configuring will not work.
I have a flake.nix that sets up the whole environment.
Running nix develop works, but that creates a subshell, which means I can’t just write in the run.sh:

nix develop
configure things
and more things
and even more
run special code

How can I load the develop environment from within a shell script to then run more shell?

you could try


      · Run a series of script commands:

          | # nix develop --command bash -c "mkdir build && cmake .. && make"

from nix develop --help

but if you only need packages you could try something liek

#! /usr/bin/env nix-shell
#! nix-shell -i sh -p awscli2 jq coreutils ripgrep util-linux

configure things
and more things
and even more
run special code

in script.sh and then

chmod -x script.sh
./script.sh
1 Like

nix develop --command bash -c "

I have used that before, but it unfortunately won’t work in this script for a couple of reasons, mainly that what follows is conditional and a few hundred lines of shell.

#! /usr/bin/env nix-shell
#! nix-shell -i sh -p awscli2 jq coreutils ripgrep util-linux

This is interesting and could work, although I need something far more complex than I think you could put there:

  • multiple inputs (which is another thing I don’t quite have working in this context yet)
  • python libs that require a python3.withPackages context.

I see some references about pinning nixpkgs and multiline support with flakes here: Nix-shell shebang - NixOS Wiki. Time to dig in.

for

  • python libs that require a python3.withPackages context.

I use

#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ boto3 botocore ])"

import argparse
import boto3
  • multiple inputs (which is another thing I don’t quite have working in this context yet)

wdym by multiple inputs?

Is this, say a demonstration script, or something they’d use every time they run this script (with this script being the primary means of entering the shell?)

If this is the latter, it sounds to me like whatever you’re doing in the shell script should just be part of the shellHook on the devShell.

This is something they’ll be running every single time they interact with the stack. Perhaps a little more details will help clarify the constraints (and the weirdness).

  • This runner script is to run ansible, which itself is a python application.
  • The script must choose which version of ansible to run based on which environment is calling it (currently via an environment variable).
  • The script must also check out another repo for inventory at a specific git ref (inventory = a concept with Ansible to keep all nodes/things being managed along with their configuration).
  • The script finally initializes the environment by defining environment variables that ansible will consume, parses and passes any command line arguments and finally calls ansible.

The previous method of doing most of the above was to use a mixture of pyenv, pipenv and way too much scripting. Assuming the person has direnv installed, the entire script works as is. But, I also want the script to be smart enough to tell the direnv is not present and to manually load the environment the same way that direnv would, and to continue along in the script.

Perhaps this is simply not possible without direnv?

This is an interesting idea. In order to support multiple versions of ansible depending on which env is calling it, we have multiple flake.nix files. I’d want a way to not have to duplicate all that code somehow. There must be a way to load the contents of a file and pass to devShell?

I don’t (personally) feel clear enough on your exact requirements to say what I would or wouldn’t do. I’m reasonably confident there’s some way to do what you need, even it ends up being a kludge, but I’m not sure what it is.

Maybe you want to be using nix print-dev-env. Maybe you can get away with something like I did in nix-shell, but make it lovely. Maybe your shell script should be a runnable app in the flake. Maybe the inline expressions for a shell shebang given earlier are the right fit. There are probably a few more I am leaving out.