diff --git a/test-detect-targets-musl.sh b/.github/scripts/test-detect-targets-musl.sh
similarity index 69%
rename from test-detect-targets-musl.sh
rename to .github/scripts/test-detect-targets-musl.sh
index 9613120f..e8f404b1 100755
--- a/test-detect-targets-musl.sh
+++ b/.github/scripts/test-detect-targets-musl.sh
@@ -1,6 +1,4 @@
-#!/bin/ash
-
-# shellcheck shell=dash
+#!/bin/bash
 
 set -exuo pipefail
 
@@ -13,7 +11,7 @@ apk add gcompat
 
 ls -lsha /lib
 
-GNU_TARGET=$(echo "$TARGET" | sed 's/musl/gnu/')
+GNU_TARGET=${TARGET//musl/gnu}
 
 [ "$(detect-targets)" = "$(printf '%s\n%s' "$GNU_TARGET" "$TARGET")" ]
 
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 38f844c4..b40f7225 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -139,28 +139,50 @@ jobs:
       CARGO_PROFILE_RELEASE_LTO: no
       CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 4
 
-  detect-targets-alpine-test:
+  detect-targets-build:
     runs-on: ubuntu-latest
     env:
       CARGO_BUILD_TARGET: x86_64-unknown-linux-musl
-      TARGET: x86_64-unknown-linux-musl
     steps:
     - uses: actions/checkout@v4
-    - name: Install x86_64-unknown-linux-musl target
-      run: rustup target add $TARGET
+    - name: Install ${{ env.CARGO_BUILD_TARGET }} target
+      run: |
+        rustup target add $CARGO_BUILD_TARGET
+        pip3 install -r zigbuild-requirements.txt
     - uses: Swatinem/rust-cache@v2
+      with:
+        cache-all-crates: true
     - name: Build detect-targets
       run: |
-        pip3 install -r zigbuild-requirements.txt
-        cargo zigbuild --bin detect-targets --features cli-logging --target $TARGET
+        cargo zigbuild --features cli-logging --target $CARGO_BUILD_TARGET
+      # Set working directory here, otherwise `cargo-zigbuild` would download
+      # and build quite a few unused dependencies.
+      working-directory: crates/detect-targets
+    - uses: actions/upload-artifact@v3
+      with:
+        name: detect-targets
+        path: target/${{ env.CARGO_BUILD_TARGET }}/debug/detect-targets
+
+  detect-targets-alpine-test:
+    runs-on: ubuntu-latest
+    needs: detect-targets-build
+    steps:
+    - uses: actions/checkout@v4
+
+    - uses: actions/download-artifact@v3
+      with:
+        name: detect-targets
+    - run: chmod +x detect-targets
+
     - name: Run test in alpine
       run: |
         docker run --rm \
-          --mount src="$PWD/target/$TARGET/debug/detect-targets",dst=/usr/local/bin/detect-targets,type=bind \
-          --mount src="$PWD/test-detect-targets-musl.sh",dst=/usr/local/bin/test.sh,type=bind \
-          alpine test.sh "$TARGET"
+          --mount src="$PWD/detect-targets",dst=/usr/local/bin/detect-targets,type=bind \
+          --mount src="$PWD/.github/scripts/test-detect-targets-musl.sh",dst=/usr/local/bin/test.sh,type=bind \
+          alpine /bin/ash -c "apk update && apk add bash && test.sh x86_64-unknown-linux-musl"
 
   detect-targets-ubuntu-test:
+    needs: detect-targets-build
     strategy:
       fail-fast: false
       matrix:
@@ -169,16 +191,56 @@ jobs:
           - ubuntu-latest
     runs-on: ${{ matrix.os }}
     steps:
-    - uses: actions/checkout@v4
-    - uses: Swatinem/rust-cache@v2
+    - uses: actions/download-artifact@v3
       with:
-        key: ${{ matrix.os }}
-    - name: Build detect-targets
-      run: cargo build --bin detect-targets --features cli-logging
+        name: detect-targets
+    - run: chmod +x detect-targets
+
     - name: Run test in ubuntu
       run: |
         set -exuo pipefail
-        [ "$(./target/debug/detect-targets)" = "$(printf '%s\n%s' x86_64-unknown-linux-gnu x86_64-unknown-linux-musl)" ]
+        [ "$(./detect-targets)" = "$(printf 'x86_64-unknown-linux-gnu\nx86_64-unknown-linux-musl')" ]
+
+  detect-targets-more-glibc-test:
+    needs: detect-targets-build
+    strategy:
+      fail-fast: false
+      matrix:
+        container:
+          - archlinux
+          - fedora:37
+          - fedora:38
+          - fedora:39
+          - fedora
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/download-artifact@v3
+      with:
+        name: detect-targets
+    - run: chmod +x detect-targets
+
+    - name: Run test
+      run: |
+        set -exuo pipefail
+        [ "$(docker run --rm \
+          --mount src="$PWD/detect-targets",dst=/usr/local/bin/detect-targets,type=bind \
+          ${{ matrix.container }} detect-targets )" = "$(printf 'x86_64-unknown-linux-gnu\nx86_64-unknown-linux-musl')" ]
+
+  detect-targets-nix-test:
+    needs: detect-targets-build
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/download-artifact@v3
+      with:
+        name: detect-targets
+    - run: chmod +x detect-targets
+
+    - name: Run test
+      run: |
+        set -exuo pipefail
+        [ "$(docker run --rm \
+          --mount src="$PWD/detect-targets",dst=/detect-targets,type=bind \
+          nixos/nix /detect-targets )" = x86_64-unknown-linux-musl ]
 
   # Dummy job to have a stable name for the "all tests pass" requirement
   tests-pass:
@@ -188,8 +250,11 @@ jobs:
     - cross-check
     - lint
     - release-dry-run
+    - detect-targets-build
     - detect-targets-alpine-test
     - detect-targets-ubuntu-test
+    - detect-targets-more-glibc-test
+    - detect-targets-nix-test
     if: always() # always run even if dependencies fail
     runs-on: ubuntu-latest
     steps:
diff --git a/crates/detect-targets/src/detect/linux.rs b/crates/detect-targets/src/detect/linux.rs
index bba7fe60..04a88924 100644
--- a/crates/detect-targets/src/detect/linux.rs
+++ b/crates/detect-targets/src/detect/linux.rs
@@ -38,16 +38,23 @@ pub(super) async fn detect_targets(target: String) -> Vec<String> {
                 .expect("unwrap: target always has a - for cpu_arch")
                 .0;
 
-            let cpu_arch_suffix = cpu_arch.replace('_', "-");
+            let handles: Vec<_> = {
+                let cpu_arch_suffix = cpu_arch.replace('_', "-");
+                let filename = format!("ld-linux-{cpu_arch_suffix}.so.2");
+                let dirname = format!("{cpu_arch}-linux-gnu");
 
-            let handles: Vec<_> = [
-                format!("/lib/ld-linux-{cpu_arch_suffix}.so.2"),
-                format!("/lib/{cpu_arch}-linux-gnu/ld-linux-{cpu_arch_suffix}.so.2"),
-                format!("/usr/lib/{cpu_arch}-linux-gnu/ld-linux-{cpu_arch_suffix}.so.2"),
-            ]
-            .into_iter()
-            .map(|p| AutoAbortHandle(tokio::spawn(is_gnu_ld(p))))
-            .collect();
+                [
+                    format!("/lib/{filename}"),
+                    format!("/lib64/{filename}"),
+                    format!("/lib/{dirname}/{filename}"),
+                    format!("/lib64/{dirname}/{filename}"),
+                    format!("/usr/lib/{dirname}/{filename}"),
+                    format!("/usr/lib64/{dirname}/{filename}"),
+                ]
+                .into_iter()
+                .map(|p| AutoAbortHandle(tokio::spawn(is_gnu_ld(p))))
+                .collect()
+            };
 
             let has_glibc = async move {
                 for mut handle in handles {
@@ -108,7 +115,7 @@ You are not meant to run this directly.
     if status.success() {
         // Executing glibc ldd or /lib/ld-linux-{cpu_arch}.so.1 will always
         // succeeds.
-        stdout.contains("GLIBC").then_some(Libc::Gnu)
+        (stdout.contains("GLIBC") || stdout.contains("GNU libc")).then_some(Libc::Gnu)
     } else if status.code() == Some(1) {
         // On Alpine, executing both the gcompat glibc and the ldd and
         // /lib/ld-musl-{cpu_arch}.so.1 will fail with exit status 1.