Flake-programs-sqlite: fixing command-not-found for pure flake systems

Hey everyone,
happy to introduce flake-programs-sqlite, a simple flake to automagically specify programs.sqlite for command-not-found.

Why?

NixOS systems configured with flakes often don’t have a channel set (e.g. nix-channel --list shows no channel), which usually results in a broken command-not-found as the command database is part of the channel system and not part of nixpkgs.
Up to now the only option was to use nix-index, but it was not possible to get back the UX known from channels. (see here)

With flake-programs-sqlite a working command-not-found only requires a few additions to a flake based system configuration.

How?

flake-programs-sqlite makes use of a mapping from git commit hashes to channel names. This mapping is updated by a GitHub action by scraping {channels,releases}.nixos.org (currently) about every ten minutes.
When importing flake-programs-sqlite, the standard flake mechanism can be used to pin it’s nixpkgs input. When the programs-sqlite output package is requested, a fixed output derivation for a programs.sqlite database matching the revision of the input nixpkgs is constructed from the scraped data. The result of this derivation is then injected into command-not-found.

NixOS Module Integration

Using flake-programs-sqlite as a module in your NixOS configuration is the preferred method. Just add it to your flake inputs, pass it to your outputs and add it to your list of modules:

# ... 
inputs.fps.url = "github:wamserma/flake-programs-sqlite";
inputs.fps.inputs.nixpkgs.follows = "nixpkgs";

# ...

outputs = { nixpkgs, fps, ... }: {

    nixosConfigurations.mymachine = nixpkgs.lib.nixosSystem {
      modules =
        [
          (import configuration.nix)
          fps.nixosModules.programs-sqlite
          # ...
        ];
    };

Contribute

Feel free to submit issues or pull requests on the GitHub repository.

Note

Scraping started on 21st December 2022. If a certain channel revision is missing, follow the README for instructions on scraping or open an issue.

10 Likes

Wouldn’t this work?

nix.registry.nixpkgs.flake  = inputs.nixpkgs;
nix.nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
1 Like

No, this only pins the version of nixpgks in the flake registry. The command-not-found script relies on information that can only be computed after a nixpkgs commit has been fully evaluated and thus can only be found in the channel metadata and not in the nixpkgs-flake.

2 Likes

@wamserma Thanks for this, I was seeing NAR mismatches fetching the channel between machines. But no more!

Thanks for this! I wasn’t aware what exactly broke the command-not-found integration at first. This fixes it for me.