Learning Nix to contribute back

Hi everyone!

I’ve been running NixOS for some time now, and I’m loving it. A lot of work was put into this, and I would like to ‘do my part’ and give something back. I’ve always wanted to contribute to open source software, and now more than ever.

I’d love to be able to help with issues and updates of the nixpkgs repo. The problem I’m having is that the documentation is, as we all know, not that great. I’ve tried packaging an app, it kind of works, but it doesn’t. Perhaps it’s because it’s missing some dependencies, or it’s built on tauri and I saw some issues reported about performance etc. I’ve read through a couple of issues and PRs and I feel lost, too complicated.

My questions are: where do I learn about packaging with Nix? How it works? Do I actually need expert knowledge of the tools used to build these apps (rust, node, python etc), or am I missing something? If you could give me some kind of roadmap of resources, that would be great.

Thanks

1 Like

Hi, it’s really nice you want to contribute! I’m not the most experienced nixpkgs contributor either, but there was a talk at NixCon2024 which covered some of your questions, if you like that format.

2 Likes

where do I learn about packaging with Nix

For specific language packaging, there are some channels in matrix to help: (#rust:nixos.org, #python:nixos.org ,

But you can also consult the nix and nixpkgs manuals.

Do I actually need expert knowledge of the tools used to build these apps

Yes :frowning: I feel much more comfortable packaging a nix derivation if I feel comfortable building it using conventional tools.

You can DIY some stuff by using the packaging knowledge people already coded into nixpkgs, see it’s manual

1 Like

I disagree, the nixpkgs manual is a must, but some documentation will also be in READMEs in the repo, and some best practices are outlined at https://nix.dev/ as well - you’ll want to get somewhat familiar with callPackage. But the docs, generally, are there, even if the formatting could be improved or so on. (And if you see some opportunity for improvement feel free to send a PR.)

Not really, I’ve sent about 200 PRs to nixpkgs and I don’t know jack about the tools in the python, rust, etc. ecosystem, other than the names of the files involved (Cargo.toml, pyproject.toml, etc.)

Node is an exception, JS is just tough to package in general due to there being many kinds of tooling and lockfile formats, bugs in said tooling, the tendency for upstreams to run arbitrary commands during packaging, and the tendency for node et al to download random binaries which you then have to work around.

If you’re packaging rust, go, python, or node, you can use nix-init in the root of a nixpkgs clone (external tool, you can use .e.g nix-shell -p nix-init to get it in a shell, then run it) to get you started quickly. It may be helpful for other languages as well, but you just have to write a bit more afterwards, and it won’t use other language-specific builders.

Do look at other packages in nixpkgs, but do note there are some quite old standards in packaging in the nixpkgs repo, whereas the unstable manual should have the more up-to-date recommendations.

Do not use shallow or treeless clones with nixpkgs, as rebasing is the standard workflow here.
If you want to save time and disk space, fork the repo into your account, then use a blobless clone:

git clone --filter=blob:none https://github.com/YOUR-USERNAME/nixpkgs

And become familiar with git rebasing, if you aren’t.

Commit format should also be followed, generally packagename: init at 1.2.3 or packagename: 1.2.3 -> 1.2.4 or so on, as CI will actually read that and run tests accordingly.

Don’t worry about too much else, nixpkgs-review is overkill for example; reviewers can run that if needed, and they can also provide any other necessary feedback.

Finally, if you have an idea of what to do but are stuck, send the PR anyway, reviewers can help you move it forward, or you can ask here.

PS:

this link is years outdated, don’t use this.

6 Likes

Well that title is a little obvious haha How did I not see that video before. Thanks!

I’ll check those out, thanks!

Thank you @waffle8946, that’s very informative and exactly what I was looking for! I’ll give both manual a read in my spare time and brush up on the things you mentioned.

As I mentioned, I tried to package an app. It builds and runs, but doesn’t play any video I throw at it, just coredumps. (Not looking for you to debug haha) My question is how do you handle runtime dependencies (buildInputs right?) for such projects? This was the biggest gripe for me, I think. Is it just building, see what sticks, change, build again? With this one, it took me a minute to figure out it needs gstreamer plugins (it said it’s missing after running ./result/bin/blink), but as I said, it still doesn’t work as it should so it needs something else as well probably.

EDIT:
I joined the codetriage squad, so hopefully it will let me see different sides of nixpkgs. Not contributing or commenting yet though haha

PS:
For anyone else with the same questions, I found this video very interesting https://www.youtube.com/watch?v=5D3nUU1OVx8 (shame the author had to read the thesis to figure it out lol)

It depends very much on the builder used and whether the code is linked against the correct libs or not. I don’t have too much experience with tauri (essentially rust + js) but nixpkgs does have info about it:

For this case you may also want rustPlatform.bindgenHook and pkg-config (caveat that I didn’t check the code too deeply here).

If you’re still stuck, share what you have so far, and I or others can take a look. (If no one else responds sooner, I can look in about a day from now.)

So I’ve tried building it again, and now it works (although it doesn’t play one of the videos, but that’s probably a bug in the app itself, will check later).

Possible fixes:

  • I updated Jellyfin today from 10.10.5 to 10.10.6
  • Apparently, even with buildRustPackage, I don’t need cargoHash. I had it empty and it never gave me the proper hash. I removed the attribute, and it didn’t complain at all lol
  • I had a few nix files, trying different approaches at the same time. Removed all of them and renamed the file I built now. Could the result be linked/cached to a different build result before, even though I rebuilt it? That’s why it didn’t work no matter what I did?
  • My nixpkgs input is 24.11 which probably changes every hour, so maybe some dependency got updated in the meantime? Not ideal, should’ve used a commit :confused:

Here is the code if you want to have a look code.
The patch is because of this. I should probably comment the code more, but I was just experimenting, so… :stuck_out_tongue:

Either way, it works now, thanks for the help! I’ll probably ask for more haha

because you set cargoLock. FYI the current standard is to use fetchCargoVendor = true; + cargoHash instead, and not vendor the lockfile.

Not sure what you mean by result linked to a result. Changing any input in a build should result in a rebuild, by nix’s design. (Caveat would be fixed-output derivations, such as fetchers, where the only relevant inputs are essentially name and outputHash.)

If you’re PRing to nixpkgs, not really; only “weird” things that deviate from packaging standards or anything surprising in the expression needs commenting.

Makes sense.

I used that because of the patch. I tried using cargoPatches now, with cargoHash and useFetchCargoVendor = true; and now it’s screaming it can’t find the Cargo.lock file. Even though cargoRoot is specified and all.

I appreciate the help, but this is getting more and more irrelevant to the main topic of the post. I’ll create another one later if needed, that focuses on this particular issue :slight_smile: