This is a random thing I started playing with after a conversation with @samueldr on IRC. Started with @matthewbauer’s nix-bundle which uses arx to bundle an executable and chroot into an env. And some inspiration from static-nix. Then added some opinionated defaults and a few hacks. Ended up with a self-installing script with minimal host machine dependencies.
As a user on a Linux machine without nix you can
- run ./myScript.sh which self-extracts the /nix/store to a tmp directory
- chroot’s into the environment
- It trims away the binary and wrapper and runs itself
- the nix-shell shebang will download/update dependencies
- your script runs.
- the store persists in /tmp and subsequent runs are faster
Pros:
- edit the script directly, no recompilation needed
- single file contains everything
- no nix install needed
- easy cleanup, remove /tmp/tmpx-* and the file itself
- no root needed (actually, fails with root)
Cons:
- super ugly hack
- only Linux due to nix-user-chroot
- Appimage approach doesn’t work due to the FUSE not writable by nix. Creating yet another store in another location led down a horrible rabbit hole.
- need to preload the correct /nix/store
- needs tricks to embed other languages into shell (see below)
- Too big
Ideas:
- Use static-nix?
- Appimage with non-standard remote store.
- nix run vs nix-shell: there are some benefits to the shebang approach, but nix run might be cleaner
The top of myScript.sh looks like:
#!/bin/sh
if [ ! -z "$IN_NIX_USER_CHROOT"]; then
#! /nix/env nix-shell
#! nix-shell --pure -I nixpkgs=channel://nixpkgs-unstable -p hello -i sh
echo Modify this script for a self-installing nix-shell in a chroot.
echo "The store will persist in TMPDIR due to nix-bundle's arx approach."
echo "This hard-codes a channel, feel free to modify."
echo
echo "Perhaps try '-i python' for a run-anywhere-with-nix python script"
echo "Cons:"
echo " Linux only due to nix-user-chroot"
echo " nix-shell is slow to start"
echo "Arguments:"
shift
echo "$@"
### Don't remove this exit, or weird things happen ###
exit
#ENDSENTINEL
fi
<ARX script>
<BINARY>
Python support requires a bit of commenting polyglot goodness.
#!/bin/sh
if [ ! -z "$IN_NIX_USER_CHROOT"]; then
#! /nix/env nix-shell
#! nix-shell --pure -I nixpkgs=channel://nixpkgs-unstable -p python bash -i python
"""": '
"""
print("hi")
quit()
""" : '
"""" # "
#ENDSENTINEL
fi
<ARX script>
<BINARY>
To build, grab GitHub - tomberek/nix-bundle: Bundle Nix derivations to run anywhere! (c2ec9977325392e483dd090c8f7af2f909023076) and run ./nix-bundle.sh nix /bin/nix-shell
to build a nix-shell
script, which can be manually edited.