Running a Nixpkgs team
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:
- Goal (e.g. “prevent malicious or careless changes from landing on packages we track”).
- Scope (exact attribute paths or package sets).
- Membership rule (Tweag required commit access so reputation is already established).
- Merge rule (review-and-block vs review-and-merge).
- 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
- Branding the team as a company. Policy wants accountable humans. Sponsor the work; do not make the org name the trust root.
- 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.
- 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.
- Publishing the entire checklist. Transparency of queue ≠ transparency of detection heuristics. A little friction against gaming is healthy.
- 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
- Pick three packages you already maintain. Estimate monthly PR volume (GitHub search
is:pr path:pkgs/…). - Draft a one-page charter issue (goal, scope, membership, merge posture).
- If you have commit access, create a topic team and add yourself; confirm the in-tree sync updates.
- Add the team to those three packages’
meta.maintainerson a branch and open a PR that only does that — prove notifications work. - Stand up a project board with columns
Incoming / Reviewing / Doneand move one real PR through it.
Sources
- How to set up and run a Nixpkgs team (Aleksandr Bantev / Tweag, 2026-10-08)
- Nixpkgs CONTRIBUTING.md (maintainer and contribution norms)
- Nixpkgs teams / maintainers documentation in-tree (follow current
maintainers/and teams sync docs in the revision you ship against)