-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
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
[wip] Statically built Nix #56281
[wip] Statically built Nix #56281
Conversation
I tried following some of the examples in your blog post on my NixOS machine, and I get this error message:
|
I'm getting the same error as @ryantm |
Thanks for the heads up. I had forgotten about those extra files needed. The updated binary at For future reference, this is how it was built:
If you don't want to download/extract anything each time, you should run:
Install size is ~11M. |
Works now for me! |
|
||
curl = super.curl.override { | ||
gssSupport = 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.
I would imagine your target audience for this is users who are running and deploying on rootless "enterprise" environments such a RHEL or CentOS. It's worth noting that in many of these setups, kerberos is used extensively for all HTTP and git authentication, so if you could get it working in this static variant it'd probably be worthwhile.
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.
Yeah this is an issue. libkrb5 doesn't have good way to link statically, however:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=439039
kerberos heimdal might support it though.
pkgs/top-level/static.nix
Outdated
}; | ||
|
||
nix = super.nix.overrideAttrs (_: { | ||
NIX_LDFLAGS = "-lssl -lbrotlicommon -lssh2 -lz -lnghttp2 -lcrypto"; |
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 think the right way to do this would be patching the pkg-config files to include these libraries in the Requires.private
section, as is done in:
$ nix-build -A brotli.dev && cat result-dev/lib/pkgconfig/libbrotlidec.pc
prefix=/nix/store/7i965pyrkqph3gwpfzswz35c6a1j1v5h-brotli-1.0.7
exec_prefix=/nix/store/7i965pyrkqph3gwpfzswz35c6a1j1v5h-brotli-1.0.7
libdir=/nix/store/iahrxydkznvf6z0q0hp0cp9nhrq1pkys-brotli-1.0.7-lib/lib
includedir=/nix/store/1qcykjlmxvvzgvvnyzsz7yii794m5rjv-brotli-1.0.7-dev/include
Name: libbrotlidec
URL: https://github.com/google/brotli
Description: Brotli decoder library
Version: 1.0.7
Libs: -L${libdir} -lbrotlidec
Requires.private: libbrotlicommon >= 1.0.2
Cflags: -I${includedir}
I haven't looked at this specific case too closely, but in general invoking pkgconfig --static <args>
will also include the Requires.private
sections for transitive link dependencies that are not needed in the dynamic variant.
For example, the libssl.pc
has a Requires.private
directive on libcrypto
, which means you don't need to include -lcrypto
on the linkline manually if you use pkgconfig --static ssl
.
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 think the issue was that all of these need to be propagated in static. static linking requires knowing where all of the needed libraries are.
In principle this looks fine to me, but it clutters Nixpkgs with numerous patches and special-case attributes that are going to be a pain in the ass to maintain. Who is going to be responsible for maintaining those? |
One possible part of the solution would be for @matthewbauer to add himself as a maintainer of these packages. |
name = "boehm-gc-7.6.0-sys_select.patch"; | ||
url = "https://gitweb.gentoo.org/proj/musl.git/plain/dev-libs/boehm-gc/files/boehm-gc-7.6.0-sys_select.patch?id=85b6a600996bdd71162b357e9ba93d8559342432"; | ||
sha256 = "1gydwlklvci30f5dpp5ccw2p2qpph5y41r55wx9idamjlq66fbb3"; | ||
}) ] ++ |
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 still needed? It was explicitly removed in a recent-ish PR with the idea that this didn't hurt but didn't help, IIRC. Might be good to check.
@@ -44,6 +44,7 @@ rec { | |||
then throw "Cannot build fully static binaries on Darwin/macOS" | |||
else stdenv'.mkDerivation (args // { | |||
NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -static"; | |||
separateDebugInfo = 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.
This doesn't seem right, why must this be disabled for static adapter?
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.
Yeah maybe not... I was getting an issue that I thought was due to this but it might have been unrelated.
Yeah i can do that. Lots of these are because of ad hoc configure scripts (no autotools, cmake, or meson). Other times static libs are not being installed correctly into prefix. All of these can probably be corrected with upstream patches though. |
@@ -13,6 +13,10 @@ stdenv.mkDerivation rec { | |||
|
|||
nativeBuildInputs = [ cmake ]; | |||
|
|||
postPatch = stdenv.lib.optionalString stdenv.hostPlatform.isMusl '' | |||
sed -i "24ireturn()" cmake/AwsTestHarness.cmake |
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.
This is fragile. In general, a better approach is to generate a patch with diff -U1
.
This breaks non-musl configure with:
CMake Error at tests/CMakeLists.txt:260 (target_compile_options):
Cannot specify compile options for target "aws-c-common-tests" which is not
built by this project.
Why does it work with musl?
You could try -DBUILD_TESTING=OFF
instead.
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.
Yeah it’s super broken. BUILD_TESTING doesn’t work at least
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 see, BUILD_TESTING
is not actually implemented. You could patch out add_subdirectory(tests)
in the main CMakeLists.txt
then.
This looks really cool, it would help people (me) run nix on ARM with limited memory / disk space (by downloading a static nix and loading some external disk space and setting the nix store inside there).
|
I don't think that will work - it will build a static toolchain and then cross compile with it. Ideally, you would pass these args to Nixpkgs:
But I don't think crossOverlays is exposed yet. |
Thanks for this PR @matthewbauer ! After 220 derivations & a couple of days on my small ARM board, I've got a statically compiled armv7l nix! I did have to edit the bash derivation though: diff --git a/pkgs/shells/bash/4.4.nix b/pkgs/shells/bash/4.4.nix
index e5e33c7..a61801a 100644
--- a/pkgs/shells/bash/4.4.nix
+++ b/pkgs/shells/bash/4.4.nix
@@ -28,7 +28,7 @@ stdenv.mkDerivation rec {
sha256 = "1jyz6snd63xjn6skk7za6psgidsd53k05cr3lksqybi0q6936syq";
};
- hardeningDisable = [ "format" ];
+ hardeningDisable = [ "format" ] ++ optional (stdenv.hostPlatform.libc == "musl") "pie";
outputs = [ "out" "dev" "man" "doc" "info" ]; now I can run it but nix seems to ignore the $ zcat /proc/config.gz | egrep 'USER_NS|SECCOMP'
CONFIG_USER_NS=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
$ sudo mkdir -p /nix/store
$ ./nix run --store ~/my-nix nixpkgs.nix nixpkgs.bashInteractive
error: getting status of '/nix/store/3azwf31ib816jq403qrymzw02hrlj5fk-nix-2.2-armv7l-unknown-linux-musleabihf': No such file or directory
$ ./nix show-config | grep '/nix/store'
build-hook = /nix/store/3azwf31ib816jq403qrymzw02hrlj5fk-nix-2.2-armv7l-unknown-linux-musleabihf/libexec/nix/build-remote
sandbox-paths = /bin/sh=/nix/store/l31h4is1irdw1zfld2qf7l0l4w98ylrh-busybox-1.30.1-armv7l-unknown-linux-musleabihf/bin/busybox i'll keep poking around, thought i'd post the built binary here if it helps anyone |
You need to provide a Nix channel / file for it to use. So most likely you need something like this:
Both the NIX_DATA_DIR is needed to pick up some "booter" expressions in corepkgs. You can use the native Nix for this to avoid rebuliding. |
@matthewbauer that worked! i'm currently building with a static nix in a custom nix-store 🎉 !
the files in my so, the static nix is fully portable except that it references those two paths. EDIT: diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 1c2c0871..34a08756 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -64,7 +64,7 @@ Settings::Settings()
}
#if defined(__linux__) && defined(SANDBOX_SHELL)
- sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
+ sandboxPaths = tokenizeString<StringSet>("/bin/sh=" + getEnv("NIX_SANDBOX_SHELL", SANDBOX_SHELL));
#endif
allowedImpureHostPrefixes = tokenizeString<StringSet>(DEFAULT_ALLOWED_IMPURE_PREFIXES); and then using |
1857278
to
4fb2125
Compare
8241f2d
to
78bd45b
Compare
ppc64le and ppc64 are different targets in the configure script. We can’t use the same one. TODO: canonicalize similar ones based on qemu’s configure script.
@@ -295,6 +295,10 @@ stdenv.mkDerivation { | |||
hardening_unsupported_flags+=" stackprotector fortify" | |||
'' | |||
|
|||
+ optionalString targetPlatform.isx86_32 '' | |||
hardening_unsupported_flags+=" stackprotector" |
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.
This is temporary I assume?
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.
Maybe... binutils and musl seemed to get stuck. I don't think anyone supports i686 very well any more.
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 combination or in isolation? with targetPlatform.isx86_32 && targetPlatform.isMusl
I'd be more comfortable with that.
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.
see #62817
I have a repo that holds some scripts to build static nix here: https://github.com/matthewbauer/static-nix It makes it easy to cross build Nix to a few architectures like:
|
thanks @Ericson2314
This pull request has been mentioned on Nix community. There might be relevant details there: https://discourse.nixos.org/t/crosscompilation-to-musl32-problems/3110/3 |
I've polished a few commits from here and pushed to master to fix builds of bohemgc, brotli, and busybox. What's left seems to be: curl, boost and openssl. |
Fixed also curl, boost, opeensl and libsodium. Last one standing before nix is nghttp2:
Any ideas? EDIT: ah, probably need to build zlib with shared libs as well. |
Fixed also zlib and nghttp2. |
It gets all the way to nix now:
EDIT: will continue after lunch, seems like boost copying needs fixes for static compilatin. |
I think we should close this one as it has conflicts. I haven't checked cross compilation (certainly some patches from this PR is missing), but at least Nix compiles statically in #70024 |
Is there a way to get the static binary without flake ? |
It is built by CI, so it just needs that some adds an artifact. |
That's so cool. A lot of guides or tutorials could use it instead for a very light installation or demo. |
Off topic: @domenkozar why is multi user install becoming the default ? |
See NixOS/nix#4181 for discussion |
@fzakaria You can now download static nix via Hydra at: https://hydra.nixos.org/job/nix/master/buildStatic.x86_64-linux/latest/download/2/nix We don't have any official release on nixos.org yet though. |
The link above is dead now, it takes you to the nix docs.
To view all static builds you can start at https://hydra.nixos.org/jobset/nix/maintenance-2.9#tabs-jobs and search for "buildStatic" |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/where-can-i-get-a-statically-built-nix/34253/3 |
Motivation for this change
This makes it possible to build Nix statically through pkgsStatic.nix. Needs a couple of patches to nix but otherwise works smoothly.
If you'd like to try it, you can just check out this branch and run:
and wait a little bit. More targets are available here:
https://github.com/matthewbauer/static-nix
Alternatively, you can use my prebuilt binary at https://matthewbauer.us/nix. It is built for x86_64-linux and can be used on any system like this:
For instance, on a linux system without nix installed, you can do this:
There are many uses cases where nix is unavailable and the above command can be extremely useful. It's a little slow still, but can be sped up by reusing the same
--store
value (such as $HOME/.cache/nix/store). Here is the time: