{"title":"NixOS Flakes","url":"https://seanbehan.ca/posts/nixos","description":"What a flake actually is: inputs, outputs, and a NixOS configuration with every dependency pinned.","author":"Sean Behan","published":"2024-06-01T22:38:41.000Z","updated":null,"draft":false,"tags":["nixos"],"readingMinutes":2,"image":null,"sections":[{"id":"introduction-to-flakes","text":"Introduction to Flakes","level":2},{"id":"flake-structure","text":"Flake Structure","level":2},{"id":"managing-dependencies-with-flakelock","text":"Managing Dependencies with flake.lock","level":2},{"id":"development-shells-devshell","text":"Development Shells (devShell)","level":2},{"id":"building-packages-with-flakes","text":"Building Packages with Flakes","level":2}],"content_format":"text/markdown","content_url":"https://seanbehan.ca/posts/nixos.md","content":"### Introduction to Flakes\n\nFlakes in NixOS allow you to write Nix code that has custom inputs and outputs.\n\nFor example this is a simple example of a Flake. You can get a copy for\n\nyourself by running `nix flake init`.\n\n```nix\n{\n  description = \"A very basic flake\";\n\n  inputs = {\n    nixpkgs.url = \"github:nixos/nixpkgs?ref=nixos-unstable\";\n  };\n\n  outputs = { self, nixpkgs }: {\n\n    packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;\n\n    packages.x86_64-linux.default = self.packages.x86_64-linux.hello;\n\n  };\n}\n```\n\n### Flake Structure\n\nAs you can see there are inputs (nixpkgs), and outputs (self, nixpkgs).\n\n### Managing Dependencies with flake.lock\n\nIf you build this Flake using `nix build` you'll end up with a new directory\n\ncalled `result` which is a symlink to where the package was built in your Nix\n\nstore.\n\n```shell\nresult -> /nix/store/yh6x9ia5kxxw3w90vkb09vqgfvhb416k-hello-2.12.1\n```\n\nYou'll also end up with a `flake.lock`. If you've used `npm` before\n\n`flake.lock` is very similar to `package-lock.json`. If you haven't, a quick\n\nexplanation is that it keeps track of package versions and keeps them locked\n\nbetween updates. If you want to update your lockfile so you can get a newer\n\npackage version you can do so with `nix flake update`\n\nNow so far I've only showed a very basic example of a Flake, the example from\n\n`nix flake init`. You can see more templates with `nix flake show templates`.\n\n### Development Shells (devShell)\n\nOne thing I like using Flakes for is to create a `devShell`. You can initialize\n\na Flake with a `devShell` preconfigured with `nix flake init -t\n\ntemplates#utils-generic`\n\n```nix\n{\n  inputs = {\n    utils.url = \"github:numtide/flake-utils\";\n  };\n  outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system:\n    let\n      pkgs = nixpkgs.legacyPackages.${system};\n    in\n    {\n      devShell = pkgs.mkShell {\n        buildInputs = with pkgs; [\n        ];\n      };\n    }\n  );\n}\n```\n\nIn this example you can add packages from nixpkgs to `buildInputs` for them to\n\nbe installed temporarily. You can activate it with `nix develop`. This is the\n\n`devShell` I use for my typescript projects.\n\n```nix\n# ...\n      devShell = pkgs.mkShell {\n        buildInputs = with pkgs; [\n          efm-langserver\n          nil\n          nodePackages_latest.nodejs\n          nodePackages_latest.typescript-language-server\n          nodePackages_latest.prettier\n          vscode-langservers-extracted\n          nodePackages_latest.bash-language-server\n        ];\n      };\n# ...\n```\n\n### Building Packages with Flakes\n\nYou can use Flakes to build packages as well. You can look at just about any\n\nNix package for an example. Just choose one in\n\n[nixpkgs](https://github.com/nixos/nixpkgs). Flakes have many functions to\n\nbuild different types of packages as you can see in nixpkgs.\n"}