The problem with that is that all methods of managing extensions that Firefox makes available which do not touch the profile directory are imperative instead of declarative, allowing only instructions to install or uninstall extensions from the profile directory.
I don’t believe there can be any NixOS solution less complicated than running Firefox in a way that shadows the extension directory (user namespace + bindmount?) - so we will probably have to use home-manager and just accept that one profile must correspond to one set of extensions.
I don’t believe there can be any NixOS solution less complicated than running Firefox over a FUSE layer that shadows the extension directory - so we will probably have to use home-manager and just accept that one profile must correspond to one set of extensions.
There might be some solution along the lines of running Firefox during nix-build to initialise the extension directory, then overwrite the profile’s extensions directory on start. (I do that with whole profile, which is a bit easier, but maybe partial profile overwrite also works fine with some care).
Both of those will install extensions to a users directory, leaving them there when started with a Firefox version without extension or when they are removed from the configuration.
GitHub - mozilla/policy-templates: Policy Templates for Firefox can be used to force extensions to be installed in a declarative way.
But it also requires a policies.json file in the “installation directory”, so we should solve that problem first.
In my private nix config, I solve this by using bind mounts + user namespaces in a wrapper, which sets things up, so firefox sees the distribution directory under the correct path. But that’s probably too complex for an “official” solution.
That’s not well documented as far as I can see (at least I had trouble finding documentation), but it appears to be the directory where the shared libraries can be found.
$(nix eval --raw nixpkgs.firefox-unwrapped)/lib/firefox/ in our case, to be precise.
That shouldn’t be too hard to do right? Just make a wrapper that copies firefox$out, adds the profile.json and patch all self-references of firefox if necessary.
Yes, that’s what the tor-browser-bundle derivation does I think. But then if you have multiple variants of the wrapper, it will consume a lot of disk space. Maybe that is acceptable though?
firefox-unwrapped only is 148M, I think that is okay. Most people will only have one version anyways.
If the ff code is clean and the location of profile.json is defined in a central place, we could also patch that to take the location from an environment variable or a flag. Then use a normal wrapper.
So probably pretty much everything could be symlinked. You could make a separate derivation juts for profile.json and then use symlinkJoin or something.
The wrapper script is /nix/store/igr92m1c10cahcngda5n2v88g7z46vkr-firefox-unwrapped-65.0.2/bin/firefox and it does some work. But I agree, that that’s not a fundamental problem.
What can be symlinked depends on what part of firefox actually resolves the paths.
If its libxul (~100M) for example, then we can’t symlink that :-/
Because it will try to resolve the symlink and expect the configuration files to be found in the correct paths relative to its “true” location.
But I just tried and found that its the actual “firefox” executable at firefox-unwrapped/lib/firefox/firefox, which does the resolving. It would have to be copied, but the rest can be symlinked, and its only a few k.
Edit: Ok, actually that’s to be expected, after all the other things there are shared libraries. It would be extremely odd for paths to be resolved relative to one of them.