Skip to content
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

Use pkgsStatic instead of static-haskell-nix, bump to libpq 16 and support GSSAPI #3169

Merged
merged 4 commits into from
Jan 26, 2024

Conversation

wolfgangwalther
Copy link
Member

The first commit replaces static-haskell-nix with a build of the static executable via the pkgsStatic overlay of nixpkgs. This supersedes #2332 to resolve #2478.

Based on this, I also tried to cross-compile the static executable to aarch64, but this quickly fails because of NixOS/nixpkgs#36200. Cross-compiling Template Haskell is not easy. Will investigate further.

In the meantime, I also did the following:

  • Update to libpq v16 in the second commit.
  • Build libpq with GSSAPI support in the third commit, which resolves GSSAPI authorization to the database #2815. Had to patch PG a little bit for it to correctly link to the static krb5 libraries, but it builds fine now.

There is room for improvement with the libpq package, which is basically just a stripped down postgresql package right now. It still builds the server, but without systemd, which makes it pull in a lot fewer dependencies - and makes it succeed on cross-platform builds, too. We could still do more here to really only build libpq and nothing else - which would surely be much quicker. Also we currently build it twice (once for the dynamic overlay and once for the static overlay), which can possibly be reduced to one. Furthermore, I suspect that the current way of overriding the "default postgresql version" package, effectively leads to having to rebuild some other dependencies that we use for our devtools, because they depend on that postgresql package for their version of libpq. TLDR: If we create a separate, small derivation just for libpq and pass that only to postgresql-lib (both for dynamic and static), that should be much more efficient.

Copy link
Member

@steve-chavez steve-chavez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's all working fine! 🚀

@wolfgangwalther
Copy link
Member Author

Looks like it's all working fine! 🚀

Yes... took me good while to make it that way :D

Will do some more refactoring before I merge, though.

@wolfgangwalther
Copy link
Member Author

Refactor done, this is in great shape now. Will merge if all pipelines pass.

@wolfgangwalther
Copy link
Member Author

wolfgangwalther commented Jan 25, 2024

@develop7 please have a look at the pipelines in this PR. All the "Text .. (Nix)" pipelines, which should benefit from the prepopulate job, are building the same dependencies again, that the prepopulate job had to build. I think we are missing postgrestPackage as a "tool" in the prepopulate job, because that contains all the haskell dependencies for the dynamic build - which is used in all tests etc.

Edit: At the same time, I think the "CI / Build Linux static (Nix)" job does not need to wait on the prepopulate job. It doesn't benefit from it at all, because it only builds the static parts, which are not cached there anyway.

@develop7
Copy link
Collaborator

@wolfgangwalther thanks for both the heads-up and the suggestion as well! I've noticed the unnecessary rebuilds yesterday and were a wee bit stuck fixing them. Trying it now.

@develop7
Copy link
Collaborator

@wolfgangwalther didn't help. I've filed nix-community/cache-nix-action#27 and about to revert cache-nix-action back to 4.x. Honestly, I didn't quite expect them to break the cache restore part :)

@wolfgangwalther wolfgangwalther merged commit c94aa9c into PostgREST:main Jan 26, 2024
33 checks passed
@wolfgangwalther wolfgangwalther deleted the pkgs-static branch January 26, 2024 16:17
@wolfgangwalther
Copy link
Member Author

After merging, the Cachix / Seed Linux job failed. I didn't know it existed and it only runs on main. Should be fixed in 071a3d4.

@wolfgangwalther
Copy link
Member Author

This MR broke the docker image. The artifact postgrest-docker-x64 is now 380 MB big and includes all kinds of /nix/store paths... will look into that.

@wolfgangwalther
Copy link
Member Author

Before this change, the static executable was ~5 MB. Now it's ~12 MB - very similar to all the other dynamic builds. The docker image containers 370 MB of dependencies.

This all looks like the build is actually dynamically linked. Yet:

file postgrest
postgrest: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

@wolfgangwalther
Copy link
Member Author

The file size could be related to this:

https://github.com/nh2/static-haskell-nix/blob/88f1e2d57e3f4cd6d980eb3d8f99d5e60040ad54/survey/default.nix#L11-L17

TODO Find out why pkgsStatic creates ~3x larger binaries.


The big number of dependencies seem to be added, because all the haskell dependencies are now listed in propagatedBuildInputs for the new derivation. This was not the case with static-haskell-nix before.

@steve-chavez
Copy link
Member

@wolfgangwalther
Copy link
Member Author

Perhaps https://github.com/nlewo/nix2container could help? I've heard it's lighter on the nix store.

I think that would only change the way the docker image is created - but the problem is the input we are giving to this tool. The input has changed, and this is a problem. The main difference, from what I can tell, is:

  • the old way had all the haskell dependencies in buildInputs
  • the new way has all the haskell dependencies in propagatedBuildInputs

This both works fine for actually building the static executable - but when using this derivation somewhere else (docker, here) then all the propagated build inputs are carried with it, and that's what lands in the image.

@wolfgangwalther
Copy link
Member Author

I'm pretty sure that both findings (executable is bigger and closure for docker image is bigger) are directly related:

  • The old executable had some hardcoded /nix/store/... paths only for a openssl-etc derivation.
  • The new executable has more hardcoded /nix/store/... paths: warp, libkrb5, HTTP, libpq, openssl-etc, postgrest itself

Those hardcoded paths are detected as dependencies by nix, and thus copied into the docker image - including many transitive dependencies, which blows up the image size.

Not sure why those new builds are bigger now and contain so much more stuff. But if we fix that, the docker image will immediately become smaller again, too.


propagatedBuildInputs

This had nothing to do with it.

@wolfgangwalther
Copy link
Member Author

I found the additional store paths in the static libraries as well. The old libpq.a did not have a reference to /nix/store/.../etc/postgresql - but the new one has it. This means that the whole haskell toolchain might not even be involved in this, since libpq itself does not depend on any of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

GSSAPI authorization to the database Move away from static-haskell-nix
3 participants