Add two more Nix/Flake examples (with their note files)

This commit is contained in:
Hassan Abedi 2026-04-24 12:45:34 +02:00
parent 981bb0d4de
commit 5d82986f30
13 changed files with 484 additions and 0 deletions

View File

@ -0,0 +1,19 @@
# 20-package-overrides
This example shows how to customize an existing package with `overrideAttrs`.
It includes:
- a package built from `pkgs.hello`,
- one override that changes the installed program's behavior, and
- a check that proves the override took effect.
Useful commands:
```bash
nix build
./result/bin/hello
nix run
nix flake check
```

27
20-package-overrides/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
}

View File

@ -0,0 +1,45 @@
{
# Customizes an existing package with `overrideAttrs` and verifies that
# the override changes the package's runtime behavior.
description = "Customize an existing package with overrideAttrs";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
customizedHello = pkgs.hello.overrideAttrs (old: {
pname = "hello-override";
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postInstall = (old.postInstall or "") + ''
wrapProgram $out/bin/hello \
--add-flags "--greeting=hello-from-overrideAttrs"
'';
});
in
{
packages.${system}.default = customizedHello;
apps.${system}.default = {
type = "app";
program = "${self.packages.${system}.default}/bin/hello";
meta.description = "Run GNU hello with a greeting injected by overrideAttrs.";
};
checks.${system}.greeting = pkgs.runCommand "hello-override-check" { } ''
output="$(${self.packages.${system}.default}/bin/hello)"
if [ "$output" = "hello-from-overrideAttrs" ]; then
echo ok > "$out"
else
echo "unexpected output: $output" >&2
exit 1
fi
'';
};
}

View File

@ -0,0 +1,17 @@
# 21-nixos-configurations
This example shows a small `nixosConfigurations` output.
It includes:
- a local module in `module.nix`,
- one full system configuration exposed as `nixosConfigurations.demo`, and
- a check that reads values from the evaluated system configuration.
Useful commands:
```bash
nix flake show
nix eval .#nixosConfigurations.demo.config.networking.hostName --raw
nix flake check
```

27
21-nixos-configurations/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
}

View File

@ -0,0 +1,64 @@
{
# Defines a minimal `nixosConfigurations` output and verifies a known
# value from the evaluated system configuration.
description = "A minimal nixosConfigurations example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
demoSystem = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./module.nix
{
boot.loader.grub = {
enable = true;
device = "/dev/null";
};
fileSystems."/" = {
device = "tmpfs";
fsType = "tmpfs";
};
system.stateVersion = "24.11";
playground = {
hostName = "demo-machine";
motd = "hello from nixosConfigurations";
};
}
];
};
in
{
nixosConfigurations.demo = demoSystem;
checks.${system}.configuration =
pkgs.runCommand "nixos-configuration-check"
{
inherit (demoSystem.config.networking) hostName;
motd = demoSystem.config.environment.etc."playground-motd".text;
}
''
if [ "$hostName" != "demo-machine" ]; then
echo "unexpected host name: $hostName" >&2
exit 1
fi
if [ "$motd" != "hello from nixosConfigurations" ]; then
echo "unexpected motd: $motd" >&2
exit 1
fi
echo ok > "$out"
'';
};
}

View File

@ -0,0 +1,24 @@
{ config, lib, ... }:
let
cfg = config.playground;
in
{
options.playground = {
hostName = lib.mkOption {
type = lib.types.str;
default = "playground";
description = "The host name used by the example system configuration.";
};
motd = lib.mkOption {
type = lib.types.str;
default = "hello";
description = "Text written to /etc/playground-motd.";
};
};
config = {
networking.hostName = cfg.hostName;
environment.etc."playground-motd".text = cfg.motd;
};
}

View File

@ -0,0 +1,20 @@
# 22-fetchers-and-fixed-output
This example shows a pinned fetcher with `fetchurl`.
It includes:
- one upstream tarball fetched with `fetchurl`,
- a declared content hash,
- a small package that consumes the fetched file, and
- a check that verifies the tarball hash and contents.
Useful commands:
```bash
nix build
./result/bin/show-fetched-hello-source
nix run
nix flake check
```

27
22-fetchers-and-fixed-output/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
}

View File

@ -0,0 +1,56 @@
{
# Fetches a pinned upstream archive with `fetchurl`, then consumes that
# fixed-output file from a small package and check.
description = "Fetch a pinned upstream file with fetchurl";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
url = "mirror://gnu/hello/hello-2.12.3.tar.gz";
archiveName = builtins.baseNameOf url;
archiveHash = "sha256-DV9gFUOC/uELEUocNOeF2LH0kgc64tOm97FHaHs2aqA=";
archiveSha256 = "0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0";
helloSource = pkgs.fetchurl {
inherit url;
hash = archiveHash;
};
in
{
packages.${system}.default = pkgs.writeShellApplication {
name = "show-fetched-hello-source";
runtimeInputs = [ pkgs.gnutar ];
text = ''
echo "archive: ${archiveName}"
echo "top-level entry: $(tar -tzf ${helloSource} | head -n 1)"
'';
};
apps.${system}.default = {
type = "app";
program = "${self.packages.${system}.default}/bin/show-fetched-hello-source";
meta.description = "Inspect the archive fetched by a fixed-output fetchurl.";
};
checks.${system}.archive = pkgs.runCommand "hello-source-check" { } ''
actualHash="$(sha256sum ${helloSource} | cut -d' ' -f1)"
if [ "$actualHash" != "${archiveSha256}" ]; then
echo "unexpected sha256: $actualHash" >&2
exit 1
fi
tar -tzf ${helloSource} > entries.txt
grep -q '^hello-2.12.3/README$' entries.txt
echo ok > "$out"
'';
};
}

View File

@ -0,0 +1,46 @@
# Package Overrides
This note covers `20-package-overrides/`, which customizes an existing package with `overrideAttrs`.
---
## 1. Why Override Instead of Rewriting
Sometimes you want to change one part of an existing package, not replace the whole derivation. That is what package overrides are for.
This example starts from `pkgs.hello` and changes its installed program with `overrideAttrs`.
---
## 2. What `overrideAttrs` Changes
`overrideAttrs` receives the old derivation attributes and returns an updated attrset.
In this example, the override:
- appends `makeWrapper` to `nativeBuildInputs`, and
- wraps `bin/hello` so the program always receives a custom `--greeting` flag.
The package still comes from `pkgs.hello`; only one part of its install result changes.
---
## 3. Why the Check Runs the Program
The check does not inspect the derivation text. It runs the overridden program and asserts that the greeting changed.
That keeps the example focused on visible package behavior.
---
## 4. Commands to Try
```bash
cd 20-package-overrides
nix build
./result/bin/hello
nix run
nix flake check
```

View File

@ -0,0 +1,56 @@
# NixOS Configurations
This note covers `21-nixos-configurations/`, which defines a full `nixosConfigurations` output.
---
## 1. Module Versus Configuration
`04-nixos-module/` shows a reusable module. This example shows the next layer up: a full system definition built with `nixpkgs.lib.nixosSystem`.
The local `module.nix` still matters, but now it is only one input into a named machine configuration.
---
## 2. What the Flake Exposes
The key output is:
- `nixosConfigurations.demo`
That is the shape other commands expect when you build, inspect, or deploy a NixOS system from a flake.
---
## 3. Why the Example Sets Boot and File System Options
Even a small NixOS configuration needs a few system-level settings to evaluate cleanly as a full configuration.
This example sets:
- a host name,
- a root file system,
- a boot loader device, and
- `system.stateVersion`.
Those settings are minimal, and they keep the example focused on flake structure rather than real machine setup.
---
## 4. What the Check Verifies
The check reads values from the evaluated configuration and compares them with the expected host name and `/etc` file contents.
That proves the configuration merges correctly without turning the example into a deployment workflow.
---
## 5. Commands to Try
```bash
cd 21-nixos-configurations
nix flake show
nix eval .#nixosConfigurations.demo.config.networking.hostName --raw
nix flake check
```

View File

@ -0,0 +1,56 @@
# Fetchers and Fixed-Output Derivations
This note covers `22-fetchers-and-fixed-output/`, which uses `fetchurl` to pin an upstream tarball by content hash.
---
## 1. Why Fetchers Need a Hash
When Nix fetches content from outside the store, it needs a declared hash so the result stays reproducible.
That turns the fetch into a fixed-output derivation: the output is defined by the content hash, not just by the build steps.
---
## 2. What This Example Pins
The example fetches:
- the GNU hello source archive,
- from a concrete upstream URL, and
- with a declared SHA-256 hash.
If the upstream content changes, the hash check fails instead of silently accepting different bytes.
---
## 3. Why the Example Builds a Second Package
The fetched file by itself is not very interesting. The point is that later derivations can consume it as a normal store path.
This example adds a small package that reads the tarball and prints its top-level entry. That keeps the fetcher visible while still showing how fetched inputs flow into downstream builds.
---
## 4. What the Check Verifies
The check:
- computes the tarball SHA-256 with `sha256sum`, and
- asserts that the archive contains `hello-2.12.3/README`.
That proves both the pinned bytes and the expected archive layout.
---
## 5. Commands to Try
```bash
cd 22-fetchers-and-fixed-output
nix build
./result/bin/show-fetched-hello-source
nix run
nix flake check
```