Issues Running Self-Contained .NET 8 Binary in Nix Flakes (Single vs. Multi-File Deployment)

I’m trying to package and run a self-contained .NET 8 application using Nix flakes. I tried both single-file and multi-file deployments. The idea is to build a flake that will include my binary. I’m currently testing with a simple project (here is the link: GitHub - nasdvoya/test: test), but later on, I will use the “real” one. The only condition is that I can’t share the source code, so I believe buildDotnetModule is not an option.

Is it simply not possible to build a derivation for precompiled .NET binaries due to the way dynamic linking works? Or am I missing something obvious? I’ve tried pretty much every possible variation.

Single-file deployment:

dotnet publish simple.csproj --configuration Release --output ./great \
  --self-contained True --runtime linux-x64 \
  --verbosity minimal \
  /property:PublishSingleFile=True \
  /property:IncludeNativeLibrariesForSelfExtract=True \
  /property:AssemblyName=simple

Multi-file deployment:

dotnet publish --configuration Release --output ./great \
  --self-contained true --runtime linux-x64

Case 1: Single-file Deployment Flake

{
  description = "A simple flake example for Simple";

  inputs = { nixpkgs.url = "github:NixOS/nixpkgs"; };

  outputs = { self, nixpkgs }: {
    packages.x86_64-linux = let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      dynamicLinker = pkgs.stdenv.cc.bintools.dynamicLinker;
      rpath = pkgs.lib.strings.makeLibraryPath [
        pkgs.stdenv.cc.cc pkgs.icu pkgs.openssl
        pkgs.zlib pkgs.libkrb5 pkgs.libunwind pkgs.libuuid
        pkgs.icu pkgs.lttng-ust pkgs.lttng-ust_2_12
      ];
    in {
      simple = pkgs.stdenv.mkDerivation {
        pname = "simple";
        version = "1.0";

        buildInputs = [
          pkgs.dotnet-sdk_8 pkgs.openssl pkgs.zlib pkgs.icu
          pkgs.gcc.libc pkgs.libkrb5 pkgs.stdenv.cc.cc.lib
          pkgs.lttng-ust pkgs.lttng-ust_2_12
        ];

        src = pkgs.fetchurl {
          url = "https://github.com/nasdvoya/test/releases/download/v1.9.9/simple";
          sha256 = "0m0bzwmy0r4pmz9w4125gswr10ijm4qlgw3w691ajlp4i4x529vp";
        };

        unpackPhase = "true"; # Skip unpacking
        installPhase = ''
          mkdir -p $out/bin
          cp $src $out/bin/simple
          chmod +x $out/bin/simple
        '';

        postFixup = ''
          echo "Patching binary: $out/bin/simple"
          patchelf --set-interpreter "${dynamicLinker}" \
                   --set-rpath '$ORIGIN:${rpath}' $out/bin/simple
        '';

        meta = with pkgs.lib; {
          description = "Simple binary built from release";
          license = licenses.mit;
          platforms = platforms.linux;
        };
      };
    };

    defaultPackage.x86_64-linux = self.packages.x86_64-linux.simple;
    defaultApp = { type = "app"; program = "${self.packages.x86_64-linux.simple}/bin/simple"; };
  };
}

Running it produces the following output:

nix build
ldd ./result/bin/simple

./result/bin/simple
Failure processing application bundle; possible file corruption.
Arithmetic overflow while reading bundle.
A fatal error occurred while processing application bundle

Case 2: Multi-file Deployment Flake

{
  description = "A simple flake example for Simple";

  inputs = { nixpkgs.url = "github:NixOS/nixpkgs"; };

  outputs = { self, nixpkgs }: {
    packages.x86_64-linux = let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      dynamicLinker = pkgs.stdenv.cc.bintools.dynamicLinker;
      rpath = pkgs.lib.strings.makeLibraryPath [
        pkgs.stdenv.cc.cc pkgs.icu pkgs.openssl
        pkgs.zlib pkgs.libkrb5 pkgs.libunwind pkgs.libuuid
        pkgs.icu pkgs.lttng-ust pkgs.lttng-ust_2_12
      ];
    in {
      simple = pkgs.stdenv.mkDerivation {
        pname = "simple";
        version = "1.0";

        buildInputs = [
          pkgs.dotnet-sdk_8 pkgs.openssl pkgs.zlib pkgs.icu
          pkgs.gcc.libc pkgs.libkrb5 pkgs.stdenv.cc.cc.lib
          pkgs.lttng-ust pkgs.lttng-ust_2_12
        ];

        src = pkgs.fetchurl {
          url = "https://github.com/nasdvoya/test/releases/download/v1.9.9/simple.tar.gz";
          sha256 = "0hrm0gxxzagwmgkvyp4y6qhjplm6rlpyzbhx2gs6zf0f6hnra0l6";
        };

        unpackPhase = ''tar -xzf $src'';

        installPhase = ''
          mkdir -p $out/bin
          cp -r * $out/bin/
          chmod +x $out/bin/simple
        '';

        postFixup = ''
          echo "Patching binary: $out/bin/simple"
          patchelf --set-interpreter "${dynamicLinker}" \
                   --set-rpath '$ORIGIN:${rpath}' $out/bin/simple
          find $out/bin -type f \( -name "*.so" -o -name "simple" \) -exec \
            patchelf --set-rpath '$ORIGIN:${rpath}' {} ';'
        '';

        meta = with pkgs.lib; {
          description = "Simple binary built from release";
          license = licenses.mit;
          platforms = platforms.linux;
        };
      };
    };

    defaultPackage.x86_64-linux = self.packages.x86_64-linux.simple;
    defaultApp = { type = "app"; program = "${self.packages.x86_64-linux.simple}/bin/simple"; };
  };
}

Running it produces the following output:

Failed to load System.Private.CoreLib.dll (error code 0x8007000B)
Path: /nix/store/xyz-simple-1.0/bin/System.Private.CoreLib.dll
Error message: An attempt was made to load a program with an incorrect format.
(0x8007000B)
Failed to create CoreCLR, HRESULT: 0x8007000B