Import a global cfg variable file (error: access to the absolute path '/nix/store/cfg' is forbidden in pure eval mode)

Hey there,

I am trying to create a “config” file that holds global variables. I wanted to import this file as needed in various other files. I can do this with the first, but the second I import that file into a second file, I get the following error: error: access to the absolute path '/nix/store/cfg' is forbidden in pure eval mode (use '--impure' to override).

I would then import it into a nix file with something like:

{ pkgs, lib, ... }:
let
  globalconf = import ../../../cfg/git;
in
......

I essentially want to put repeated info in this cfg file, or something sensitive where I can add it to git-crypt.

I usually build with sudo nixos-rebuild switch --flake .#hostname

Thanks.

So, the problem that error is trying to explain with confusingly functional-programming-inspired language, is that you’re depending on something outside of the confines of your repository.

Flakes try very hard to make sure that if you have a project, you will be able to reproduce a system or package or whatever from it, even if the computer it was developed on explodes.

In this case, ../../../cfg/git is not part of your project, so if your computer exploded and you only had a backup of your project you wouldn’t be able to build your configuration anymore.

Of course that doesn’t mean your project needs to contain everything. It already doesn’t contain the nixpkgs source for example. Nix has a mechanism to explicitly state your dependencies - your flake inputs. The idea is that - should your computer explode - you can look at your flake inputs to determine what projects you need access to to be able to rebuild it.

This ultimately is the concept of “purity” from functional programming languages - “side-effect”-free “functions” that don’t depend on any implicit external state whose presence - or disappearance - might cause problems. Purity can be used for all kinds of other useful things, such as caching, so it’s a pretty useful concept even outside of blow-up insurance.


So back in the real world you have two options: Either move that directory into the project (presumably a git repo, or whatever directory your flake.nix is in) or make a second flake containing only the git directory, and make its module an output (an outputs.nixosModule) and use it as an input for all your projects that need it.

The former is better if it’s all one project anyway, and doesn’t make sense to split up. The latter is better if you do in fact have multiple projects that all depend on the same thing. I’d wager your situation is really the former though, hard coupling like this for just system configurations seems like a code smell.

There is, of course, also the option of just using the --impure flag and accepting that your project isn’t perfectly reproducible (and that evaluation cannot be properly cached, among presumably other problems I’m less aware of).

Note that you can use a path:/some/absolute/path url to point to a local directory, so you don’t actually need to publish this with the rest of your project if it’s confidential. Storing passwords like this is a bad idea though, nix will put them in the world-readable nix store at build time - if you want to store passwords see this other answer by me: How to hide private info in a flake-based config? - #3 by TLATER

If all of this is still too confusing, I’ll need to know what your directory structure looks like, and what exactly you want to import from where. If you explain exactly what “config” stuff you want in there, I might even be able to suggest a more idiomatic solution.

2 Likes

Thanks for the response and excellent explanation.

My directory structure is:

.
├── cfg
│ ├── git
│ │ └── default.nix
│ └── neovim
│ └── default.nix
├── flake.lock
├── flake.nix
├── home
├── home-manager
│ ├── autostart
│ │ └── default.nix
│ ├── desktop
│ │ └── gnome
│ │ └── dconf
│ │ ├── dconf.nix
│ │ └── default.nix
│ ├── development
│ │ ├── default.nix
│ │ ├── go.nix
│ │ ├── npm.nix
│ │ └── python.nix
│ ├── fonts
│ │ ├── BerkeleyMono-BoldItalic.ttf
│ │ ├── BerkeleyMono-Bold.ttf
│ │ ├── BerkeleyMono-Italic.ttf
│ │ ├── berkeley-mono.nix
│ │ ├── BerkeleyMono-Regular.ttf
│ │ ├── BerkeleyMonoVariable-Italic.ttf
│ │ ├── BerkeleyMonoVariable-Regular.ttf
│ │ └── default.nix
│ ├── home.nix
│ ├── pkgs
│ │ ├── default.nix
│ │ ├── kopia.nix
│ │ ├── ncspot.nix
│ │ ├── neovim.nix
│ │ └── shell.nix
│ ├── shell
│ │ ├── alacritty.nix
│ │ ├── bash.nix
│ │ ├── default.nix
│ │ ├── encryption.nix
│ │ ├── fish.nix
│ │ ├── git.nix
│ │ ├── kitty.nix
│ │ ├── ssh.nix
│ │ └── wezterm.nix
│ ├── srvcs
│ │ └── default.nix
│ └── xdg.configFile-sample.nix
├── hosts
│ ├── common
│ │ ├── cfg
│ │ │ ├── default.nix
│ │ │ ├── etc_profile.nix
│ │ │ └── user.nix
│ │ ├── default.nix
│ │ ├── desktop
│ │ │ └── gnome
│ │ │ ├── default.nix
│ │ │ ├── gnome.nix
│ │ │ └── gnome-packages.nix
│ │ └── pkgs
│ │ ├── 1password.nix
│ │ ├── default.nix
│ │ ├── docker.nix
│ │ ├── insecure-packages.nix
│ │ ├── nextdns.nix
│ │ └── system-packages.nix
│ ├── tower
│ │ ├── amdgpu.nix
│ │ ├── configuration.nix
│ │ ├── default.nix
│ │ ├── disks.nix
│ │ └── hardware-configuration.nix
│ └── x13
│ ├── configuration.nix
│ ├── default.nix
│ ├── disks.nix
│ ├── hardware-configuration.nix
│ └── udev-rules-battery-threshold.nix
├── justfile
└── README.md

This is my git repo in its entirety. I was noting your comment about the path to the cfg folder, which is in the project folder. I bolded the files of interest.

Thanks!

That should be import ../../cfg/git; then, right?

You are correct, that was an incorrect import. It hasn’t solved my problem yet, but I need to go back and look at the code and update this thread.