Skip to content

Instantly share code, notes, and snippets.

@nat-418
Last active March 24, 2024 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nat-418/ce9b5e9f49c969538947d66924345bbe to your computer and use it in GitHub Desktop.
Save nat-418/ce9b5e9f49c969538947d66924345bbe to your computer and use it in GitHub Desktop.
Running your own Nix channel

Running your own Nix channel

In my previous article, How to build with Nix, I explained how to write a Nix package and contribute it to the official Nix package repository. One of the advantages of Nix is how easy it is to develop your own custom Nix package repository, called a channel. A channel can be implemented simply as a tarball containing a default.nix file like this:

let
  pkgs = import <nixpkgs> {};
in

{
  knock = pkgs.callPackage ./pkgs/knock.nix {};
}

In this example, we take the knock program described in the previous article and put it in a pkgs directory—this is optional, I just like to keep the directory organized this way. The callPackage function handles making sure that the knock.nix package gets the parameters it needs. The advantage of this pattern is that it allows you to develop your own packages just as if you were doing it for the official repository:

{ lib, buildGoModule, installShellFiles, fetchFromGitHub }:

buildGoModule rec {
  pname = "knock";
  version = "0.0.2";

  src = fetchFromGitHub {
    owner = "nat-418";
    repo = pname;
    rev = "a3749685381cae178bb5836c67645e0fce7aa1d0";
    hash = "sha256-VXrWphfBDGDNsz4iuUdwwd46oqnmhJ9i3TtzMqHoSJk=";
  };

  vendorHash = "sha256-wkSXdIgfkHbVJYsgm/hLAeKA9geof92U3mzSzt7eJE8=";

  outputs = [ "out" "man" ];

  nativeBuildInputs = [ installShellFiles ];

  postInstall = ''
    installManPage man/man1/knock.1
  '';

  meta = with lib; {
    description = "A simple CLI network reachability tester";
    homepage = "https://github.com/nat-418/knock";
    license = licenses.bsd0;
    changelog = "https://github.com/nat-418/knock/blob/${version}/CHANGELOG.md";
    maintainers = with maintainers; [ nat-418 ];
  };
}

Once you have the above, you can test it with a quick nix-build. If that works, it should produce a result symlink pointing to artifacts in the Nix store. If everything looks good, you just need to distribute this directory as a tarball. Probably the easiest way to do this is using GitHub. Every GitHub repository has an automatic archive accessible at https://github.com/$USER_NAME/$REPO_NAME/archive/$BRANCH_NAME.tar.gz. You can add that as a Nix channel like so:

$ nix-channel --add https://github.com/nat-418/grimoire/archive/main.tar.gz grimoire
$ nix-channel --update

You can now use, e.g., <grimoire> in your Nix files just as you use <nixpkgs>. Here's an example using Home Manager:

{pkgs, config, ...}:

let
  grimoire = import <grimoire> {};
in

{
  home = {
    packages = with pkgs; [
      abduco
      age
      # more packages
      grimoire.knock
    ];
    # more config
  };
}

There are many uses for a custom channel: from project-specific tools to just getting your own software released without having to ask anyone else to accept a pull request. Nix gives you that flexibility in a simple and easy-to-maintain solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment