How to make a package for Nix OS

Aman Setia
8 min readJun 28, 2023

--

Hey! Ever got stuck trying to get your package in nixpkgs? Found the documentation lacking? I tried here to make a simple, straight forward guide going through all the steps of adding your package to nixpkgs, Let’s start!

Nixos logo in gruvbox colors from https://codeberg.org/lunik1/nixos-logo-gruvbox-wallpaper

Prerequisites

  1. A project in any language such as rust, go, nodejs, etc that you want to bring to nixpkgs
  2. Basic git/GitHub knowledge
  3. Basic knowledge of Nix language

Step-by-Step guide

  1. Fork nixpkgs repo

Go to https://github.com/nixos/nixpkgs and hit the fork button

You can keep the default settings and continue with creating a fork.

2. Setting up environment

Once creation of fork is complete, you will be redirected to the nixpkgs repo on your account. You could use your local machine for development or you can take advantage of codespaces given by GitHub for free which gives you a free PC in the cloud for your development! To use this click the code button and select “Codespaces” and click the plus button

This will take you to your cloud VS Code environment with the repo cloned already!

For people doing this on local machine i would recommend not cloning the entire history of commits but instead use --depth option of git to save you some storage. you can do this with :

git clone https://github.com/your-username/nixpkgs --depth=1

Using this will also make the clone much faster.

For people using codespaces like me, codespaces sometimes will make a clone with depth 1 as well, in case you need older commits you can do

git pull origin --deepen=3 where 3 is how much you wanna deepen the repo, ie, how many more commits you need. This is however optional, as you will only need this if you want to make some changes to your commits later on.

If you are on local machine, you probably have nix package manager installed, but to install it on codespaces you should use the single user script from nixos.org by running the following in your terminal

sh <(curl -L https://nixos.org/nix/install) --no-daemon
. /home/codespace/.nix-profile/etc/profile.d/nix.sh

The second command will add the nix binaries to your PATH variable so you can use them. You need to be present in maintainers list to add a package, you can add yourself as follows.

3. Adding yourself as maintainer

If you are reading this guide, chances are you are a first time contributor to nixpkgs, for that you will need to add yourself to maintainers list, to do that open “maintainers/maintainer-list.nix.” Notice that this file is sorted in alphabetical order, so you need to figure out where would your maintainer name come in this file, for example, my name “amanse” came after “amanjeev.” Once you know where to add, to add it, use this

mainatainerName = {
email = "your-email@here.com";
github = "your-github-username";
githubId = github-id(check below on how to find);
name = "your name";
};

To get the github id you need to go to https://api.github.com/users/your-username, for example for my username “amanse” it is https://api.github.com/users/amanse. From the resulting json you need to use the “id” field’s value is your githubId field in the maintainer-list.nix file.

Once this is done, run the following commands in your terminal to commit the changes, your commit of adding yourself as maintainer and adding the package needs to be different.

git add .
git commit -m "maintainers: add your-maintainer-name"

Make sure the commit contains your maintainer name that was the key value in the maintainer-list.nix file.

4. Adding the package to repo

Now we get to the main part, adding the instructions to compile and install the package on a system, this may sound daunting and may remind you of makefiles, but it is actually quite simple, there tools premade for multiple languages, pre configured to compile and install, you just need to pick the tool for your language, they all can be found here https://github.com/NixOS/nixpkgs/tree/master/doc/languages-frameworks

For example for rust it is rustPlatform.buildRustPackage , for golang its buildGoModule and so on. All of these tools can be found in the linked folder. It even has PHP, swift, GNOME and more.

You can see there is a “pkgs” folder in the root of nixpkgs repo that you have open in codespaces or your local machine, with multiple sub folders telling the category of the package, you need to know in which category your package will fall into, for example my game-rs, falls into the “misc” folder category, if it’s a shell it’ll go into “shells” folder and so on. If you are unsure which category to choose but you know of a similar package already in nixpkgs you can see what folder it resides in. Find the category that your package falls into and make a folder there with your package-name. Again using the game-rs example, I will make “game-rs”. Inside this folder make a file “default.nix”, inside this file we define how to build and install the package, somethings may differ depending on the language but these are the common parts in any package:

  1. Package name and version
  2. Downloading source(The binary or the source code from which it will be compiled/installed)
  3. Hash for verification
  4. Metadata about the package

Package name and version is self explanatory but for the source there are couple of different options to get, you probably have your source code on GitHub but Nix can fetch and compile from any Git repo or even direct archive URL. For example to fetch from GitHub from a version tag of let’s say “v0.1.1” from “amanse/game-rs”

{lib, fetchFromGitHub}: {
...
version = 0.1.1;

src = fetchFromGitHub {
owner = "amanse";
repo = "game-rs";
rev = "refs/tags/v${version}";
sha256 = lib.fakeSha256; #don't worry about this for now
};
...
}

At top we are importing lib and fetchFromGitHub, these are inbuilt helpers from Nix itself, lib contains multiple helpful fucntions like fakeSha256 sum generator/placeholder and multiple other fetchers if your source code or binary is not on GitHub, info on other fetchers can be found here https://ryantm.github.io/nixpkgs/builders/fetchers/

It will automatically download the source code, build the package and install it too according to the language or tool that you selected earlier. I would highly recommend going through the documentation on https://github.com/NixOS/nixpkgs/tree/master/doc/languages-frameworks for your specific language. The Sha256 sum of the source archive is required, which we will get later on, for this purpose Nix lib provides fakeSha256 as a placeholder.

Next for the hash verification, each language’s package manager’s lock file has hashes for what version of package to use, for rust you can use cargoHash = lib.fakeSha256; for now and later replace it with the real hash, for golang its vendorHash = lib.fakeSha256;

Next for the metadata part, you need this codeblock

 meta = with lib; {
description = "one-line description of your program";
homepage = "Website of your program or it's github page";
license = licenses.unlicense; #nix has inbuilt license enum, it can be MIT,GPL, etc.
maintainers = [ maintainers.maintainerName ]; #here we use the maintainer name that we added to list before
};

Now we need to tell nix about this new package that we added, we can do so by going into “pkgs/top-level/all-packages.nix” and there are comments to specificy the category, use ctrl+f to find “tools” or whatever category your package falls in and after the comment of your category enter

packageName = callPackage ../misc/package-name;

Instead of “../misc” use the path of your package-name file. Here is an example of how the default.nix file will be looking like right now with package name, version, hash, src and meta.

{ lib
, rustPlatform
, fetchFromGitHub
}:

rustPlatform.buildRustPackage rec {
pname = "game-rs";
version = "0.1.1";

src = fetchFromGitHub {
owner = "amanse";
repo = "game-rs";
rev = "refs/tags/v${version}";
sha256 = lib.fakeSha256;
};

cargoHash = lib.fakeSha256;

meta = with lib; {
description = "Minimal CLI game launcher for linux";
homepage = "https://github.com/amanse/game-rs";
license = licenses.mit;
maintainers = with maintainers; [ amanse ];
};
}

Now to run the package, make sure you are in the root of nixpkgs repo and use the command nix-build -A packageName this will try to build your package, but right now it will fail and that’s okay! It will give an error about wrong Sha256Sum in your source archive and will give you the correct hash, just copy that hash and paste it in sha256 of fetchFromGithub and run the command again. It will again tell you that hash for cargoHash is invalid, again just copy the correct hash it gives and paste it in cargoHash, now your default.nix file must be looking something like this:

{ lib
, rustPlatform
, fetchFromGitHub
}:

rustPlatform.buildRustPackage rec {
pname = "game-rs";
version = "0.1.1";

src = fetchFromGitHub {
owner = "amanse";
repo = "game-rs";
rev = "refs/tags/v${version}";
sha256 = "sha256-Gjw1dRrgM8D3G7v6WIM2+50r4HmTXvx0Xxme2fH9TlQ=";
};

cargoHash = "sha256-ciBIR+a1oaYH+H1PcC8cD8ncfJczk1IiJ8iYNM+R6aA=";

meta = with lib; {
description = "Minimal CLI game launcher for linux";
homepage = "https://github.com/amanse/game-rs";
license = licenses.mit;
maintainers = with maintainers; [ amanse ];
};
}

For language specific things like enabling features in rust you can again refer to the link above for language specific tools. Now if you run the nix-build command again, it should compile and install you rust package! There you have it! You have successfully made a package for Nixos! Now to add this to nixpkgs repo, you need to open a Pull request, but before that let’s commit our changes. The format for commit message for new package is packageName: init at (version) for example to init game-rs at 0.1.1 it will be game-rs: init at 0.1.1

To commit the changes run

git add .
git commit -m "packageName: init at 0.1"
git push

If you are on codespaces like me git will have authentication already setup so you should be able to push changes to your repo directly, now go to the github page of your nixpkgs and you will see the Golden(green in reality) “Compare and pull request” button, click it, the title of the pull request uses a similar format to the commit message, packageName: init at 0.1 or whatever the name of the pacakge and the version is, it will also give a checklist auto generated from a template, check what applies to you and make the pull request. Congratulations! Now you have to wait for someone to review your code and they will give some suggestions, help you solve if you have some issue and once all is done your PR will be merged into nixpkgs and your package will officially be part of Nixpkgs repo! YAY! Give yourself a pat on the back, you have a long way. There are many other advanced topics in nix like fhsEnv and more helper functions in nix to make your complex available on nixos, if you are stuck in someway you can refer to documentation or ask for community to help, nix is blessed with a good community, I will be happy to resolve any issues you face while bringing your package to nixos as well.

Thankyou for reading, Happy coding!

You can find me on github here!

--

--