-
Notifications
You must be signed in to change notification settings - Fork 6
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
feat: adds tools for hermetic nix installation #48
Conversation
I'm not sure if you care for this device, but in case someone is interested, here it is. |
Hello @filmil, thanks for your contribution. I think the feature would deserve consideration for inclusion in tweag/rules_nixpkgs#75, rather than in setup by users of What do you think? |
Well, this is not really a collection of build rules, so it can not be placed into a rules package.
I am not sure of the best way to enable easy addition into repos that need it.
I just thought it would be maybe an interesting approach to publicize. Especially because it just reuses existing tools in a new way, and
as all nix+bazel attempts I've seen prior to this one were based on an existing system `/nix/store`. This requires a somewhat onerous
nix installation, which is a big commitment for someone who isn't quite at that point in their dev journey.
This approach makes a private nix store that is tied to a specific bazel cache directory.
Which makes it easier to use out of the box, as no special nix installation needed.
And may be distributed cache friendly. I was a bit surprised how easy it
was to apply to a new repo (`clodl`) once I worked out the exact needed changes.
But the way this is done (copying files over) is not very pleasant nor maintenance friendly.
My goal is to help bazelize the world. In the past I worked out https://github.com/filmil/bazel-rules-bid, which is a way to
run a single bazel build step inside a docker container. This avoids needing to bazelize things that are hard or onerous
to bazelize, such as python programs with deeply nested dependencies. The downside there is the need to use `docker`,
as podman does not work because of the nested sandboxing, and the general
lack of hermeticity using docker images - though we still have reproducibility. It's also a bit annoying to maintain docker build
environments for each project separately.
Hermetic nix+bazel be even better if there was a way to install nix in a user-defined prefix without needing `chroot`.
|
Applies the device introduced at: https://github.com/filmil/bazel-nix-flakes to produce a hermetic nix installation when bazel is started. Made some changes to the clodl runner and pinned bazel version and options to ensure this still compiles. Try it as follows: ``` bazel run :clotestbin ``` or ``` bazel run :clotestbin-cc ```
I modified the approach to make it not require elevated privileges for chrooting. Based on existing solutions (in this case, nix-portable). The glue is the only contribution. |
@filmil Thank you for your contribution! This does look very interesting! Also thanks for documenting your approach so well. I've dug through it to get a better understanding of it (raw observations attached below in case they might be useful to others). As far as I can see the following questions are open at the moment:
where to contribute this work?I agree with @facundominguez that this could fit very well into rules_nixpkgs. As far as I understand this addresses issues that are relevant to all rules_nixpkgs users, not just clodl users. In particular, this provides support to build a Nix + Bazel project without a global Nix installation, not just to generate a relocatable and distributable artifact from a (Nix + ) Bazel project. cc @benradf in what form can this be contributed?As you point out this does not provide a set of rules. So, it's not immediately clear how to contribute it to rules_nixpkgs. Perhaps there are ways to turn some of this into rules of some kind. But, before we go there. Maybe a good first step would be to contribute this as an example that is checked on CI. This way it provides documentation on how to use rules_nixpkgs without a global Nix installation right in rules_nixpkgs, and CI verifies that this approach continues to work going forward and is not inadvertently broken. is there anything that should maybe be changed?Two main things stand out to me that I think should change before this can be contributed:
raw observations
|
Thanks for taking the time to look through this. I agree with your findings.
That seems to be the case. And that was the original idea.
There is one at https://github.com/filmil/bazel-nix-example now.
I understand that this is not ideal. It might be possible to bootstrap the approach somehow. The issue is that the For example, adding a self-contained repository implementing this, then using Alex Eagle's trick (used to be at 1, now 404s :/ ) to run a script from it that adapts the "main" workspace correctly.
This is true. It should be removed.
FWIW: |
I reworked the approach to address the issues. I moved most of the setup into a separate repository, started downloading I also minimized the amount of scripting that ends up injected into the top-level repository. I hope this relative opaqueness is not too problematic, since the scripts come from an integrity-checked regular repository anyways. I also added an integration test repository, which is currently "just" a nix-based hello world program, but which compiles and runs as one would expect. There seems to be a bug with It is also not strictly necessary to tack this code to |
Sorry for the delay and thank you for addressing the comments and updating the code!
Nice! That looks very good.
I guess another simple solution could be a similar approach to what buildozer does: Download and cache a release binary on the fly and check it against an expected digest within the Bazel wrapper. That way users that decide to go with this approach could check in their
True. The way this is looking it could be a standalone Bazel module or it could be a part of rules_nixpkgs. I'd be very open to the latter. |
Not sure I understand this bit.
Thinking a bit, I'm not sure we should require people who don't need an ephemeral nix installation to have to the support in. I'm OK if the contribution stays as-is, and would welcome the folks at tweag/rules_nixpkgs#75 to try out the ephemeral nix support at: https://github.com/filmil/bazel_local_nix |
Sorry, that wording was a bit convoluted. The main point was "without having to run an install step at every use-site". IIUC, right now, every user has to run the install step by invoking
The way I was imagining it, it would still be an opt-in choice for users. If they don't set up the |
No, this is not necessary. As soon as someone checks in the results of the installation, it is done. No additional quirks. Binaries are fetched via external repositories as usual. The Maybe I misunderstood your point?
While yes, you could do that, note that it is unnecessary. The ephemeral nix installation in That said, maybe you'd want to take over the maintenance of the rules, in case I slide under a bus or something. In which case feel free to put them wherever you think they fit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a pass over the changes after learning some more about the approach of bazel_local_nix
, and left some questions.
Also, there seems to be some CI failures.
@@ -1,3 +1,4 @@ | |||
build --host_javabase=@local_jdk//:jdk | |||
build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host | |||
build --incompatible_require_linker_input_cc_api=false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have something to do with bazel_local_nix
. I cannot fathom from the documentation of the flag how it relates to the PR. It isn't mentioned in the setup instructions of bazel_local_nix
either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we go too much into the weeds. This PR was not meant as a contribution to clodl
. It was instead meant as an illustration of the approach. I took an arbitrary repo that uses rules_nixpkgs
and converted it into a working repo with an ephemeral nix store with relatively few changes overall.
If you wanted to use the bazel_local_nix
approach, someone else would need to apply it to your repo. If nobody else is interested, it might end up being me, once I get to a point where I wanted to use clodl
imminently. (This may be soon enough, but perhaps not soon enough for folks who want an ephemeral nix bazel build yesterday.)
Now, on to why this flag sits here. I think this flag ended up here because I pegged the bazel version to 5.4.0 using .bazelverson
, for other reasons; but the clodl
default bazel version used is 3.x.x
, which then fights with this version choice. Sadly, bazel is wonky like this, and changing major versions ends up too disruptive.
I suspect that MacOS side would be broken too. But I still think that the correct choice of the interpreter is essential, since the target system may use a different interpreter version. Otherwise clodl
-produced archives would not be portable in the way that clodl
claims them to be.
trap "rm -rf '\\$$tmpdir'" EXIT | ||
unzip -q "\\$$0" -d "\\$$tmpdir" 2> /dev/null || true | ||
"\\$$tmpdir/clodl-top0" | ||
"\\$$tmpdir/ld-linux-x86-64.so.2" --library-path "\\$$tmpdir" "\\$$tmpdir/clodl-top0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this going to work in OSX? Is the current invocation of clodl-top0
problematic for bazel_local_nix
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It certainly doesn't work without this on linux. The issue is that otherwise the interpreter is taken to live in /nix/...
, which is not true on systems with an ephemeral nix installation. But since today you can only build clodl
on systems that do have an ephemeral nix installation, you may never see this issue. (I.e. it works today for clodl
only by accident.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You would probably want to package a nix interpreter in to get things to work reliably everywhere, not just on systems that already have the nix store installed.
But that may complicate the licensing story, so... IANAL, not sure what to tell you.
@@ -0,0 +1 @@ | |||
third_party/bazel_local_nix/tools |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this folder populated by bazel --max_idle_secs=1 run @bazel_local_nix//:install
?
Looks empty to me otherwise, and the installation instructions in bazel_local_nix
don't mention adding a submodule and symlinking it like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the modified approach does not require this at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify.
This PR is the first approach I made here. I have then modified the approach based on the feedback I got on the PR.
I thought I had updated the PR files as well, but apparently I have not. Which made this review more confusing than it should have been. Sorry about that. The PR should not contain .gitmodules
nor any other submodule additions. Y'all noted that it's too onerous, and it is. So I removed it.
The tools
symlink is also suspect.
@@ -0,0 +1,3 @@ | |||
[submodule "third_party/bazel_local_nix"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A submodule is no longer needed with the modified approach.
@@ -66,7 +66,6 @@ binary_closure( | |||
excludes = [ | |||
"^/System/", | |||
"^/usr/lib/", | |||
"ld-linux-x86-64\\.so.*", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ELF interpreter on my machine (/bin/ld-linux-x86-64.ld.so
or whatever) was incompatible with the closure bundle built by clodl
. Running the clodl bundle using it ended with SIGSEGV
.
So I had to include the interpreter binary from the ephemeral nix store into the clodl
-generated closure and instruct clodl
to use it instead of the system ELF interpreter.
I think this is a bug in clodl
that should be fixed. You probably won't see it if you use this on systems that already have nix installed. But ephemeral nix support brings the issue up to the surface, since an ephemeral nix store may not be available at all outside a bazel sandbox, on systems that don't have a system-wide nix
installation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's good to know. It is worth considering how to deal with this ELF interpreters separately.
I'll close this PR then, given that it is not intended to be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me. Thanks for all the advice you all gave in this PR. I think the goal has been achieved, the ephemeral approach is now way better than what I originally had, and anyone who needs it can use it today.
Applies the device introduced at: https://github.com/filmil/bazel-nix-flakes to produce a hermetic nix installation when bazel is started.
Made some changes to the clodl runner and pinned bazel version and options to ensure this still compiles.
Try it as follows:
or