{
"$type": "site.standard.document",
"canonicalUrl": "https://isabelroses.com/blog/nix-shells",
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreia5lbwmw73vbygn7nhdkyxyuyze76rqtaxbs4e57bxn6s3qzt4oma"
},
"mimeType": "image/png",
"size": 9454
},
"description": "Nix is truly an enlightening experience",
"path": "/blog/nix-shells",
"publishedAt": "2024-06-07T00:00:00.000Z",
"site": "at://did:plc:qxichs7jsycphrsmbujwqbfb/site.standard.publication/3mn5hmwkcmb22",
"tags": [
"nix"
],
"textContent": "Introduction\n\nHandling dependencies is hard to say the least. Issue after issue of missing and conflicting dependencies. And no good way to fix this util ~~Docker~~ Nix came along. This blog post will go over the start to end of getting a solid nix dev entiroment setup for all your projects.\n\nGetting started\n\nFirst we are going to create a basic file tree, such that you can understand how your system may look like.\n\nAt first when seeing this tree you may think why are we polluting our root directory with all these files. But in this is a good way to help us write less Nix!\n\nNow, we're going to create a flake.nix file. Unlike some other files mentioned later in this post, it's quite agnostic about the language of your project. Since I won't be explaining this part in detail, I recommend you read my previous blog post experimenting with nix.\n\nNow we have something more useable for our flake.nix file we can now start making our default.nix file and shell.nix files.\n\nWe are going to start with the default.nix file for a basic Rust project. We start with the default.nix file to identify the dependencies of our project, which is particularly easy to do with Nix since the build system is isolated.\n\nYou may have noticed buildInputs and nativeBuildInputs, which contain the dependencies of the project. At a basic level buildInputs are the dependencies that are needed at runtime whilst nativeBuildInputs are the dependencies that are only needed during the build process. So why does that matter?\n\nWell these dependencies can be reused in our shell.nix file, we can do this like so:\n\nIn this example we are adding additional Rust tooling to our shell. This is because those inputs are not there in our dependencies that we have defined in our default.nix file.\n\nBut what if I don't want to have default.nix file?\n\nNix still has a solution for this — pkgs.mkShell.\n\nWhat if you also require all the dependencies of another program? I've personally never needed this, but you can do it like so:\n\nNow you have a shell with all the dependencies of rust-analyzer and any other dependencies you have defined in your shell.nix file.\n\nSome common misconceptions\n\nShould I use nativeBuildInputs or buildInputs?\n\nWell in this case it doesn't matter! All packages that are put into the mkShell will be merged into one attribute, and will all be available to the end user. So really the best thing to do here is use packages since it's documented and therefore a good practice.\n\nIf you would like proof they get merged into the one attribute here is the source:\n\nHow about the environment variables?\n\nI see a number of people using shellHook, but I'd argue that this is wrong — ideally we should use env. But not for any technical reason, since they fundamentally do the same thing and env is converted into a shellHook, but rather for readability.\n\n1. The worst way:\n\n2. A bit better:\n\n3. The best way:\n\nAfter reading all three of these example, I hope you understand why I personally prefer the third example. Since its clear that its exporting environment variables, and it's also clear what the environment variables are or will be. It should also be noted that as of release 24.05 the recommended manor of exporting environment variables in a shell is example 2, but uses mixes between example 1 and 2.\n\nBut you didn't mention pkgs.mkShellNoCC?\n\nThe difference between difference these two is that mkShell includes a C compiler in the shell environment, whilst mkShellNoCC does not. So in a situation where you know you won't need any C compiler or related technogies its better to use pkgs.mkShellNoCC.\n\nHow about using my overlay?\n\nMy personal favorite has to be oxalica/rust-overlay, so that is what we are going to use in this example. I heavily advice mainly using the flake to get reproducible outputs.\n\nBut you didn't include a shell.nix that time? I know thats because I want to keep this as reproducible as possible and that beacomes difficult with overlays and staying backwards compatible. The below example shows how you could do this though its not exactly pretty.\n\nThe cherry on top\n\ndirenv\n\nnix-direnv is a tool that allows you to have a .envrc file in your project that will automatically load the nix shell when you enter the directory. This is a great way to make sure that you are always in the correct environment.\n\nThe files from before will not change but now the .envrc file will be added to the project, and this will contain something like so:\n\nTemplates\n\nNix allows you to create reproducible templates for your project, so you only have to set these up one time and then you can reuse them for all your projects.\n\nFor example you can use my templates like so nix flake init -t github:tgirlcloud/nix-templates#go which will create a new go project in your current directory, or you can use nix flake new -t github:tgirlcloud/nix-templates#rust cheese which will create a new directory called cheese with the rust template defined here.\n\nHere we will create a quick example for a basic flake, but you can do this with littrally anything you want.\n\nFirst lets define what our tree will look like as we did before:\n\nNow lets define our flake.nix:\n\nYou may have notice that we are not taking any inputs and are only producing outputs and thats because we don't need a package set here. Then our comfy/* files will look like the ones we defined at the beginning of this post.\n\nWrapping up\n\nNix is a great tool for managing dependencies, and I hope this post has helped you understand how to use it in your projects. If you have any further questions feel free to email me. Thanks for reading!!! And If you really enjoyed the post please consider donating so I can keep doing this kind of thing on kofi or GitHub Sponsors.",
"title": "Dev dependencies",
"updatedAt": "2025-08-05T00:00:00.000Z"
}