Image for post flake-checker
Jun 20, 2023 by Luc Perkins

Introducing the Nix Flake Checker

Quite possibly the best thing about the Nix ecosystem is that there’s a small army of people hard at work improving Nixpkgs, the largest software package repository in existence and one of the most active repos on GitHub, every single day. Not only are they constantly adding brand new packages for stuff that you might want to use—over 80,000 packages and counting!—they’re also updating existing packages, which sometimes even includes fixes for critical security vulnerabilities.

But to take full advantage of this steady drumbeat of progress, it’s important that you follow some best practices. To help you adopt those practices, we at Determinate Systems have created a tool called Nix Flake Checker and we’re excited to release it to the Nix community.

What Nix Flake Checker looks for

In any flake-enabled Nix project, Nix Flake Checker runs three checks on the root-level Nixpkgs dependencies in your flake inputs:

  1. If your Nixpkgs input uses a specific Git branch, such as nixpkgs-unstable, it needs to be a supported release branch. Nixpkgs’ release branches stop receiving updates roughly 7 months after release and then gradually become more and more out of date—read: potentially insecure—over time. Release branches are also certain to have good binary cache coverage, which other branches can’t promise.
  2. Your Nixpkgs input must have been updated in the last 30 days. Because Nixpkgs sees a steady stream of community updates, the “older” your Nixpkgs revision, the less likely you’ll be to benefit from these updates. 30 days is somewhat arbitrarily chosen and potentially too lax; we may make this more strict in the future.
  3. If your Nixpkgs input is a GitHub repo, it needs to have the NixOS org as the owner. In principle, you could have a Nixpkgs input owned by someone else, for example inputs.nixpkgs.url = "github:EvilCo/nixpkgs". But we don’t recommend this, first because forks and other non-upstream variants of Nixpkgs can introduce security vulnerabilities and unexpected behaviors, and second because those forks are often not kept up to date (though maybe they would be if they used Nix Flake Checker 😉).

Upstream Nixpkgs isn’t bulletproof—nothing in software is!—but it has a wide range of security measures in place, most notably continuous integration testing with Hydra, that mitigate a great deal of supply chain risk.

It’s important to keep in mind that Nix Flake Checker checks all root-level Nixpkgs inputs. In a flake input group like this, three inputs would be checked:

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nixpkgs-very-specific-ref.url = "github:NixOS/nixpkgs/0b23874b968c333abd4434701c2bbd552da8af8b";
};

It does not, however, check non-root Nixpkgs inputs for other inputs. If your flake uses rust-overlay as an input, for example, then Nix Flake Checker doesn’t check rust-overlay’s own Nixpkgs input, even though that input is registered in your flake.lock. If you used a follows statement to pin rust-overlay’s Nixpkgs to your root Nixpkgs, however, then Nix Flake Checker would cover that:

{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; # Root Nixpkgs
inputs.rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs"; # rust-overlay pin to root Nixpkgs
};
}

Run Nix Flake Checker locally

Run this command in the same directory as the lock file to check the flake.lock in a Nix project:

Terminal window
nix run "github:DeterminateSystems/flake-checker"
# Or specify a different location
nix run "github:DeterminateSystems/flake-checker" -- /some/other/project/flake.lock

This provides a plaintext assessment of your flake.lock’s health, indicating any issues with your Nixpkgs inputs and providing pointers on how to bring your flake in line with best practices.

You can also add it to your Nix profile:

Terminal window
nix profile install "github:DeterminateSystems/flake-checker"

And of course you can add it to a Nix development environment.

Automatic checks using the Nix Flake Checker Action

While running ad-hoc checks locally and fixing issues is nice, we recommend using automated approaches whenever possible. For GitHub Actions users, we’ve created the Determinate Flake Checker Action. To add the checker to your pipeline:

- name: Check Nix flake inputs
uses: DeterminateSystems/flake-checker-action@v4

Here’s an example of using it in a real pipeline:

jobs:
nix_build:
name: Build Nix targets
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Check Nix flake inputs
uses: DeterminateSystems/flake-checker-action@v5
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v4
- name: Build Nix package
run: nix build

The Action outputs a job summary as Markdown. You can see some live examples here.

If your flake.lock has a clean bill of health, you should see a summary like this:

Nix Flake Checker summary with a clean bill of health
Nix Flake Checker summary with a clean bill of health

But if your flake.lock has issues, you’ll see something like this:

Nix Flake Checker summary with a not-so-squeaky-clean bill of health
Nix Flake Checker summary with a not-so-squeaky-clean bill of health

As you can see, the summary points out not only what is wrong but also how you can fix it. In this case, if you click on What to do the summary tells you to use one of a select set of officially supported branches and then shows you how to update your flake inputs accordingly.

For the sake of your flakes’ long-term health, we recommend using the Nix Flake Checker Action in conjunction with our update-flake-lock Action, which automatically submits nix flake update pull requests to flake-backed Nix projects on GitHub.

Telemetry

We’d like you to be aware that Nix Flake Checker collects a bit of anonymized, aggregated telemetry that Determinate Systems uses to measure the impact of our efforts. You can see a full breakdown of what information it collects in the Nix Flake Checker README.

Implications

At Determinate Systems, our goal is to make Nix better. Pinning dependencies is quite possibly the killer feature of Nix flakes, and flakes become all the more powerful when they’re kept up to date with the most recent work of the incredible Nix community. We believe that supporting best practices in flake dependencies is a small but substantial step forward for developers and orgs that use Nix.

We’re open to feedback on both Nix Flake Checker and the Nix Flake Checker Action, so do feel free to submit issues and pull requests. We welcome bug fixes, feature requests, and everything between.


Share
Avatar for Luc Perkins
Written by Luc Perkins

Luc is a technical writer, software engineer, and Nix advocate who's always on the lookout for qualitatively better ways of building software. He originally hails from the Pacific Northwest but has recently taken to living abroad.