A fuse filesystem that dynamically populates contents of /bin and /usr/bin/ so that it contains all executables from the PATH of the requesting process. This allows executing FHS based programs on a non-FHS system. For example, this is useful to execute shebangs on NixOS that assume hard coded locations like /bin or /usr/bin etc.
Mount envfs on /usr/bin sudo envfs /usr/bin
Programs are magically available, based on the PATH of the calling process.
$ /usr/bin/env --version
env (GNU coreutils) 9.1
Packaged by https://nixos.org
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Richard Mlynarik, David MacKenzie, and Assaf Gordon.
$ echo $PATH
If the caller doesn't have the binary in the PATH, it will fail.
$ PATH= /usr/bin/env --version 2>&1 || true
As you can see, /usr/bin is empty. $ ls -la /usr/bin
total 1
drwxr-xr-x 3345300086 root root 0 Jan 1 1970 .
drwxr-xr-x 3 root root 3 Sep 5 13:04 ..
By default, binaries are only available whenever the calling process executes or
open a program, not when using stat or listing the directory:
$ ls -la /usr/bin/env 2>&1 || true
ls: cannot access '/usr/bin/env': No such file or directory
This behaviour can be overridden by setting ENVFS_RESOLVE_ALWAYS=1
.
$ ENVFS_RESOLVE_ALWAYS=1 ls -la /usr/bin/env
lr----x--t 1 root root 0 Jan 1 1970 /usr/bin/env -> /nix/store/4vjigg3pr8bns6id4af51mza5p73l9lx-coreutils-9.1/bin/env
In conclusion, combined with the usual Nix wrappers or nix-shells, it makes things magically work!
Choose one of the following methods:
Since NixOS 23.05 you can enable envfs with a single line:
{
services.envfs.enable = true;
}
If you use nix flakes support:
{
inputs.envfs.url = "github:Mic92/envfs";
inputs.envfs.inputs.nixpkgs.follows = "nixpkgs";
outputs = { self, nixpkgs, envfs }: {
# change `yourhostname` to your actual hostname
nixosConfigurations.yourhostname = nixpkgs.lib.nixosSystem {
# change to your system:
system = "x86_64-linux";
modules = [
./configuration.nix
envfs.nixosModules.envfs
];
};
};
}
First add it to niv:
$ niv add Mic92/envfs
Then add the following to your configuration.nix in the imports
list:
{
imports = [ "${(import ./nix/sources.nix).envfs}/modules/envfs.nix" ];
}
As root run:
$ nix-channel --add https://github.com/Mic92/envfs/archive/main.tar.gz envfs
$ nix-channel --update
Then add the following to your configuration.nix in the imports
list:
{
imports = [ <envfs/modules/envfs.nix> ];
}
Add the following to your configuration.nix:
{
imports = [ "${builtins.fetchTarball "https://github.com/Mic92/envfs/archive/main.tar.gz"}/modules/envfs.nix" ];
}
or with pinning:
{
imports = let
# replace this with an actual commit id or tag
commit = "f2783a8ef91624b375a3cf665c3af4ac60b7c278";
in [
"${builtins.fetchTarball {
url = "https://github.com/Mic92/envfs/archive/${commit}.tar.gz";
# replace this with an actual hash
sha256 = "0000000000000000000000000000000000000000000000000000";
}}/modules/envfs.nix"
];
}
$ nix-build
$ sudo ./result/bin/envfs -o bind-mount=/bin /usr/bin