Skip to content

Repository files navigation

GuixPkgs Logo

GuixPkgs

GuixPkgs translates selected GNU Guix package graphs into checked-in Nix expressions. Nix evaluates them without Import From Derivation (IFD) or a running Guix daemon.

Motivation

Guix and Nix share the exact same underlying deployment model, but they are built on different languages (Guile Scheme vs. the Nix expression language). While it is technically possible to evaluate Guix packages within Nix using IFD (Import From Derivation), IFD is notoriously slow, breaks evaluation caching, and is forbidden in pure evaluation modes (such as standard Nix flakes).

We want to allow users to transparently mix and match nixpkgs and Guix packages within the same Nix flake, retaining fast evaluation and full reproducibility.

Goal

The goal of this repository is to act as a direct, automated translation layer:

  1. Translate the dependency closures of selected Guix packages at a given commit into a deduplicated set of .nix files.
  2. Provide a standard Nixpkgs-like interface (packages.x86_64-linux.<package>) via a flake, mapping names to translated packages wrapped with Guix-generated runtime environments.
  3. Automatically sync and translate the upstream Guix tree on a recurring schedule (e.g. via GitHub Actions), recording the exact Guix state in guix-metadata.json.

How it Works

GuixPkgs leverages guix-transfer to perform a one-time conversion per Guix commit. The resulting repository tree looks like this:

guixpkgs/
├── flake.nix             # The entry point exposing the Guix packages as Nix outputs
├── guix-metadata.json    # Tracks the Guix channel, commit, and sync timestamp
├── .github/
│   └── workflows/
│       └── sync.yml      # GitHub Action to periodically sync with upstream Guix
└── pkgs/
    ├── by-name/          # Human-readable entry points wrapping Guix packages
    │   ├── h/hello.nix   # e.g., `{ pkgs }: pkgs.callPackage ../../wrap-guix-package.nix { … }`
    │   └── z/zile.nix
    ├── store/            # The deduplicated translated Nix derivations, each a
    │   ├── b6x8v...-hello.nix             # standalone `builtins.derivation { … }`
    │   ├── c7y9w...-hello-runtime-env.nix # the package's generated `etc/profile`
    │   └── ...
    ├── sources/          # Local files (patches, builder scripts) referenced by the derivations
    └── wrap-guix-package.nix # Generic runtime wrapper for translated packages

Each store/*.nix file is a self-contained builtins.derivation that references its dependencies directly via (import ../store/<file>.nix).<output>. Public by-name entries don't expose that raw derivation; instead each is a small { pkgs } function that wraps the translated package and sources a companion *-runtime-env derivation's etc/profile before running any program. That runtime environment is generated by Guix's own search-path machinery over the package and its target runtime inputs, so tools work outside a Guix profile — without unioning those inputs into the visible package output.

The wrapper keeps both halves reachable through passthru: pkg.unwrapped is the raw translated main output and pkg.runtimeEnv is the generated profile. Packages that can serve as login shells also expose a package-relative pkg.shellPath; Bash currently reports /bin/bash. Some packages need small, Nix-specific build adjustments; those are applied during translation by guix-transfer, not in this repo — see Patching packages.

Syncing Manually

You can manually trigger the translation of Guix derivations into Nix expressions at any time. The flake exposes an app to run the synchronization process:

# Note: This requires `guix` to be installed and the Guix daemon running.
nix run .#sync

Package specifications are listed in %package-names in get-all-derivations.scm. Guix variables that are not package specifications belong in %aliased-packages, which preserves their requested public names.

After the sync completes, add the generated package tree and metadata so Nix can evaluate them:

git add pkgs/ guix-metadata.json

Binary Cache

To avoid building Guix packages from source, you can use the provided Cachix binary cache. You can configure this by adding the following nixConfig to your flake.nix:

  nixConfig = {
    extra-substituters = [ "https://guixpkgs.cachix.org" ];
    extra-trusted-public-keys = [ "guixpkgs.cachix.org-1:rM4xwCs5NUy+FcCKkiWP/CmRaSVxxDPaKWZvM1bRopg=" ];
  };

Alternatively, you can temporarily use it via the command line:

nix build .#hello \
  --extra-substituters https://guixpkgs.cachix.org \
  --extra-trusted-public-keys guixpkgs.cachix.org-1:rM4xwCs5NUy+FcCKkiWP/CmRaSVxxDPaKWZvM1bRopg=

Example Usage

Because GuixPkgs translates Guix packages into pure Nix expressions, they become standard Nix derivations (technically, they evaluate to an attribute set created by builtins.derivation { ... }).

In your own projects, you can mix and match nixpkgs and guixpkgs seamlessly via flakes:

{
  description = "A project mixing Nix and Guix";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    guixpkgs.url = "github:fzakaria/guixpkgs";
  };

  outputs = { self, nixpkgs, guixpkgs }:
  let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
    guixPkgs = guixpkgs.packages.${system};
  in {
    devShells.${system}.default = pkgs.mkShell {
      buildInputs = [
        pkgs.git                   # From Nixpkgs
        guixPkgs.hello             # From Guix (via GuixPkgs)
      ];
    };
  };
}

Run standard Nix commands against Guix packages effortlessly:

Note

Building Guix packages from source within Nix can sometimes fail during bootstrap (e.g., chmod: Operation not permitted). This is often because Guix's bootstrap scripts try to restore SETGID bits, which the Nix sandbox strictly blocks. To successfully build from source, you may need to disable syscall filtering and/or the sandbox temporarily.

# Build the GNU Hello package from Guix
nix build .#hello --option filter-syscalls false --option sandbox false

# Drop into a shell with Zile from Guix
nix shell .#zile --option filter-syscalls false --option sandbox false

Patching packages

pkgs/store, pkgs/sources, and pkgs/by-name are generated and replaced on every sync. Do not edit them by hand. Some packages need small, Nix-specific adjustments because the Guix and Nix build sandboxes differ.

All such fixes are applied at translation time, in guix-transfer — never as a Nix overlay in this repo.

Why not a Nix overlay?

Guix bakes absolute dependency store paths into each package's builder script (the Guile %build-inputs):

("perl" . "/nix/store/h0gbcdg…-perl-boot0-5.36.0")

Those builder scripts are frozen source files. If you change a package's derivation in a way that alters its output hash (disabling tests, rewriting the builder, dropping an attribute), every consumer's builder still points at the old path — so the dependency vanishes from the consumer's PATH at build time (classic symptom: configure: error: perl not found). A Nix overlay can't fix this because it can't rewrite the frozen builders. The change has to happen where builders and dependency edges are emitted together: during translation.

How it's done

guix-transfer applies these fixes before any path is hashed, so the modified build and all downstream references stay consistent:

Problem Handled by
Bootstrap test suites fail under Nix's sandbox guix-transfer --disable-tests rewrites #:tests? #t#:tests? #f in every *-builder script. The nix run .#sync app passes this flag.
An installer applies setuid or setgid modes to a Nix store output guix-transfer disables those modes beside the builder's existing install-time ownership guard before paths are hashed.
disallowedReferences (etc.) point at an untranslated /gnu/store path, which Nix rejects as an illegal reference specifier guix-transfer filters invalid specifiers out of the allowed/disallowed References/Requisites attributes.

If a new package needs a tweak, add it to guix-transfer (e.g. a builder substitution applied in stage_source) and re-sync — there is deliberately no overlay layer to reach for.

About

Guix Packages collection built via Nix

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages