When I declare system.autoUpgrade.flake = inputs.self.outPath; I get this error in the nixos-upgrade systemd service: error: your NixOS configuration path seems to be missing essential files. Apparently this is because inputs.self.outPath returns the directory after being copied into the nix store.
I want system.autoUpgrade to rebuild & switch my flake regularly, but would rather not have my config dependent on hardcoded directory paths.
Can’t be done, pure eval explicitly prohibits accessing the repo path on disk for build/eval reproducibility.
If you could access it, copying the config to another directory would potentially result in a different build output with no code changes. In fact, that’s exactly what you’re trying to do, and nix is preventing a reproducibility issue for you.
You need to hardcode the path, but look at it this way, the configuration location becomes a fundamental part of the system configuration if you’re going to use a local directory to update from, so in effect it kinda has to be hardcoded. You need to run at least one rebuild to change the path if you do want to move the configuration anyway.
You could create an option or variable for it if you wanted to vary the location on different systems.
Basically, the update service will include a line somewhere that says something like:
nixos-rebuild switch --flake /etc/nixos
The file that contains this line is built by nix. If you could use some kind of magic variable like this:
nixos-rebuild switch --flake ${real-flake-path}
… simply running the build with your flake in a different directory would produce a different script. That is non-reproducible output, because it depends on the directory your flake happens to be in.
This might not seem like a problem, but remember that nix does caching and remote builds.
What should ${real-flake-path} resolve to in those situations? If you move your flake and rebuild, nix’ cache means that the script won’t be updated, since nix doesn’t see any changes to the file. This causes the updates to break, because the flake has moved, and cannot be fixed unless you delete the script from the store.
Worse, if you do remote builds and deployment, the flake isn’t even present on those systems, so the location of the path is undefined. Ideally the build would fail, or - as nix does - that scenario is impossible to create to begin with.
Those are the kinds of non-obvious issues caused by reproducibility bugs that nix is designed to prevent. Hence pure eval disallows exactly what you’re trying to do.