Add more Nix/Flake examples (and accompanying notes files)

This commit is contained in:
Hassan Abedi 2026-04-23 11:10:17 +02:00
parent 4177cdb552
commit 52aea18780
14 changed files with 520 additions and 0 deletions

21
13-overlay/README.md Normal file
View File

@ -0,0 +1,21 @@
# 13-overlay
This example shows a small flake overlay.
It includes:
- `overlays.default`,
- one package added by the overlay,
- a package output that imports `nixpkgs` with that overlay, and
- a check run by `nix flake check`.
Useful commands:
```bash
nix build
./result/bin/hello-overlay
nix run
nix flake check
nix flake show
```

27
13-overlay/flake.lock generated Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

48
13-overlay/flake.nix Normal file
View File

@ -0,0 +1,48 @@
{
# Exposes an overlay that adds one package, then imports nixpkgs with that
# overlay so the package is available through normal flake outputs.
description = "A minimal overlay example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ self, nixpkgs, ... }:
let
system = "x86_64-linux";
overlay = _: prev: {
hello-overlay = prev.writeShellScriptBin "hello-overlay" ''
echo "hello from an overlay"
'';
};
pkgs = import nixpkgs {
inherit system;
overlays = [ overlay ];
};
in
{
overlays.default = overlay;
packages.${system}.default = pkgs.hello-overlay;
apps.${system}.default = {
type = "app";
program = "${self.packages.${system}.default}/bin/hello-overlay";
meta.description = "Run the package added by the overlay.";
};
checks.${system}.runs = pkgs.runCommand "hello-overlay-runs" { } ''
output="$(${self.packages.${system}.default}/bin/hello-overlay)"
if [ "$output" = "hello from an overlay" ]; then
echo ok > "$out"
else
echo "unexpected output: $output" >&2
exit 1
fi
'';
};
}

17
14-template/README.md Normal file
View File

@ -0,0 +1,17 @@
# 14-template
This example shows a small `templates.default` output.
It includes:
- one reusable flake template under `template/`,
- a description shown by `nix flake show`, and
- a check that verifies the template files contain the expected scaffold.
Useful commands:
```bash
nix flake show
nix flake init -t .#default
nix flake check
```

27
14-template/flake.lock generated Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

31
14-template/flake.nix Normal file
View File

@ -0,0 +1,31 @@
{
# Exposes one flake template that scaffolds a tiny dev-shell-based flake.
description = "A minimal flake template example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
in
{
templates.default = {
path = ./template;
description = "Scaffold a tiny flake with one dev shell.";
};
checks.${system}.template-files = pkgs.runCommand "template-files-check" { } ''
cp ${./template/flake.nix} ./flake.nix
cp ${./template/README.md} ./README.md
grep -q 'devShells\..*default' ./flake.nix
grep -q 'nix develop' ./README.md
echo ok > "$out"
'';
};
}

View File

@ -0,0 +1,9 @@
# Template Output
This scaffold gives you a tiny flake with one dev shell.
Try:
```bash
nix develop
```

View File

@ -0,0 +1,19 @@
{
description = "A tiny flake scaffolded from 14-template";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
in
{
devShells.${system}.default = pkgs.mkShell {
packages = [ pkgs.jq ];
};
};
}

View File

@ -0,0 +1,21 @@
# 15-follows-and-inputs
This example shows multiple flake inputs and one `follows` relationship.
It includes:
- a top-level `systems` input,
- `flake-utils` configured to reuse that input with `follows`,
- a small package and app output, and
- a check run by `nix flake check`.
Useful commands:
```bash
nix flake metadata
nix flake show
nix build
./result/bin/show-follows
nix run
nix flake check
```

64
15-follows-and-inputs/flake.lock generated Normal file
View File

@ -0,0 +1,64 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1776548001,
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@ -0,0 +1,52 @@
{
# Shows multiple flake inputs plus a `follows` edge that makes one
# transitive input reuse a top-level input from this flake.
description = "A minimal follows and inputs example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
systems.url = "github:nix-systems/default";
flake-utils = {
url = "github:numtide/flake-utils";
inputs.systems.follows = "systems";
};
};
outputs =
{
self,
nixpkgs,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
in
{
packages.default = pkgs.writeShellScriptBin "show-follows" ''
echo "flake-utils is sharing the top-level systems input"
'';
apps.default = {
type = "app";
program = "${self.packages.${system}.default}/bin/show-follows";
meta.description = "Run the package built in the follows example.";
};
checks.runs = pkgs.runCommand "show-follows-runs" { } ''
output="$(${self.packages.${system}.default}/bin/show-follows)"
if [ "$output" = "flake-utils is sharing the top-level systems input" ]; then
echo ok > "$out"
else
echo "unexpected output: $output" >&2
exit 1
fi
'';
}
);
}

81
notes/016-overlays.md Normal file
View File

@ -0,0 +1,81 @@
# Overlays
This note covers `13-overlay/`, which defines `overlays.default` and then imports `nixpkgs` with that overlay to expose the overlaid package as a normal flake output.
---
## 1. What an Overlay Is
An overlay is a function:
```nix
final: prev: {
...
}
```
It receives:
- `prev`: the package set before your changes, and
- `final`: the package set after all overlays are applied.
The result is an attrset of additions or overrides.
This example writes the first argument as `_` because it only needs `prev`:
```nix
overlay = _: prev: {
...
};
```
---
## 2. The Smallest Useful Pattern
This example adds one package:
```nix
overlay = _: prev: {
hello-overlay = prev.writeShellScriptBin "hello-overlay" ''
echo "hello from an overlay"
'';
};
```
Then it imports `nixpkgs` with that overlay:
```nix
pkgs = import nixpkgs {
inherit system;
overlays = [ overlay ];
};
```
That is the key mechanic. The overlay itself is just a function. It does nothing until you import a package set with it.
---
## 3. Why the Flake Exposes Both
The example exposes:
- `overlays.default`, so other flakes can reuse the overlay, and
- `packages.<system>.default`, so the same flake is easy to build and run locally.
That makes the example useful both as a teaching flake and as a reusable overlay source.
---
## 4. Commands to Try
```bash
cd 13-overlay
nix build
./result/bin/hello-overlay
nix run
nix flake show
nix flake check
```

46
notes/017-templates.md Normal file
View File

@ -0,0 +1,46 @@
# Templates
This note covers `14-template/`, which exposes `templates.default` so `nix flake init -t` can scaffold a new flake from files in the repository.
---
## 1. What a Template Output Is
A template output is metadata plus a path:
```nix
templates.default = {
path = ./template;
description = "Scaffold a tiny flake with one dev shell.";
};
```
The `path` points at the directory that should be copied into the new project. The `description` is what users see in `nix flake show`.
---
## 2. Why the Template Lives in Its Own Directory
The template is just ordinary files. In this example, `template/` contains:
- a small `flake.nix`, and
- a short `README.md`.
That separation matters because the example flake and the template flake are doing different jobs:
- `14-template/flake.nix` publishes the template, and
- `14-template/template/flake.nix` is the scaffold that gets copied into a new directory.
---
## 3. Commands to Try
```bash
cd 14-template
nix flake show
mkdir /tmp/template-demo
cd /tmp/template-demo
nix flake init -t /path/to/nix-playground/14-template#default
```

View File

@ -0,0 +1,57 @@
# Follows and Inputs
This note covers `15-follows-and-inputs/`, which defines multiple inputs and uses `follows` so one transitive input is reused instead of resolved separately.
---
## 1. What `follows` Does
`follows` points one input at another input by name:
```nix
flake-utils = {
url = "github:numtide/flake-utils";
inputs.systems.follows = "systems";
};
```
That means `flake-utils` does not resolve its own separate `systems` input. It reuses the top-level `systems` input from this flake.
---
## 2. Why This Matters
Without `follows`, transitive dependencies can drift apart. Two flakes may each resolve their own copy of an input, even though you wanted them to share one.
This example keeps the case small:
- one top-level `systems` input,
- one dependent flake, `flake-utils`, and
- one `follows` edge that ties them together.
That makes it easy to inspect with `nix flake metadata`.
---
## 3. Why the Example Still Builds Something
The flake uses `flake-utils.lib.eachDefaultSystem` so the dependency is not just declared, but actually used. The package itself stays trivial because the point of the example is the input graph, not the package.
If you want to compare output-generation styles, see `03-multi-system/`. This example is about input wiring.
---
## 4. Commands to Try
```bash
cd 15-follows-and-inputs
nix flake metadata
nix flake show
nix build
./result/bin/show-follows
nix run
nix flake check
```