-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow builtins.storePath
in pure mode
#5868
Comments
It may not be impure, but it does make builds non-reproducible: it prevents rebuilding a flake unless you already have the store path or you have a substituter that can provide it. It's true that fetchers have the same problem, but they at least in principle provide a mechanism to get their output. |
Indeed binary-only distribution is by definition not reproducible, as all relations to the source are intentionally stripped by the owner. It is the single constraint that defines this use case. What if |
I consider storePath can be something like "fetchNar" or "fetchStorePathUsingNixMechanisms". It absolutely should be allowed for CA paths. The remaining question is what to do with non-CA paths, ie: non-deterministic output. I'd say this should be allowed as those paths are still signed and "morally" provide the same functionality. Consuming something like https://github.com/NixOS/hydra/blob/master/src/lib/Hydra/View/NixExprs.pm#L30-L34 would be another use-case. While this mechanism can be abused it also opens up possibilities like pre-evaluating nixpkgs, binary distribution. Yes, it destroys build-time information, but sometimes that might be exactly the intention, or one can provide other mechanisms to provide that info (eg: can use a drvPath here ) Docs should suggest one not use this haphazardly and warn about the consequences.
I'm not sure which way to go for this. We have several other places to put substituter information: nix.conf's, env var, CLI, flake nixConfig. This is a natural extension to specify it per-derivation. I'd suggest that it should only have the semantics "extra-substituters" if anything. But I'd be okay with it not being present or the empty-list to start with. I started by removing that check, but it seems flake evaluation uses drvPath's to express what needs to be built. |
I suppose the |
I started implementing this, but must admit I started changing too much stuff and probably broke stuff I shouldn't. I am still interested and would like to collaborate on it. Also open to the "similar primop" idea if that is deemed more appropriate. |
Brainstorming: potentially provide a way to tie a substituter to the storePath, to make it similar to fetchers where one can lock the narHash from the perspective of a particular substituter (non-CA paths). My original idea was to leverage nixConfig.substituters at the flake.nix level, but that might not be granular enough? Another approach: a new input type.
|
Implementation-wise, you'll still need some primop, as flake evaluation happens through
Then it'd be similar to the status quo, but allowing In response to your earlier comment
Per-derivation is not a goal here, even if it is interesting. I believe it needs per-derivation meta info to be passed to libstore, which is not something we have, so that's quite a can of worms. (
Yes, the regular substituters should be queried if the |
I'm leaning toward the simpler approach and removing the restriction from the builtin. The loss of reproducibility would be identical compared to declaring any src via git/github/url/mirrors with regards to it being possible to be unable to fetch + reproduce the content if the source has changed/moved/permissions/etc. In some ways this would be more resilient due to substituters being utilized as the mechanism to get their output, they are similar to having mirrors available. The distinction is that other fetchers are normally locked with a content hash. I presume builtins.storePath could be used with CA-derivations as well, and this could be implemented in a mkFakeCADerivation function which would be distinct from the mkFakeNormalDerivation that relies upon the trust in a substituter to provide the correct output. [this is already trust we utilize]. |
This issue also prevents nixpkgs' I think it's a bit unfortunate that in order to get a dependency's reference graph we have to use a derivation with Is there any hope of making |
The binary distribution use case is solved by supporting input addressed path in pure mode in
This surprises me. Nix is pretty good at finding references to anything in the entire derivation graph; not just the input's outputs' closure as you might expect. It's why have #7087 instead of a rot13 hack to hide dependencies through an otherwise unnecessary derivation. So maybe I'm mistaken on that assumption?
I don't think you need output references, right? Just derivation references.
|
There's another use-case for Consider the following: with import <nixpkgs> {};
writeTextDir "blah.nix" ''
{
p = ./.;
}
'' This is basically the reduced version of what
That is, there is no way of generating the path to the current file of nix source (which obviously is present) as a string, with context. Motivating example:Something that frustratingly cannot be done in nixpkgs of today is something like the following: {config, pkgs, ...}:
{
# No! because of https://github.com/NixOS/nix/issues/7075. also because it copies nixpkgs again for no reason
# nix.nixPath = [ "nixpkgs=${pkgs.path}" ];
# No! because the string has no context, so the nixpkgs never gets onto a remote system if you do a remote build.
# nix.nixPath = [ "nixpkgs=${toString pkgs.path}" ];
# No! because you are a flake.
# nix.nixPath = [ "nixpkgs=${builtins.storePath pkgs.path}" ];
} Yes, the pkgs.path can be yeeted in via an anonymous module in the flake.nix, but we cannot ship a generic and automatic version of this to users. This is sad! We should be able to do that: NixOS users deserve to be able to pin nixpkgs in the flake registry and in It would be possible, since nixpkgs.lib.nixosSystem is a flakes only thing, to sneak a |
I would like this as an alternative to #8963, making I think If we allow |
The biggest risk is that due to indecisiveness we bother users with unnecessary fear, uncertainty and doubt until we finish all the other things. Because that's what should happen. In the big picture we have for the foreseeable future, solving the problems @Ericson2314 indicates is just not a priority, yet still a significant expenditure of effort. I'm ok with either approach, but if in doubt pick the simpler one. Above all pick one though, because neglecting this functionality is really wasteful. |
I also wouldn't mind if we do this first, I mostly opted for |
Use case: simplify source based deployment script expressionI'm (again) running into this issue, but now while generating a deployment script which needs a derivation closure for a string of bash statements, to be built and run on a remote host. I.e. this is for source-based deployment. Solution using
|
I didn't immediate understand this, but then I talked to @roberth and now I get it.
|
Improve
|
@edolstra would it be feasible to relax this constraint in cases where we know that it won't make builds non-reproducible. The particular case I have in mind is IFD: When I import from a derivation, I know that I will trigger the realization of that derivation so that all of its runtime closure will be in my I believe this makes vanilla IFD more flexible by itself, but I've actually run into dead ends because of this when |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2023-11-20-nix-team-meeting-minutes-105/35902/1 |
Discussed in the Nix maintenance meeting. We couldn't manage to reach an agreement, so this is currently in a limbo. |
…xt for self This is an extremely subtle feature which is necessary to be able to incur dependencies on this nixpkgs's source code without copying it twice (NixOS/nix#9428, NixOS/nix#5868). pkgs.path is not sufficient, because actually using it incurs a copy, which winds up looking like /nix/store/HASH-HASH-source in flakes. Similarly, `toString pkgs.path` is not sufficient because that does not have any string context, so it will not incur a dependency if it's used. It's exceptionally subtle. There are four cases: - non flakes, pure mode: can't do anything about this, we must copy to the store. - non flakes, not already in the store: can't do anything about this, we are copying to the store. - non flakes, already in the store: storePath gives us a string with context for free. - flakes: overlay makes it a stringification of self.outPath. In all cases, this is a string with appropriate context to transfer this nixpkgs to another system.
Hi all, I've been tackling trying to get glibc patched on a NixOS system without having to recompile all derivations/packages as every update will cause a measurable amount of downtime/poor performance on the system and without having to sacrifice the pure essence of Nix. system.replaceRuntimeDependencies = [
{
original = pkgs.glibc;
replacement = pkgs.glibc.overrideAttrs {
patches = [
(import <nix/fetchurl.nix> {
url = "[REDACTED]";
hash = "[REDACTED]";
})
];
};
}
]; |
Replacing glibc is possible. Needs a few tricks: NixOS/bundlers#18 (comment) In that case I'm only adding a file, but something similar would help with your override. |
Is your feature request related to a problem? Please describe.
The
storePath
builtin is disallowed in pure mode. This hinders a use case for binary-only distribution via binary caches.Describe the solution you'd like
storePath
isn't impure. It's not even non-hermetic, because it specifies that a store path should exist, which is the same level of hermeticity that a fetcher provides (both built-in or FOD); for example that a git commit should exist.Describe alternatives you've considered
Use Docker to distribute binary-only software that was originally built with Nix.
The text was updated successfully, but these errors were encountered: