Github action fails to find GLIBC while running nix-provisioned `rsync`

Ideal outcome of me posting here is someone who have seen an issue like this pointing me to the right direction for debugging and maybe refactoring my Github action and/or the way I use Nix to create a deterministic environment for the project.

Here is the issue:

The test in question uses rsync under the hood from rust code. It works on my machine:tm: with the following flake:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    goo.url = "github:doma-engineering/goo-1.14?ref=v1.14";
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    passveil.url = "github:doma-engineering/passveil";
  };

  outputs =
    {
      nixpkgs,
      goo,
      fenix,
      passveil,
      ...
    }:
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      npkgs = pkgs.nodePackages;
      rust_complete = (
        fenix.outputs.packages.x86_64-linux.complete.withComponents [
          "cargo"
          "clippy"
          "rustc"
          "rustfmt"
          "rust-src"
          "rust-analyzer"
        ]
      );
    in
    {
      defaultPackage.x86_64-linux = pkgs.hello;

      devShell.x86_64-linux = pkgs.mkShell {
        nativeBuildInputs = [
          pkgs.libsodium
          pkgs.pkg-config
          pkgs.openssl.dev
          # Github actions are failing because of glibc
          pkgs.glibc
        ];
        buildInputs = [
          rust_complete
          pkgs.sqlx-cli

          pkgs.erlang_24
          goo.defaultPackage.x86_64-linux
          pkgs.elixir_ls

          pkgs.inotify-tools
          pkgs.postgresql
          pkgs.openssl
          pkgs.openssl.dev
          # Helpers
          pkgs.httpie
          pkgs.jq
          pkgs.yq
          pkgs.dig

          # Stuff that has to be externally configured
          pkgs.gnupg
          pkgs.darcs
          pkgs.unzip
          npkgs.yarn
          passveil.packages.x86_64-linux.passveil

          pkgs.nodejs_22
          pkgs.pnpm
          npkgs.typescript

          pkgs.sqlite
        ];
        LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ pkgs.openssl ];
        LOCALE_ARCHIVE = "${pkgs.glibcLocales}/lib/locale/locale-archive";
      };
    };
}

The relevant part of the Github action, which fails, is:

      - name: Rootrunner and Bakery Tests
        working-directory: /opt/zerohr/devs/rootrunner
        run: |
          nix develop --command bash -c "DATABASE_URL='sqlite:/opt/zerohr/db/rootrunner_ci.db' sqlx migrate run && DATABASE_URL='sqlite:/opt/zerohr/db/rootrunner_ci.db' cargo test --features ci --workspace"

See full workflow configuration at the end of this post.

Here is the error that it causes:

 running 5 tests
test output::tests::test_get_gen_multiplayer ... ok
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by /nix/store/jv2p6cmx23ihj5y4r98wnn2nmv4qhfh5-openssl-3.0.14/lib/libcrypto.so.3)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by /nix/store/jv2p6cmx23ihj5y4r98wnn2nmv4qhfh5-openssl-3.0.14/lib/libcrypto.so.3)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by /nix/store/jv2p6cmx23ihj5y4r98wnn2nmv4qhfh5-openssl-3.0.14/lib/libcrypto.so.3)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libdl.so.2)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)
rsync: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /nix/store/m71p7f0nymb19yn1dascklyya2i96jfw-glibc-2.39-52/lib/libpthread.so.0)

Here is some debug information I have collected in said action:

Check Ubuntu version

0s
Run echo "=== Ubuntu Version ==="
=== Ubuntu Version ===
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.5 LTS
Release:	22.04
Codename:	jammy
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

Check glibc versions

Run echo "=== glibc Version ==="
=== glibc Version ===
ldd (Ubuntu GLIBC 2.35-0ubuntu3.8) 2.35
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

=== libc.so.6 Version ===
GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.8) stable release version 2.35.
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 11.4.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

=== GLIBC Versions in libc.so.6 ===
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.29
GLIBC_2.30
GLIBC_2.31
GLIBC_2.32
GLIBC_2.33
GLIBC_2.34
GLIBC_2.35
GLIBC_PRIVATE

Check environment variables

Run echo "=== LD_LIBRARY_PATH ==="
=== LD_LIBRARY_PATH ===


=== All Environment Variables ===
SELENIUM_JAR_PATH=/usr/share/java/selenium-server.jar
CONDA=/usr/share/miniconda
GITHUB_WORKSPACE=/home/runner/work/zerohr/zerohr
JAVA_HOME_11_X64=/usr/lib/jvm/temurin-11-jdk-amd64
GITHUB_PATH=/home/runner/work/_temp/_runner_file_commands/add_path_8dcf188b-702a-4cf8-94b8-0ac04e13892b
GITHUB_ACTION=__run_4
JAVA_HOME=/usr/lib/jvm/temurin-11-jdk-amd64
GITHUB_RUN_NUMBER=32
RUNNER_NAME=GitHub Actions 17
GRADLE_HOME=/usr/share/gradle-8.11.1
GITHUB_REPOSITORY_OWNER_ID=88152561
ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE=/opt/actionarchivecache
XDG_CONFIG_HOME=/home/runner/.config
DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
ANT_HOME=/usr/share/ant
JAVA_HOME_8_X64=/usr/lib/jvm/temurin-8-jdk-amd64
GITHUB_TRIGGERING_ACTOR=cognivore
GITHUB_REF_TYPE=branch
HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS=3650
ANDROID_NDK=/usr/local/lib/android/sdk/ndk/27.2.12479018
BOOTSTRAP_HASKELL_NONINTERACTIVE=1
***
PIPX_BIN_DIR=/opt/pipx_bin
STATS_TRP=true
GITHUB_REPOSITORY_ID=736711150
DEPLOYMENT_BASEPATH=/opt/runner
GITHUB_ACTIONS=true
STATS_VMD=true
ANDROID_NDK_LATEST_HOME=/usr/local/lib/android/sdk/ndk/27.2.12479018
SYSTEMD_EXEC_PID=477
GITHUB_SHA=f1186b9ab31d408590e3a22a33836a34a0415cb3
GITHUB_WORKFLOW_REF=doma-engineering/zerohr/.github/workflows/rootrunner-ci.yml@refs/heads/cognivore/rust-rewrite
POWERSHELL_DISTRIBUTION_CHANNEL=GitHub-Actions-ubuntu22
RUNNER_ENVIRONMENT=github-hosted
STATS_EXTP=https://provjobdprod.z13.web.core.windows.net/settings/provjobdsettings-latest/provjobd.data
DOTNET_MULTILEVEL_LOOKUP=0
STATS_TIS=mining
GITHUB_REF=refs/heads/cognivore/rust-rewrite
RUNNER_OS=Linux
GITHUB_REF_PROTECTED=false
HOME=/home/runner
GITHUB_API_URL=https://api.github.com
LANG=C.UTF-8
RUNNER_TRACKING_ID=github_a43d5199-da2e-4f57-bf87-6d9164f9f376
RUNNER_ARCH=X64
GOROOT_1_21_X64=/opt/hostedtoolcache/go/1.21.13/x64
RUNNER_TEMP=/home/runner/work/_temp
GITHUB_STATE=/home/runner/work/_temp/_runner_file_commands/save_state_8dcf188b-702a-4cf8-94b8-0ac04e13892b
STATS_PIP=false
EDGEWEBDRIVER=/usr/local/share/edge_driver
JAVA_HOME_21_X64=/usr/lib/jvm/temurin-21-jdk-amd64
GITHUB_ENV=/home/runner/work/_temp/_runner_file_commands/set_env_8dcf188b-702a-4cf8-94b8-0ac04e13892b
GITHUB_EVENT_PATH=/home/runner/work/_temp/_github_workflow/event.json
INVOCATION_ID=1f92cc5a147647bdb4889d400634c1fb
STATS_D=false
GITHUB_EVENT_NAME=push
GITHUB_RUN_ID=12101371536
JAVA_HOME_17_X64=/usr/lib/jvm/temurin-17-jdk-amd64
ANDROID_NDK_HOME=/usr/local/lib/android/sdk/ndk/27.2.12479018
GITHUB_STEP_SUMMARY=/home/runner/work/_temp/_runner_file_commands/step_summary_8dcf188b-702a-4cf8-94b8-0ac04e13892b
HOMEBREW_NO_AUTO_UPDATE=1
GITHUB_ACTOR=cognivore
NVM_DIR=/home/runner/.nvm
SGX_AESM_ADDR=1
GITHUB_RUN_ATTEMPT=1
STATS_RDCL=true
ANDROID_HOME=/usr/local/lib/android/sdk
GITHUB_GRAPHQL_URL=https://api.github.com/graphql
RUNNER_USER=runner
ACCEPT_EULA=Y
STATS_UE=true
USER=runner
GITHUB_SERVER_URL=https://github.com
STATS_V3PS=true
PIPX_HOME=/opt/pipx
GECKOWEBDRIVER=/usr/local/share/gecko_driver
STATS_EXT=true
CHROMEWEBDRIVER=/usr/local/share/chromedriver-linux64
SHLVL=1
ANDROID_SDK_ROOT=/usr/local/lib/android/sdk
VCPKG_INSTALLATION_ROOT=/usr/local/share/vcpkg
GITHUB_ACTOR_ID=66186054
RUNNER_TOOL_CACHE=/opt/hostedtoolcache
ImageVersion=20241124.1.0
DOTNET_NOLOGO=1
GOROOT_1_23_X64=/opt/hostedtoolcache/go/1.23.3/x64
GITHUB_WORKFLOW_SHA=f1186b9ab31d408590e3a22a33836a34a0415cb3
GITHUB_REF_NAME=cognivore/rust-rewrite
GITHUB_JOB=rootrunner-cargo-test
XDG_RUNTIME_DIR=/run/user/1001
AZURE_EXTENSION_DIR=/opt/az/azcliextensions
PERFLOG_LOCATION_SETTING=RUNNER_PERFLOG
STATS_VMFE=true
GITHUB_REPOSITORY=doma-engineering/zerohr
CHROME_BIN=/usr/bin/google-chrome
ANDROID_NDK_ROOT=/usr/local/lib/android/sdk/ndk/27.2.12479018
GOROOT_1_22_X64=/opt/hostedtoolcache/go/1.22.9/x64
GITHUB_RETENTION_DAYS=90
JOURNAL_STREAM=8:18193
RUNNER_WORKSPACE=/home/runner/work/zerohr
LEIN_HOME=/usr/local/lib/lein
LEIN_JAR=/usr/local/lib/lein/self-installs/leiningen-2.11.2-standalone.jar
GITHUB_ACTION_REPOSITORY=
PATH=/snap/bin:/home/runner/.local/bin:/opt/pipx_bin:/home/runner/.cargo/bin:/home/runner/.config/composer/vendor/bin:/usr/local/.ghcup/bin:/home/runner/.dotnet/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
RUNNER_PERFLOG=/home/runner/perflog
GITHUB_BASE_REF=
GHCUP_INSTALL_BASE_PREFIX=/usr/local
CI=true
SWIFT_PATH=/usr/share/swift/usr/bin
ImageOS=ubuntu22
STATS_D_D=false
GITHUB_REPOSITORY_OWNER=doma-engineering
GITHUB_HEAD_REF=
GITHUB_ACTION_REF=
STATS_D_TC=true
GITHUB_WORKFLOW=RootRunner CI
DEBIAN_FRONTEND=noninteractive
GITHUB_OUTPUT=/home/runner/work/_temp/_runner_file_commands/set_output_8dcf188b-702a-4cf8-94b8-0ac04e13892b
AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache
_=/usr/bin/env

List installed libc packages in Ubuntu


Run echo "=== Installed libc Packages ==="
=== Installed libc Packages ===
ii  libc6:amd64                                                 2.35-0ubuntu3.8                                                amd64        GNU C Library: Shared libraries
ii  libc6-dev:amd64                                             2.35-0ubuntu3.8                                                amd64        GNU C Library: Development Libraries and Header Files
ii  libc6-i386                                                  2.35-0ubuntu3.8                                                amd64        GNU C Library: 32-bit shared libraries for AMD64

Offending Github action

name: RootRunner CI

on:
  push:
    branches:
      - "cognivore/rust-rewrite"
    paths:
      - 'devs/rootrunner/**'
      - '.github/workflows/rootrunner-ci.yml'

jobs:
  rootrunner-cargo-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cp -r /home/runner/work/zerohr/zerohr /opt/zerohr

      - name: Check Ubuntu Version
        run: |
          echo "=== Ubuntu Version ==="
          lsb_release -a || true
          cat /etc/os-release

      - name: Check glibc Version
        run: |
          echo "=== glibc Version ==="
          ldd --version || true
          echo
          echo "=== libc.so.6 Version ==="
          /lib/x86_64-linux-gnu/libc.so.6 || true
          echo
          echo "=== GLIBC Versions in libc.so.6 ==="
          strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC_

      - name: Display Environment Variables
        run: |
          echo "=== LD_LIBRARY_PATH ==="
          echo "$LD_LIBRARY_PATH"
          echo
          echo "=== All Environment Variables ==="
          env

      - name: List Installed libc Packages
        run: |
          echo "=== Installed libc Packages ==="
          dpkg -l | grep libc6

      - name: Change working directory
        run: cd /opt/zerohr

      - name: Install Nix
        uses: DeterminateSystems/nix-installer-action@v4

      - name: Enable Nix Flakes
        run: |
          mkdir -p ~/.config/nix
          echo "experimental-features = nix-command flakes" | sudo tee -a /etc/nix/nix.conf

      - name: Create database file
        run: |
          export DATABASE_FILE="/opt/zerohr/db/rootrunner_ci.db"
          touch "$DATABASE_FILE"

      - name: Set directory permissions
        run: |
          sudo chown -R $USER:$USER /opt/zerohr
          chmod -R 755 /opt/zerohr

      - name: Rootrunner and Bakery Tests
        working-directory: /opt/zerohr/devs/rootrunner
        run: |
          nix develop --command bash -c "DATABASE_URL='sqlite:/opt/zerohr/db/rootrunner_ci.db' sqlx migrate run && DATABASE_URL='sqlite:/opt/zerohr/db/rootrunner_ci.db' cargo test --features ci --workspace"

This is why you should never ever set LD_LIBRARY_PATH. I think we should remove that capability from glibc in nixpkgs, purely to further discourage its use.

1 Like

I wish, though even some packages in nixpkgs do end up setting it unfortunately.

But how to make other dynamically linked libraries discoverable by stuff that is getting built inside the environments?

I heard that nativeBuildInputs should help, but I didn’t dig into how this attribute gets evaluated.

What should I look at to make CI work though? I don’t see how making my rust binaries be built with nix help with this particular issue, since Exec will still do normal PATH resolution, find the same rsync binary and crash the same way.

By configuring your linker appropriately. LD_LIBRARY_PATH isn’t even for build-time. It’s only used to detect libraries at runtime.

Perhaps you should dig into how it works: Nixpkgs Reference Manual

Remove LD_LIBRARY_PATH. The reason your rsync breaks is because Ubuntu’s dynamic library loader also reacts to LD_LIBRARY_PATH and tries to load your OpenSSL, which is not built to be compatible with your Ubuntu system’s version of glibc.

3 Likes

Maybe introducing something like NIX_LD_LIBRARY_PATH and modifying glibc accordingly would keep the functionality and protect from the host non-NixOS Linux at the same time?

1 Like

I do not wish to compartmentalize LD_LIBRARY_PATH, I wish to eliminate it.

2 Likes

Thank you for the response, I appreciate it.

I understand what LD_LIBRARY_PATH does and I don’t know another way to make my project build because openssl us a system dependency which I want to be discoverable by the binaries I run.

I shall investigate nativeBuildInputs, I assume that will ensure correct operation.

The main problem is using a mkShell environment but expecting packages to “find each other” within it. That might work for binaries if you use execvp or whatever but won’t work for libraries. The answer for libraries is to correctly package the software that needs to find its libraries, instead of using the hack of LD_LIBRARY_PATH.

I recommend reading Packaging existing software with Nix — nix.dev documentation and possibly Nixpkgs Reference Manual

2 Likes

I am reading it now.

I actually understand your answer, thank you.

Update: I’ve carefully read through the tutorial, this is something I’m comfortable with doing, and have done for software that I don’t actively develop.

However, in case of something I commit like 5 times a day, sometimes adding new dependencies, repackaging it feels like a thing that would objectively slow me down.

Let me see if I understand: you are suggesting I dynamically link rust with nix openssl, this way environment variable based look-ups are unneeded and the variables won’t get in the way of nix rsync dynamically linked against nix glibc.

If I understand correctly, let me succinctly restate my concern: it seems like I will then need to maintain Cargo.toml and expression that builds my software with nix, which will hinder development experience.

Nothing stops you from using a mkShell environment with the properly-packaged binary that can find its own libraries. All I’m saying is don’t put libraries in said mkShell env and expect binaries to use those library packages.

I don’t know what you mean by “maintain Cargo.toml with nix”, the Cargo.toml is something you write indepently of nix code.

At a risk of sounding even denser than I am — if I’m using mkShell on my dev env, I will have the same issue — Rust binaries compiled with cargo won’t be linked against nix-provided OpenSSL because shell is not enough for stuff to get linked against each other.

I’m refactoring my expression tonight to build Rust software, but I think it’s doomed for failure.

Okay, I’ll hijack this thread with more helpful links, which are also specific to the problem of packaging Rust stuff.

So it turns out there is something called crane, which works by parsing Cargo.lock. They then use cargo under the hood to make a derivation.

The only issue is that you would have to provision your network-dependency in your src/ if you want simple pure builds. “Pure”? I hear you ask. “But how is it possible to then install stuff from crates.rs”? Again, I can’t point to the source code, but it seems like the author of the project has all the known stuff cached on some cachix cache and when you run “nix build”, stuff that is not already cached by rustPlatform.

By the way, an example of using rustPlatform in a way very analagous to using crane, can be found here.

I’m still decidedly skeptical that any of this will help with the actual issue (nix develop will still fail the exact same way it did for exactly the same reason it did, no matter if I package my software “properly” or not becayse defaultPackage... has no impact on devShell...), so I’m not sure why am I wasting time on this, but to be entitled to ask a follow-up question, I guess I shall carry on.

You have pkgs.openssl.dev in nativeBuildInputs, it should be in buildInputs (and drop the LD_LIBRARY_PATH as others have said), otherwise the right environment flags for a Rust/C/… compiler to pick up the dependency will not be set. We build Rust applications without issues in a dev shell with OpenSSL.

Edit: I see that you also have it in buildInputs, maybe you can post the build error you get with having it just in buildInputs and with LD_LIBRARY_PATH removed?

1 Like

Hey, Daniel! I appreciate your response.

The error without LD_LIBRARY_PATH happens at runtime.

Current flake.nix:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, fenix, ... }:
  let
    pkgs = import nixpkgs { system = "x86_64-linux"; };
    rust_complete = fenix.outputs.packages.x86_64-linux.complete.withComponents [
      "cargo" "clippy" "rustc" "rustfmt" "rust-src"
    ];
  in
  {
    defaultPackage.x86_64-linux = pkgs.stdenv.mkDerivation {
      pname = "rootrunner";
      version = "0.1.0";
      src = ./.;
      buildInputs = [ rust_complete pkgs.openssl pkgs.pkg-config ];
      nativeBuildInputs = [ pkgs.sqlx-cli ];

      installPhase = ''
        runHook preInstall
        export CARGO_HOME="$TMPDIR/cargo-home"
        export CARGO_TARGET_DIR="$TMPDIR/cargo-target"
        mkdir -p $CARGO_HOME $CARGO_TARGET_DIR

        mkdir -p $out/bin
        cargo build --release --workspace
        cp target/release/rootrunner-exe $out/bin/
        runHook postInstall
      '';
    };

    devShell.x86_64-linux = pkgs.mkShell {
      buildInputs = [
        rust_complete
        pkgs.openssl.dev
        pkgs.openssl
        pkgs.pkg-config
        pkgs.sqlx-cli
        pkgs.postgresql
        pkgs.sqlite
        pkgs.nodejs_22
        pkgs.pnpm
      ];
      nativeBuildInputs = [ pkgs.pkg-config pkgs.openssl.dev pkgs.openssl ];
    };
  };
}

BTW, if you understand suggestions in the thread to properly package my software and how will it help with nix develop not working, and you have the energy to explain it to me like I’m five, I’d appreciate it a lot!

The situation is that fenix fucking sucks and doesn’t add libssl to the output’s RPATH. Using cargo from rustPlatform in nixpkgs or Oxalica’s rust-overlay would work.

1 Like

Gothca! Will learn rustPlatform, thank you!

I didn’t manage to make sense of rustPlatform quickly enough, so I decided to refactor everything I have in the codebase to use stable rust (cringe).

I don’t know how to use rust nightly yet, but, here’s flake.nix to quote Valteri Bottas, “to whom it may concern”:

{
  description = "Flake for building rootrunner with standard nixpkgs Rust and OpenSSL support";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils = {
      url = "github:numtide/flake-utils";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, flake-utils, ... }:
    flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
      let
        pkgs = import nixpkgs { inherit system; };
      in
      {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            rustc
            cargo
            rustfmt
            clippy
            rust-analyzer
            pkg-config
            sqlx-cli
            postgresql
            sqlite
            nodejs
            pnpm
            zip
            unzip
            rsync
            openssl.dev
            openssl
          ];
        };

        devShell = self.devShells.${system}.default;
      }
    );
}

P.S.
Regarding crane and “proper packaging” – a problem is that the codebase I’m working with is quite large. I used crane successfully to package smaller tools and it kind of just works.

P.P.S.
Thank you everyone for all the help!

Here is a version which bundles rust-analyzer in a way that a dirty VSCodium / VSCode or (god-forbid) Cursor can find and use it with direnv plugin:

{
  description = "Flake for building rootrunner with overlaid nixpkgs Rust and OpenSSL support";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils = {
      url = "github:numtide/flake-utils";
    };
    rust_overlay = {
      url = "github:oxalica/rust-overlay";
    };
  };

  outputs = { self, nixpkgs, flake-utils, rust_overlay, ... }:
    flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [ rust_overlay.overlays.default ];
        };
        rust = pkgs.rust-bin.stable.latest.default.override {
          extensions = [ "rust-src" "rustfmt" "clippy" "rust-analyzer" ];
        };
      in
      {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            rust

            pkg-config
            sqlx-cli
            postgresql
            sqlite
            nodejs
            pnpm
            zip
            unzip
            rsync
            openssl.dev
            openssl

            chromedriver
            chromium
            xvfb-run

            typescript
            nodePackages.typescript
          ];
        };

        devShell = self.devShells.${system}.default;
      }
    );
}