Linux 7.3 brings an incredibly powerful feature: eBPF binfmt_misc hooks. You can see some discussion on this here, especially the blog post by @fzakaria here.
One idea is to make the PT_INTERP elf header support $ORIGIN, so that binaries are completely relocatable. However, this breaks compatibility with older Linux kernels, and with users that otherwise cannot enable BPF.
A solution is to define the normal PT_INTERP as /nix/store/..., but to additionally define a separate PT_INTERP_NIX section that replaces the absolute path with a relative path. On a Linux 7.3+ kernel with the bpf program loaded, the binary will be relocatable, but on older systems everything would still work as long as the binary is installed into the global path. I think this is a good path forward for Nix.
But for full compatibility, the same thing needs to happen for shebangs.
The binfmt_misc program can also recognize the execution of scripts that start with #!, and can rewrite them as necessary. One option is to just substitute $ORIGIN in the shebang, but this again would lose non-bpf compatibility.
I propose the following protocol: binaries that start with #!\t (that is 0x23, 0x21, 0x09, 0x20) will be marked as “relocatable”. Ie. the bpf match program will return true when the file starts with those 4 characters.
When the bpf program recognizes a script, the interpretation rules are: skip all characters from the start of input until the first newline. Then skip the following sequence of non-whitespace characters, then the next sequence of whitespace characters. After that, the rest of that line will be parsed as a shebang, but will have $ORIGIN replaced.
For example:
#! /nix/store/xxxxxxxxxx-python3-3.14.8/bin/python3.14
# $ORIGIN/../../xxxxxxxxxx-python3-3.14.8/bin/python3.14
print("Hello from Python!")
#! /nix/store/xxxxxxxxxx-lua5_5-5.5.1/bin/lua
-- $ORIGIN/../../xxxxxxxxxx-lua5_5-5.5.1/bin/lua
print "Hello from Lua!"
#! /nix/store/xxxxxxxxxx-bash-5.3p20/bin/bash -e
# $ORIGIN/../../xxxxxxxxxx-bash-5.3p20/bin/bash -e
echo "Hello from Bash!"
I think that using a recognizable yet uncommon sequence of whitespace (\t ) is a good way to implement this feature, but let me know if you have any thoughts!