+++
title = "How To Casually Contribute to NixOS"
description = "remove DRAFT prefix and add a date field to link this from the index and feeds"
+++

as a [nix/nixOS](https://nixos.org) user, you'll inherently find yourself writing code, and some of this code might be valuable to others: be it new packages, improvements upon existing packages, or new services/options. part of what makes nix so successful (IMO) is the ease of sharing work and upstreaming, so i'm setting out here to show some easy workflows for doing so.

the number one thing you can do -- if you're not already -- is host your nix config publicly. for example, mine is [here](https://git.uninsane.org/colin/nix-files), and even without advertising it i occasionally hear from people in my orbit that they've copied some approach. as a beginner i had some public configs i found on google or [wiby](https://wiby.me) which i routinely consulted, and the authors are likely unaware since i never even contacted them.

## Authoring New Packages
let's say you find a package you want but isn't yet packaged. first, confirm it doesn't exist by searching the package name (and likely variants) on github. remove all filters, so that you're searching both PRs and issues: maybe somebody opened a [package request] (TODO: link docs) and there's already something to work off of. for [example](https://github.com/NixOS/nixpkgs/issues?q=zecwallet-lite).

having confirmed that, let's add a new package. anywhere in your config, add an [overlay](TODO: link docs):
```nix
{ ... }:
{
  nixpkgs.overlays = [
    (final: prev: {
      zecwallet-lite = prev.callPackage ./zecwallet-lite { };
    })
  ];
}
```

i'm just going to show the process i followed when upstreaming that zecwallet-lite package. create the package directory so that the callPackage knows what to reference:
```sh
$ mkdir zecwallet-lite
$ touch zecwallet-lite/default.nix
```

when you reference a path in nix like `./zecwallet-lite`, it'll resolve to `./zecwallet-lite/default.nix` if that's valid. if you're using a flake, the path won't resolve unless it's in git:
```sh
$ git add zecwallet-lite/default.nix
```

now i locate the upstream package distribution. zecwallet-lite is distributed as an appimage, so i search nixpkgs for other appimages to reference:

```sh
$ cd ~/
$ git clone git@github.com:uninsane/nixpkgs.git
$ cd nixpkgs
$ rg appimage pkgs/applications -l | xargs wc -l | sort -h
   19 pkgs/applications/misc/remnote/default.nix
   24 pkgs/applications/video/losslesscut-bin/default.nix
   25 pkgs/applications/networking/instant-messengers/caprine-bin/default.nix
   26 pkgs/applications/misc/fspy/default.nix
   27 pkgs/applications/audio/sonixd/default.nix
   ...

```

`remnote` is a simple derivation, only 19 LOC:
```nix
{ lib, fetchurl, appimageTools }:

appimageTools.wrapType2 rec {
  pname = "remnote";
  version = "1.7.6";

  src = fetchurl {
    url = "https://download.remnote.io/RemNote-${version}.AppImage";
    sha256 = "sha256-yRUpLev/Fr3mOamkFgevArv2UoXgV4e6zlyv7FaQ4RM=";
  };

  meta = with lib; {
    description = "A note-taking application focused on learning and productivity";
    homepage = "https://remnote.com/";
    maintainers = with maintainers; [ max-niederman ];
    license = licenses.unfree;
    platforms = platforms.linux;
  };
}
```

so copy that to `zecwallet-lite/default.nix` and edit the values to match your appimage package. for the hash, you can just change one character so it fails validation, and nix will tell you the actual hash (hacky, but easy process to remember).

then build the package, test it, and tweak it until you're happy with it. the simplest way to do that is add it to `environment.packages` and `nixos-rebuild switch`. most of the time if it builds, it'll run (and you might just need to patch up some icon/.desktop files, etc).

## Upstreaming New Packages

so the package builds, you've used it long enough to be confident in it: time to upstream it from your silo into the main nixpkgs. even if you're purely self-interested, upstreaming means less custom code for you to maintain, less burden keeping the package version up-to-date since others will be helping you with this, and less time spent rebuilding it when a dependency updates since it'll be present in the official build caches. it often takes all of ten minutes once you're familiar.

go back to your `nixpkgs` repo and check out the `master` branch. guess a reasonable folder for the package, like `pkgs/applications/misc/`, and copy your package there:
```sh
$ cp -R /etc/nixos/zecwallet-lite ~/nixpkgs/pkgs/applications/misc/
```

then take your `callPackage` invocation from your overlay and place it in `pkgs/top-level/all-packages.nix` instead. `git add` the file, and then make sure the package builds:
```sh
~/nixpkgs$ nix build './#zecwallet-lite'
~/nixpkgs$ ./result/bin/zecwallet-lite  # make sure it runs
```

commit the changes, push to a github account, and open a PR. github should pre-populate the PR description with a checklist for you to complete. near as i can tell, you don't have to check _every_ item: it's just a way for reviewers to know where to focus.

## Cleanup Work

so you could leave the duplicate package definition both in your `/etc/nixos` repo _and_ in your `nixpkgs` repo, and wait until the next release of nixos/nixpkgs before cleaning up, or you can reference commits in the nixpkgs repository _or in a PR_ from your nixos configuration directly, and consolidate this now.

TODO: show how to apply patches to nixpkgs within a flake.


## OLD: TODO: cleanup

first, i create a package in `~/nixos/pkgs/my-package`, add it to the `~/nixos/pkgs/overlay.nix`, and rebuild.

after i know the package is working reliably i:
- add the package to `~/dev/nixpkgs`
- `git diff HEAD~1.. > ~/nixos/nixpatches/my-package.patch`
- link this `my-package.patch` into the nixpatches and remove `~/nixos/pkgs/my-package`.

after my overlay is working reliably i:
- `git push colinsane new-pkg-my-package` and open a PR.

as the PR is worked, i'll repeat this process (`git diff` into a patch, then commit & push once i see it's working).

once the PR is merged i:
- replace `~/nixos/nixpatches/my-package.patch` with a link to the PR's diff instead.

finally as new nixos versions are released my `~/nixos/nixpatches` directory shrinks.
