Import custom directories/files to package path on nix-store

Hello!

I’m very new to NixOS and trying to get some packages working is proving quite difficult, so I want to ask for help with answers that point me to the solution (or the solution itself, of course!)

Summary:

How can I add custom directories and files to specific package paths in the nix-store, preventing that directory or file name prepending its hash? (For example, adding the ranger/ directory (with its respective files like rc.conf, rifle.conf…) to the /etc/ path of the package /nix/store/xxxxxxxxxx-ranger/ and thus the file /nix/ store/xxxxxxxx-ranger/etc/ranger/rc.conf exists, and said ranger/ directory has been imported from the one in my /home/user/.config/ranger so that the configuration will be applied to ranger even if I access as root.

Long history (multiple cases):

  1. I use a program called xournalpp, which allows you to create custom plugins to execute certain actions. Those plugins need to be in a very specific location: /usr/share/xournalpp/plugins/. I tried various ways to get my files to that location such as:
  • Make a wrapper for the package that will copy the files from my local repository (“/home/…/Nix/…”) to the target path. This didn’t work as the path didn’t belong to the nix-store, so the wrapper couldn’t find any files to copy.

  • Applying antiquotating to escape the nix-store path worked fine because I was already able to access my “/home/…”, however when copying the plugins directory to the destination path, the directory was hashed ( and of course xournalpp doesn’t look for the plugins in xxxxxxxxxxx-plugins).
    Wrapper used on mi home-manager packages list to make this try:

(runCommand “xournalpp” {
buildInputs = [ pkgs.makeWrapper ];
} ‘’
mkdir $out
ln -s ${pkgs.xournalpp}/* $out
cp -r /home/user/Nix/home-manager/Unused/xournalpp/ $out/usr/share/xournalpp/

I can currently use the plugins as they made a commit that allows the expected path to be changed, however I would really like to know what is the proper way to deal with this situation with Nix, in case there is no other option.

  1. By migrating my standard settings to Nix, I managed to get everything working perfectly when configuring lightdm, except for the background image. This image must be (per lightdm configuration requirement), an absolute path. Again, I don’t know how I would be able to locate the image I want, and which is in, say /home/user/images/image.jpg in the path /etc/lightdm/background-image.jpg (that etc being the one associated to the lightdm package, of course), in order to write to the lightdm configuration


background-image = “/etc/lightdm/background-image.jpg”

And the image can be read correctly.

Note: I know that unlike the first case, it is possible to add files to the global /etc/ via environment.etc. However when I do
environment.etc.“lightdm/background-image.jpg”.source = absolute-path-to-myhome , it only works if I use the --impure flag when doing nixos-rebuild and again I would like to ask if there is any better way to achieve this (preferably without having to add that flag).

I’ve mentioned the specific packages where the problem occurred, but I’d appreciate if the solutions were agnostic to the package I want to add the files to (so I’m guessing it’s something to do with overlays, wrappers, or something like that).

Thank you very much in advance for your help, and in case my approach/handling of the situation is wrong, I appreciate if you point me to the most appropriate way to do it!

You cannot and that won’t change in the future. Every entry in the nix store must be hashed.

Patch the program to point to /var/lib or a derivation which contain the plugins.

Copy it to the nix store via ./image.png or a fetcher and then point to that path.

If lightdm has extraConfig then it could look like:

something.lightdm.extraConfig = ''
  background-image = "${./image.png}"
'';

and image.png is then added to your nixos configuration directory.

1 Like

First of all, thanks for your answer.

Now… About the last question (lightdm)

This is exactly what I don’t know how to do. Could you tell me more about how to import a file to my nixos configuration directory (on the nix-store, I mean)?
(I’ve searched and there seems to be several ways to do it imperatively as mentioned here, however if I can add the source from the configuration.nix file it would seem like the most appropriate way to do it.)

Btw, I have tried to do that source in many ways and none works

  • environment.etc.“/lightdm/image.jpg”.source = ./lightdm/image.jpg → Tries to get image from relative path from nix-store and thus doesn’t work

  • environment.etc.“/lightdm/image.jpg” = toString ./lightdm/image.jpg → This should work fine according to this, but for some reason the symlinks are created without any information no matter where I put the image regarding my configuration.nix

  • EDIT: I also tried adding it to my imports section (just like the .hardware-configuration.nix module), but it didn’t work. (I clarify that I don’t know if this makes much sense, I just did it because I couldn’t think of anything else)

As for the rest of the answer, I understood perfectly and it is clear to me. Once again, thank you very much.

Add this line verbatim to /etc/nixos/configuration.nix:

services.xserver.displayManager.lightdm.extraConfig = ''
  background-image = "${./image.png}"
'';

Then copy your image.png to /etc/nixos. That will do it :slight_smile:

Nix is capable of handling file paths and converting them to strings by copying them to the nix store and then writing their nix store path to whatever string you use them in. That’s what the ${./image.png} thing is doing.

Note that services.xserver.displayManager.lightdm.background also exists. I think the proper way of doing it is:

services.xserver.displayManager.lightdm.background = ./image.png;

But I don’t know if it’s actually that simple. Give it a try, I’d say.

1 Like

I forgot to mention that I had already tried that option, and it didn’t work for me unfortunately :confused: .

However, I tried both again

  • Added

background-image = “${./wallpaper.jpg}”

to my extraConfig. It didn’t work.

  • added

displayManager.lightdm.background = ./wallpaper.jpg;

(Having removed the background-image from extraConfig, of course). It didn’t work either.

In both cases it gives me the same error

building the system configuration…
error: getting status of ‘/nix/store/cgf23kdz8sw0cpq01ckrgbvcsididmq3-source/nixos/wallpaper.jpg’: No such file or directory
(use ‘–show-trace’ to show detailed location information)

That’s why I believed that before you could use something in the nix-store you had to ‘import’ it. Do you have any idea what could be going on?

In case it might be helpful (or precisely the root of the problem), my configuration.nix is ​​not in /etc. I keep all my configurations in a folder in my /home/user, which contains a flake.nix that I run to call configuration.nix. The folder tree has, in short, a structure like the following.

flake.nix
|── nixos
│ ├── configuration.nix
│ ├── hardware-configuration.nix
│ └── wallpaper.jpg

If your flake is inside a git repository, you’d need to “git add wallpaper.jpg” so that it will be included in the copy of your flake inside /nix/store

4 Likes

Yeah. Not a week passes without someone getting confused over this, poor UX design. Hindsight is 20/20 and whatnot.

On the up side, you’ll be warned about this when this PR lands: Source tree abstraction by edolstra · Pull Request #6530 · NixOS/nix · GitHub

3 Likes

Well… Uh… This is a little embarrassing :man_facepalming:. Yes, that was the mistake. I forgot that step.

Thank you all for your help, I really appreciate it, everything works fine now.

1 Like

It’s got to be documented somewhere in the Nix Manual, as it has caused so much confusion.

I’d rather see the PR land, personally. Taping over poor UX with documentation only helps so much; users will still be confused about files suddenly not being where they expect them to be. Most will either never read the manual far enough or forget this rather small detail anyway.

Telling the user that they likely forgot to stage that file on the command line when it happens is much less confusing.

Besides, kind of proving my point, it’s actually already explained with the git input type documented here:

When git+file is used without specifying ref or rev , files are fetched directly from the local path as long as they have been added to the Git repository. If there are uncommitted changes, the reference is treated as dirty and a warning is printed.

Emphasis mine.

I suppose it could be made more obvious, and more explicit that this applies to the flake’s repository too, but again, I don’t really think this will have much impact, it doesn’t solve the underlying UX issue.

2 Likes