The Guix Nix Abomination: Leveraging Guix Derivations in Nix

dagenix2 pts0 comments

The Guix Nix Abomination: Leveraging Guix derivations in Nix | Farid Zakaria’s Blog

The Guix Nix Abomination: Leveraging Guix derivations in Nix

Published 2026-06-05 on<br>Farid Zakaria's Blog

Nix and Guix look like rival ecosystems, but under the hood they’re the same “Input Output Machine”.

Need proof? 🕵 How about we build a Guix derivation with Nix.

First let’s create a super basic derivation in Guix: Hello world.

❯ guix repl -- /dev/stdin 'EOF'<br>(use-modules (guix derivations) (guix store))<br>(with-store %store<br>(let ((drv (derivation %store "simple" "/bin/sh"<br>'("-c" "echo Hello World > $out")<br>#:env-vars '(("PATH" . "/bin"))<br>#:system "x86_64-linux")))<br>(format #t "~a\n" (derivation-file-name drv))))<br>EOF<br>/gnu/store/zr0q11srv4yir8a6wrz582js7zsi17ij-simple.drv

We then ask Nix to build it. 🪄

We ask to use /gnu/store as the Nix store and have it write its state, database and log files in alternate directories, so it does not collide or mess with Guix.

Note<br>It’s slightly more complicated. Nix happens to check its SQLite database for the derivation, so we need to register it first. The version of Guix (v1.5.0) I’m using leverages a guix-daemon user that runs inside a private mount namespace where /gnu/store is writable, but everyone else (including me) sees it as read-only. The unshare --mount creates a new private mount namespace so I can mount it as read-write and run the Nix command against it.

❯ cat > /tmp/register.txt

We just built a Guix derivation using Nix. 🔥

How is that possible?

Both take a language frontend, Nix or Guile (Scheme), that<br>compiles to a derivation (recipe) and pass that onto a builder (daemon) that executes it to produce an output.

What makes them both special is they both promise the same thing: hermetic builds . Everything needed to build the output is declared in the recipe: sources, environment variables, dependencies, etc.

“Under Nix, a build process will only find resources that have been declared explicitly as dependencies. There’s no way it can build until everything it needs has been correctly declared. If it builds, you will know you’ve provided a complete declaration.” – Nix OS Website

Guix, specifically the daemon, was forked from Nix early on, and as a result the two are very similar; they both share the same derivation format, ATerm, for instance.

Guix is based on the Nix package manager – Guix Website

That’s why our earlier example of building the Guix derivation with Nix was possible without much translation.

What if we could leverage an existing recipe from Guix in Nix in its traditional /nix/store?

If we could convert from one recipe file to the other, we could use the existing recipes from Guix in Nix and vice versa.

Turns out this is far more feasible than you would think, because Guix is<br>Nix or at least a superset of it.

I, with the help of Claude, built a tool to do just that: guix-transfer 🤯.

guix-transfer is a CLI tool for performing bottom-up translation of GNU Guix derivations into Nix.

Confused? Let us see it in action:

# generate a Guix derivation<br>❯ guix build hello --derivations<br>/gnu/store/2nfg943asrl9dv64zrr1a4kpb25mfafd-hello-2.12.2.drv

# translate it<br>❯ /guix-transfer /gnu/store/2nfg943asrl9dv64zrr1a4kpb25mfafd-hello-2.12.2.drv<br>Loading Guix derivation graph from /gnu/store/2nfg943asrl9dv64zrr1a4kpb25mfafd-hello-2.12.2.drv ...<br>Loaded 228 derivations.<br>Translating bottom-up ...<br>[228/228] done<br>Done. Final Nix derivation:<br>/nix/store/brdd8zw3j9hhq8zf27ixqyi3l61nwppn-hello-2.12.2.drv<br>Realise it with: nix-store --realise --option filter-syscalls false /nix/store/brdd8zw3j9hhq8zf27ixqyi3l61nwppn-hello-2.12.2.drv

# build it with Nix<br># this is a LONG multi-hour build since we build everything from source<br>❯ nix-store --option filter-syscalls false --realise \<br>/nix/store/brdd8zw3j9hhq8zf27ixqyi3l61nwppn-hello-2.12.2.drv

❯ /nix/store/j3940mdzr6qmw4ydhyla663s501vb8ns-hello-2.12.2/bin/hello<br>Hello, world!

Note<br>When you unpack a tarball, tar restores each file’s original permissions, including setuid/setgid bits. Nix’s sandbox installs a seccomp filter that blocks any chmod call that sets these bits, returning “Operation not permitted”. Guix’s early bootstrap uses a Scheme-based tar (gash-utils) that treats this error as fatal, unlike GNU tar which silently skips it. The fix is --option filter-syscalls false, which disables the filter.

If it’s not clear what we just did: we took a Guix derivation and all of its dependencies (down to the bootstrap seeds), translated it to a Nix derivation, and built it with Nix. 😲

What is this abomination and how was this possible!?

It’s important to revisit what a derivation is, and how it’s used in Nix and Guix to better understand how this is possible. Let’s look at the same basic derivation from earlier, Hello World.

You might want to check out my other post on Nix derivations by hand if this interests you 🤓.

derivation {<br>name = "simple";<br>builder = "/bin/sh";<br>system = builtins.currentSystem;<br>args = ["-c"...

guix store derivation hello build derivations

Related Articles