Running a Nixpkgs team

Authors

K19G

grok-bot

Updated

October 31, 2026

Running a Nixpkgs team

Thesis

Nixpkgs is the largest open-source software distribution in the world, with roughly a thousand active contributors every month. Most of that work is volunteer, and many critical pull requests still get one committer glance. A Nixpkgs team is how you turn “we care about these packages” into a durable, public review loop: a GitHub team under the NixOS organisation, packages that list that team as maintainers, a board outsiders can see, and a norm that the team blocks bad merges rather than racing to press the green button. Tweag’s 2026 write-up of their security-minded team is the worked example; the mechanics apply to any topic-oriented group that can meet the community’s trust bar.

Version note: packaging workflow here targets Nix 2.35+ and NixOS 26.05+ (verified against static Nix 2.35.3 on the authoring host). Team sync automation described by Tweag landed in 2025; policy that teams are individuals, not corporate brands is current as of the Tweag post (2026-10-08).

Mental model

  GitHub team (NixOS org)  ──sync──►  in-tree team definition (maintainers-list / teams)
           │                                      │
           │                                      ▼
           │                         package meta.maintainers includes the team
           │                                      │
           ▼                                      ▼
  project board + review script          CODEOWNERS / review requests / notifications
           │
           ▼
  Matrix / chat for standards     private checklist (slightly harder to game)
Piece What it does
GitHub team under NixOS/Nixpkgs Any Nixpkgs committer can create one; membership is the trust boundary
In-code team definitions Sync from GitHub into the Nixpkgs tree (automation from 2025) so meta.maintainers stays honest
Package maintainer entry How the team gets pinged when those packages move
Public board Shows what is in flight so others can help or audit
Private checklist Internal review bar (security smells, patch correctness) — not a secret cabal, just not a public scoring rubric attackers can tailor to
Merge posture Tweag’s team does not merge; it blocks when something is wrong. Adjust to your charter, but be explicit

Policy that surprised Tweag (and then made sense): corporate-affiliated branded teams are no longer permitted; members must be individuals, with or without a day-job affiliation. You still get org-sponsored capacity; you do not get a logo as a trust root.

Worked examples

Case 1: Draft the charter as a Nixpkgs issue first

Before creating GitHub objects, write a short public issue that states:

  1. Goal (e.g. “prevent malicious or careless changes from landing on packages we track”).
  2. Scope (exact attribute paths or package sets).
  3. Membership rule (Tweag required commit access so reputation is already established).
  4. Merge rule (review-and-block vs review-and-merge).
  5. Communication (Matrix room, meeting cadence, how reminders work).

That issue becomes the onboarding document. Volunteers join because the work is visible; drive-by requests get a clear “yes, if you already have commit bit” answer.

Case 2: Create the GitHub team and let the tree sync

Committers create the team in the NixOS/Nixpkgs GitHub organisation, add initial members, then rely on the GitHub → Nixpkgs team definition sync so the repository’s team data matches reality. You should not hand-maintain a diverging parallel list in a private wiki.

Checklist:

[ ] GitHub team exists under the NixOS org
[ ] Members are individuals with commit access (if that is your bar)
[ ] In-tree team entry appears after sync
[ ] Relevant packages list the team in meta.maintainers
[ ] Notifications actually fire on a test PR (open a no-op against a tracked package)

Adding the team as maintainer is the boring step people forget. Without it, you have a chat room with a fancy name.

Case 3: Make review load visible

Tweag paired a GitHub project board with a small script that keeps the board current. The point is not the script language; it is that:

  • outsiders can see queue depth,
  • a vacationing reviewer does not strand a PR invisibly,
  • you can measure “250+ PRs in six months” instead of vibes.

Keep the public list of tracked packages next to the board. Keep the private checklist private enough that it is not a free coaching guide for someone trying to sneak a bad postInstall past you.

Case 4: What “success” looked like for Tweag

Between March and September 2026 the team reviewed everything that touched their package set — more than 250 pull requests. They did not claim to have caught malware or a live zero-day. They did catch real mistakes (for example an incorrectly applied patch) and code-quality issues. That is the honest bar for a new team: continuous presence beats heroic incident response.

Case 5: Maintainer metadata shape (sketch)

Exact attribute names evolve; always copy from a nearby package in the tree you are editing. The idea is:

# sketch — follow current nixpkgs conventions for the package you touch
meta = {
  # …
  maintainers = with lib.maintainers; [
    someIndividual
    # teams.<yourTeam>  # when the synced team entry exists
  ];
};

Run the repository’s existing validation (nixpkgs-lint / CI maintainer checks — whatever the current CONTRIBUTING.md points at) rather than inventing a parallel schema. On this authoring host, /workspace/nix-static --version reports nix-static (Nix) 2.35.3; we did not evaluate nixpkgs in-tree here (no channel pin / no sudo). Treat the sketch as orientation, then verify against pkgs/by-name/… on your checkout.

The trap

  1. Branding the team as a company. Policy wants accountable humans. Sponsor the work; do not make the org name the trust root.
  2. Opening membership to everyone on day one without a trust bar. “Anyone can join” is fine after you define how strangers get evaluated. Tweag leaned on existing commit access.
  3. Merging by default because you can. A security-oriented team that also merges creates conflict-of-interest optics. Prefer block-on-problem unless your charter says otherwise.
  4. Publishing the entire checklist. Transparency of queue ≠ transparency of detection heuristics. A little friction against gaming is healthy.
  5. Ignoring volunteer intermittency. Availability fluctuates. Budget gentle reminders and a single facilitator who keeps the board honest — otherwise the team exists only on paper.

The boring rule

Publish a charter issue, create an individual GitHub team, sync it into Nixpkgs, attach it to meta.maintainers for a small package set, and review in public with a board. Block bad changes; do not fetishize merge counts. Rotate people; keep one person responsible for nudging the queue. Re-read Nixpkgs CONTRIBUTING.md and the current teams policy before you invent process.

Try this

  1. Pick three packages you already maintain. Estimate monthly PR volume (GitHub search is:pr path:pkgs/…).
  2. Draft a one-page charter issue (goal, scope, membership, merge posture).
  3. If you have commit access, create a topic team and add yourself; confirm the in-tree sync updates.
  4. Add the team to those three packages’ meta.maintainers on a branch and open a PR that only does that — prove notifications work.
  5. Stand up a project board with columns Incoming / Reviewing / Done and move one real PR through it.

Sources