2023-05-18 - Learning Journey Working Group - Meeting Notes #9


  • @06kellyjac introduces themselves.
  • @zmitchell a question was asked on the discourse what was the purpose and what was supposed to be learned from the nix documentation efforts - i.e. what are the learning goals that should be achieved
    • we want to have this as a living document
    • we might return to this point (keeping track of these learning goals)
  • @zmitchell - we want to chunk and sequence the nix learning journey
    • we’re going through previous meeting notes to get to the point we arrived to in last meeting
    • dependencies should be the next piece of learning introduced
    • getting flask and something in addition
    • add these to your environment
    • shell.nix?
    • build inputs?
    • it’s important to consider python path in this context
  • buildpythonapplication
    • if we only use flask add it to build inputs
    • if you need more than that, it gets trickier - because also needed on python path - hence need for buildpythonapplication
    • previous step shell.nix - we spoke about buildpython application or not for this step
    • at some point, we will need to address this topic (build python application)
    • @06kellyjac python has a special property/feature - withenv command?
      • pyEnv = pkgs.python.withPackages(ps: [ ps.mininet-python ]);
    • (someone mentions poetry2nix)
    • @zmitchell we’re sticking to nixpkgs, to try to stay away from third party tools - as we are becoming a more formal documentation source - and less opinionated.
    • @zmitchell they might bring an already existing py project - and that will influence the way that they choose to build it - i.e. if they were already using poetry, pip, or pipenv
    • coverage in nixpkgs - things that have been installed outside - might still be - @06kellyjac this is something to warn against - so that you don’t believe that you have a working insulated solution - when you actually are partly running on the global system python.
    • @kellyjac there is an argument for enabling the user to do whatever they need to do.
      • @zmitchell - if we need to make such shortcuts, make them as good as possible - global install would be one of the worst options
      • @khaled this is sometimes mentioned in the community as “turning off the sandbox”
      • @zmitchell - what we’re aiming at is something that doesn’t pick up globally installed packages
    • @zmitchell needing additional packages to flask, we need to go to buildpythonapplication
      • we’re looking at nix example from last meeting
  • @zmitchell - looking at different build input types
    • @zmitchell - tell me if this is correct
      • propagated build inputs - needed at build and runtime
      • build inputs - needed at runtime
      • native build inputs - needed at build
    • @06kellyjac
      • build inputs - needed by built package
      • native build inputs - needed at build time
      • propagated build inputs - needed by built package and included in output?
    • @06kellyjac - need to look at the details how the python path works and with the wrapping
    • @zmitchell - tricky nix thing we want to teach - there is a difference between these build input types
  • @06kellyjac python situation is one of the more difficult within nix - specific version that you need and pin to
    • you may be using requirements.txt - and this feeds into what needs to happen nix wise
    • add hooks for testing
    • including dependencies - directly from your python.packages - or python.packages.corepackage? so you can get dependencies in arguments???
    • easy example - basic c program?
    • we can then easier add to the shell - to make the build dependencies included
    • @zmitchell - we need to show these rough edges - people say they struggle with the language, but they actually struggle more in general with the ecosystem and how things are set up.
    • @zmitchell we intentionally chose python - with its rough edges.
  • @06kellyjac use a few of these input types as possible - use something with only propagated build inputs?
    • @jeremiah - by hiding the difficult side of it, we may do the users a disservice - we should probably mention that they exist at least. After the python learning journey, we can template it and do it for other languages - Rust and others?
    • @zmitchell - we want one learning journey
    • @zmitchell - as 06kellyjac said, we can introduce the buildinputs one after the other.
    • @zmitchell - as a beginner - wanted to create an environment that had specific things at runtime and build time - got a reply that fleshed out with type of inputs should be used where - but it was hard to digest as a beginner.
    • @zmitchell - “these are propagated build inputs - you don’t need to know right now - but we will teach you later”
  • @zmitchell - can we introduce a linter or something similar? - only needed at build time
    • @06kellyjac - yes - they will go in native build inputs
    • many scenarios exists where you need to know the difference between the inputs - but we will try to avoid that in this tutorial
  • buildpythonapplication command will be introduced
    • @zmitchell - this sounds like a managable amount of complexity
  • @Jeremiah - shall it be copy paste, or should a specific repository be set up?
    • @Jeremiah - the may be ways to segment the existing repo instead of making a new one
    • @Jeremiah - one repo as a collection of all needed assets (to be cloned)
    • @zmitchell - dealing with keeping a clean commit history for teaching purposes is unsustainable over time
  • @zmitchell - end goal building with testing and nixos - what comes next?
  • @zmitchell - we need to teach pinning nixpkgs - and for that - you need to understand nixpkgs
    • making builds reproducible - and select your architecture
    • that will define things all the way down to paths
    • this is powerful and should be shown to people
  • @Jeremiah - subtutorial - how granular can nix get on pinning - from branches to commit hashes
  • @zmitchell - discuss and explain different levels of purity
    • <nixpkgs>
    • from channel - say 22.11 - not reproducible - because channel evolves
    • pinning to commit hash - maximal granularity
  • @zmitchell adding packages or pinning - which one comes first?
  • @06kellyjac teach pinning as soon as possible - gives better guarantee that things will work
    • pinning is relatively simple to understand - in comparison to other python topics
    • @zmitchell- pinning - and then adding flask - and get it running
    • @zmitchell - next - add derivation?
    • @zmitchell we will have shell and derivation using build python application - and would essentially be the same
      • using mkshell - no flask on your python path - therefore it’s not a good way to go
  • @khaled showing unified build and shell from @infinisil
    • @06kellyjac - two options regarding the flask integration
    • @06kellyjac - shall we postpone until @infinisil joins?
    • @Jeremiah - store inputs and propagated build inputs?
    • @06kellyjac - then we could reuse and wouldn’t need two - transfer logic from shell.nix to default.nix, and make shell.nix depend on default.nix
    • @zmitchell - first instance - duplicate what needs to be duplicated - optimise files for readability and understandability - to get something building
    • @zmitchell - later tutorial - optimise our nix code to not repeat itself
  • @zmitchell - going forward - we need a nix expert in the room to make progress on this - and this will become more the norm going forward as we are onboarding people with these skills

Thanks everyone for pulling these issues apart, it sure reads like you’re doing hard work.

Please excuse me if the following sounds overly contrarian; I’m not trying to throw wrenches in the machine but rather explore different approaches to ensure we make progress:

In the past I had discussions with many people on whether to take a top-down or bottom-up approach to teaching Nix. Proponents of top-down usually insist that beginners don’t want to care how it works but just want to use it. Bottom-up is the long, arduous path to success, and since learning has a cost we’d be losing a lot of audience if we didn’t offer top-down paths. Also of course we‘d ideally offer both, but due to resource constraints one would have to focus on one thing first.

I always leaned towards bottom-up because that’s what worked well for me and others I know (opponents argued that there are different learning types, and not everything works for everyone), but more importantly because surface-level interfaces, documentation, and learning content were of little help, and at the very least extremely confusing and scattered.

Last year I essentially gave in to the top-downers for the sake of making any progress at all, despite still being convinced that in order to teach interfaces effectively we first have to get them at least somewhat consistent and document them properly at the reference level. Now the discussions of the past week reinforce my impression that attacking the mess from the outside may indeed be a fool’s errand.


  • There are too many moving parts and too many of them are arbitrary historical accidents. This makes it harder to actually teach anything at all without leaving gaps all over the place and thus risking learners to build the wrong mental models. That would do users a disservice.
  • Core concepts (such as packages in Nixpkgs or modules in NixOS) are still not entirely understood and therefore in flux, leaving interfaces a moving target. Teaching superficial features won’t age well, and we can’t afford sustained maintenance of that kind. We should teach things that are sure to stick around, for mere efficiency reasons.
  • Many features that are in evident demand (such as Python packaging) are not fully established or not well-executed upstream, and users have to develop the ability to navigate and judge the quality of competing community efforts. This is simply not possible with superficial knowledge, and tiring enough even with some expertise, and in my opinion the reason why users feel like beginners for such a long time.
  • On the other hand, building up concepts from first principles would help grow a community of empowered contributing users (who we expect to be software developers to begin with), who are more likely to help implementing sound designs we would eventually be able to teach to “purely consuming” users efficiently.

It’s all about messaging and setting expectations though. I was insisting on telling people up front that using Nix effectively requires a serious time investment and that there is nothing we can do about it with the given resources in the foreseeable future. I don’t think there is anything wrong with being honest about it. And I’m convinced there is a reasonable and much more obvious way of teaching that stuff than pretending any of this is somehow suitable to any kind of end user. (@ianthehenry aptly summarised: It’s impossible to use Nix without knowing how it works.)

I got shot down a lot for this stance. Maybe that’s because some prefer to sustain their phantasies about what Nix could or should be. Maybe that is worth reconsidering. We talked at length about first making reference documentation nice, complete, and maintainable. But reams of manual pages are near worthless without an overview, without guidance on how to make sense of all that.

What do you think about shifting focus on teaching Nix from first principles? Please try to override the sunk cost fallacy in your judgment (maybe it helps to remember that I’ve been at it for more than a year for most of my waking hours, so tell me about sunk cost).

I’m particularly interested in what @zmitchell @roberth @maj @infinisil @ericson2314 have to say.


I am inclined to agree with @fricklerhandwerk, and perhaps go even further.

I believe trying to write good tutorials before we have good reference documentation is highly inefficient. Learning materials are, by their nature, linear/single-threaded, narrative, opinionated, contentious, etc. It is hard to decide what to do, and it is hard to subdivide the work among multiple people because the narrative structure requires such tight integration and unified vision.

Reference docs on the other hand are totally the opposite. They support random access, and are dry, unopinionated, uncontenious, etc. This makes divvying up the work very easy.

For example, see my Expanding tests and docs relating to deleting profiles by Ericson2314 · Pull Request #8351 · NixOS/nix · GitHub. There is basically one contentious bit here — is some behavior so unstable that it is dangerous to document it at all? — everything else is quite cut and dry. The only interaction between sections is hyperlinking, but we can do that post-hoc, or use the glossary to support outgoing links to material that has yet to be written.

That PR covers just two of dozens of commands. It should be easy to get a bunch off people to work on more such PRs in parallel. Yes, you have to read the code to double check what exactly things do — or at least I did :slight_smile: — but that shouldn’t be too hard.

I have not been involved with the docs team except for shadowing a meeting or two, and I haven’t been to a learning journey working group meeting at all. So take the above with a big fistful off salt — it is based on the theory of the task at hand, not first-hand experience with the groups of people actually tackling it.

Also I know most contributors or would-be contributors are much more excited about and motivated by tutorial and educational material. So sure, by all means start with what you love. But if anyone feels stuck, or the leaders feel like they have more volunteers than they know what to do with, I urge reallocating person-time to reference documentation efforts.

And with the references docs overhauled, the educational material will have a much sturdier foundation upon which to be a glorious shiny building.


I obviously have opinions on this.

My feeling is that focusing primarily on reference materials is unlikely to move the needle. I see technical reference materials as building blocks. Building blocks are incredibly important, but they’re also nearly useless as a beginner without someone showing you how to put them together. For example, if you don’t yet know how to put together a website, the MDN reference of HTML elements is unlikely to be useful to you. I toyed around with Clojure in the recent past and that ecosystem suffers from a similar problem of having plenty of building blocks available, but not much in the way of people taking you by the hand to show you how to put them together. In my mind this is why there’s such a proliferation of “let me teach you Nix” blog series.

I’m not entirely sure I agree with the framing of top-down or bottom-up because I don’t think either term is well-defined in this context.

I took a step back and looked at the Rust Book, which I think does a pretty good job teaching Rust and is generally regarded as pretty good. Let’s look at the approach that it takes:

  • There’s a clear progression from “easy” to “hard” e.g. from data types up to multi-threaded web server.
  • From the very beginning you’re writing working programs even without knowing all the details of the language.
  • Most chapters rely on knowledge from previous chapters, but not on particulars of previous chapters (e.g. you aren’t building up the same project over time).
  • Each page typically builds one or more small programs, so the user is always doing something and they see aspects of the language over and over again.
  • Earlier chapters link to later chapters if a topic is mentioned before it’s entirely explained.

There are some aspects of that approach that look like what we’re doing in the WG, but there are other things that are different. Figuring out how to approach this is why we hired people to help, so I’m interested to hear their input.

With regards to interfaces moving around or having superficial knowledge, clearly people are able to get work done with Nix today, so the interfaces are concrete enough to build projects/products on top of. I don’t exactly know where Nix lands on the stability spectrum with Java 8 on one end and Javascript front end frameworks on the other end, but my gut says that there’s enough stability that we can teach and get readers to being productive.


I did this recent Nix Shorts update from the perspective of: “how to use Nix while minimally understanding how any of it works”. I think it goes a long way for the average developer.

But yes, the next step from this point on for me (and if I manage to write it up) is to figure out how to cross the chasm between:

  • Having a trivial flake to do a develop/build
  • Having to do something mildly complicated/non-standard using third party Nix code

The gap between these two locations is vast and it is not clear to me yet how to cross it.


@fricklerhandwerk what would be a guide that should be part of the learning journey that would suit your bottom up preference? And how would it be incompatible with the currently proposed/developed outline?

I tend to think that bottom up guides would accompany reference documentation. Whereas the learning journey is simply a separate aspect of documentation.

@zmitchell I don’t dispute the benefit of the learning journey work. Rather my point is about costs: even if the reference work is less valuable, it’s so much easier to produce especially with many people working simultaneously. I just want to make sure it’s not neglected because most volunteers want to work on learning journey material.

Hosted by Flying Circus.