Flakes in NixOS
Flakes are tools used to automate development environments. Each flake contains input, output and follow syntax, which is very common in NixOS environments.
The widely used data type in Nix is an attribute set: a data type for storing key-value pairs. It is similar to a JSON object or a hashmap in many languages. Its syntax is confusingly similar to a list of statements in C-like languages:
{
hello = "world";
foo = "bar";
}
The set above is equivalent to this JSON object:
{
"hello": "world",
"foo": "bar"
}
[superuser@valhalla:/my-flake]$ nix develop [superuser@valhalla:/my-flake]$ hello Hello, world!
We have now created a simple flake. These "flakes" can help to automate build environments.
A step further - Create flake that does something
[superuser@valhalla:]$ mkdir basic-flake
[superuser@valhalla:]$ cd basic-flake/
[superuser@valhalla:/basic-flake]$ cat > flake.nix
{
outputs = { self }: { };
}
[superuser@valhalla:/basic-flake]$ nix eval .#foo
We don't have too much use of this flake. Let's extend it with some functionality.
Using inputs and outputs in flakes
[superuser@valhalla:/basic-flake]$ cat flake.nix
{
outputs = { self }: { foo = "bar"; };
}
$ nix eval .#foo
warning: Git tree '/home/superuser/basic-flake' is dirty
"bar"
Flake which uses nixpkgs as input
Your flakes can use packages as outputs. In this case they will be pulled the first time you use the flake. The idea is to provide you with functions and capabilities.
[superuser@valhalla:/basic-flake]$ cat flake.nix
{
inputs = { nixpkgs.url = "github:nixos/nixpkgs"; };
outputs = { self, nixpkgs }: { foo = "bar"; };
}
$ nix eval .#foo
warning: Git tree '/home/galt/da/basic-flake' is dirty
"bar"
[superuser@valhalla:/basic-flake]$ nix build .#hello
warning: Git tree '/home/galt/da/basic-flake' is dirty
evaluating derivation 'git+file:///home/galt/da/basic-flake#hello'
querying hello-2.12.2 on https://cache.nixos.org
[0/1 built, 1/0/1 copied (0.0/0.3 MiB), 0.0/0.1 MiB DL] fetching hello-2.12.2 from https://cache.nixos.org
[superuser@valhalla:/basic-flake]$ hello
Hello, world!
Extend development environment with other packages
Our development environment can contain any package in any version supported by Nix. In this example we will pull cowsay and pingus.
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
wasmProposals = {
url = "github:WebAssembly/proposals";
flake = false;
};
};
outputs = { self, nixpkgs, wasmProposals } :{
packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
devShell.x86_64-linux =
nixpkgs.legacyPackages.x86_64-linux.mkShell {
buildInputs = [
self.packages.x86_64-linux.hello
nixpkgs.legacyPackages.x86_64-linux.cowsay
nixpkgs.legacyPackages.x86_64-linux.pingus
]; };
};
}
[superuser@valhalla:/basic-flake]$
Entering development environment with flakes
In order to "enter" the development environment with flakes, execute:
$ nix develop -c $shell warning: Git tree '/home/superuser/da/basic-flake' is dirty evaluating derivation 'git+file:///home/galt/da/basic-flake#devShells.x86_64-linux.default' evaluating derivation 'github:nixos/nixpkgs/02fb5aea5577e0c957abb8759a75deb37106cea9?narHash=sha256-TKbKISE2crHAukW ... lots of other messages, downloading packages ...
From there, we can test that our packages were installed correctly:
\[\][\[\]superuser@valhalla:/basic-flake]$\[\] fortune 2>&1 | cowsay
____________________________
< fortune: command not found >
----------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
\[\][\[\]superuser@valhalla:/basic-flake]$\[\] pingus

\[\][\[\]superuser@valhalla:/basic-flake]$\[\] exit
But what we currently have is issues with is automatically pulling git repos from our flakes. If you know how to do it, please let me know. I am welw #dflund. The best I have is something like this, and it does not work:
[superuser@valhalla:/basic-flake]$ cat flake.nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
wasmProposals = {
url = "github:WebAssembly/proposals";
flake = false;
};
# wasm-repo = {
# type = "github";
# owner = "WebAssembly";
# repo = "proposals";
# ref = "main";
#};
};
outputs = { self, nixpkgs, wasmProposals } :{
packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
devShell.x86_64-linux =
nixpkgs.legacyPackages.x86_64-linux.mkShell {
buildInputs = [
self.packages.x86_64-linux.hello
nixpkgs.legacyPackages.x86_64-linux.cowsay
nixpkgs.legacyPackages.x86_64-linux.pingus
]; };
};
}
Summary
Our flake looks as following:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
wasm-repo = {
type = "github";
owner = "WebAssembly";
repo = "proposals";
ref = "main";
};
};
outputs = { self, nixpkgs } :{
packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
devShell.x86_64-linux =
nixpkgs.legacyPackages.x86_64-linux.mkShell {
buildInputs = [
self.packages.x86_64-linux.hello
nixpkgs.legacyPackages.x86_64-linux.cowsay
nixpkgs.legacyPackages.x86_64-linux.pingus
]; };
};
}
What we've done is:
- Created a flake.nix file with a simple structure.
- Added a simple package:
- Modified the flake.nix file to include a package (hello).
- Used nix eval to check the package.
- Ran hello to verify it works.
Extended the development environment:
- Modified the flake.nix file to include a development shell with additional packages (cowsay and pingus).
- Used nix develop to enter the development environment.
- Ran commands inside the environment to verify the packages work.