{
"$type": "site.standard.document",
"canonicalUrl": "https://isabelroses.com/blog/im-not-mad-im-disappointed",
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreicykesryblbukjczcpawxauf5zu2xoungdyupmxzhrjbpmmi2c3vi"
},
"mimeType": "image/png",
"size": 10397
},
"description": "A short rant about the state of your nix code",
"path": "/blog/im-not-mad-im-disappointed",
"publishedAt": "2025-01-09T00:00:00.000Z",
"site": "at://did:plc:qxichs7jsycphrsmbujwqbfb/site.standard.publication/3mn5hmwkcmb22",
"tags": [
"nix"
],
"textContent": "Introduction\n\nWhen I see another friend of mine start using nix my eyes glisten with the\nknowledge there is still hope for their lost soul yet. But then I observe their\ncopy-pasted code and see all the bad practices everywhere. _Sighhhh_. Time to\nexplain to you everything wrong about what you're doing in your nix code. Make\nsure to pay attention and make some notes because I don't want to explain it\nagain.\n\nsystem and lib.nixosSystem\n\nOften I see people passing the system argument to lib.nixosSystem. However,\nyou should not do this! This is because \"legacy input\" and will straight up be\nignored because of your autogenerated hardware-configuration.nix file, which\nwill set system for you. So to rectify this we can instead set\nnixpkgs.hostPlatform to the desired system.\n\nFor further reading about this topic please consult\nnixpkgs@332e603/flake.nix#L54.\n\nTo such I am usually asked \"But I want to be able to track other nixpkgs\nrevisions or inputs, then don't I have to? Or set a specialArg or something?\".\nNO! Almost never do you want to use specialArgs. specialArgs are great but\noften overused for things that the module system was designed to do better. Now\nto answer the main question, you can still do that. Allow me to introduce you\nto pkgs.stdenv.hostPlatform.system and its alias pkgs.system. So now we can\ndo something more like the following:\n\nOverall, system being an input to lib.nixosSystem was so irritating me so\nmuch that I made several bluesky posts complaining about it. And went on to\nmake easy-hosts as an abstraction\naround making systems for your systems that will prevent you from making these\nmistakes, and will force you to use the module system more.\n\nsystem dependent overlays\n\nI sadly am not kidding. These are real. I have seen people do this.\n\nFirst off, overlays should not be consumed with a system like\noverlays.x86_64-linux or overlays.x86_64-linux.default. Please stop\nyourself if you ever get here. Instead, overlays should be consumed like\nsource.overlays.name, to improve upon this consider the following template:\n\nNotice how here I used prev instead of pkgs or anything alike because we do\nnot need to know what the system is here. And if you do wish to refer to the\nsystem recall how earlier I spoke of pkgs.system well prev like pkgs will\nalso expose system, so you can use prev.system.\n\nStop importing weirdly\n\nYou do not need this needless import. This is a waste of nix eval time. Since\nusers will place inputs.<source>.nixosModules.default in their flake\nimports it will load those files for them, so you don't need to import unless\nyou need to pass args.\n\nHere is a more acceptable flake, where we only import because we are passing\nour inputs to our other module.\n\nStop importing nixpkgs\n\nThis one is somewhat of a subset of the previous problem, where people import\nneedlessly. nixpkgs already provides legacyPackages which is a\npre-constructed set of packages for you. So you don't need to import nixpkgs.\n\nImporting nixpkgs without a system will use builtins.currentSystem which is\nimpure, this means that it needs to use information that may not be\nreproducible like your system type. Instead, consider writing:\n\nYou may also recall my earlier posts titled Experimenting with\nnix and or Dev\ndependencies, where I refer to a\nfunction called forAllSystems to improve upon this pattern further. For the\nsake of completion I will bring one of those examples back and use it to\ngenerate the system based outputs of packages.\n\nYou may however have noticed this won't work if you need to access unfree or\nbroken packages. In which case I would recommend modifying the function to\nalign with the following:\n\nThe key difference in the above example is that we now are importing nixpkgs\nand as such we now have access to nixpkgs.config and nixpkgs.overlays if\nyou so wish to use those.\n\nThis brings me onto my final point,\n\nStop using flake-utils\n\nflake-utils is often an extra dependency added for no good reason. The main\npurpose for using it more modernly is its overridable systems, they do this\nthrough an input from the nix-systems GitHub\norg. But more typically no one uses it for that, in fact most people use\nflake-utils for its ability to create system dependent outputs. This is what\nleads to the issues with system dependent overlays. But recall, I've\nalready covered all of what you need to make your own flake-utils, through the\nusage of the forAllSystems function.\n\nHowever, some of you may still want those overridable systems. In which case\nplease consider writing this flake like this instead:\n\nConclusion\n\nI was never mad at you, I was just disappointed. But now you know better, so go\nforth and write better nix code.",
"title": "I'm not mad, I'm disappointed",
"updatedAt": "2025-02-07T00:00:00.000Z"
}