Nix β
Nix is a language, package manager and ecosystem for creating declarative system configurations.
Nix can be used standalone to manage a user with Home Manager, or to configure your entire system using NixOS.
Nixpkgs β
Nixpkgs is the official repository of software packages for the Nix package manager.
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
}
According to Repology, nixpkgs has more than twice the number of fresh packages as the AUR.
Channels β
A channel is a branch in the Nixpkgs repository which includes a set list of (normally) well-tested packages.
To see a list of channels and their health, see the official Nix Channel Status page.
Flakes β
A flake is a kind of NixOS derivation (an entire working configuration) that uses a lockfile to manage package versions, rather than channels.
Note
You do not need a flake in order to manage your configuration with NixOS, and you do not need a flake to import other files.
To enable flakes, set the nix.package
and nix.settings.experimental-features
options to the following:
# Enable Flakes
nix.package = pkgs.nixFlakes;
nix.settings.experimental-features = ["nix-command" "flakes"];
Check out Nix Flakes for more information.
Nix language β
Working with lists and attribute sets β
Functions to work with lists and attribute sets generally come from their respective module in the nixpkgs standard library, or using the builtins
functions.
Common iteration patterns β
FRUITS = [
{ value = 1; name = "Apple"; }
{ value = 2; name = "Banana"; }
{ value = 8; name = "Pomegranate"; }
];
// { Apple: 1; Banana: 2; Pomegranate: 8; }
prices = builtins.listToAttrs FRUITS;
FRUITS = [
{ value = 1; name = "Apple"; }
{ value = 2; name = "Banana"; }
{ value = 8; name = "Pomegranate"; }
];
// [ { tag = "Apple - $1"; } { tag = "Banana - $2"; } { tag = "Pomegranate - $8"; } ]
tags = lib.lists.forEach FRUITS (fruit: {
tag = "${fruit.name} - $${fruit.value}";
});
Map an attribute set into another attribute set
Note
Pronounced "map attrs prime" π
PRICES = {
Apple: 1;
Banana: 2;
Pomegranate: 8;
};
// { "Apple - $1": "$1.00; "Banana - $2": "$2.00"; "Pomegranate - $8": "$8.00"; }
shelf = lib.attrsets.mapAttrs' (fruit: price: {
name = "${fruit} - $${price}";
value = "$${price}.00";
});
WORDS = [ "howdy" "partner" "π€ " ];
// "howdypartnerπ€ ";
greeting = lib.strings.concatStrings WORDS;
Interpolation β
Nix supports interpolation in strings, paths, and attribute names.
Interpolated expressions β
When an expression is used in interpolation, it's called an interpolated expression. Expressions interpolate like:
string
s interpolate to themselves.path
s interpolate to their absolute path in the Nix store.attribute set
s interpolate with a__toString
attribute which you must provide.
Escaping special characters β
Indented strings can be annoying to avoid interpolation with for certain things.
$
can be escaped by prefixing it with''
. i.e.''${...}
''
can be escaped by prefixing it with'
. i.e.'''stuff'''
For example: zsh value substitution in Nix#`pkgs.writeShellApplication`:
let
greeting = "Howdy π€ ";
multiline = ''
well hello there
${greeting}
''${greeting}
'''goodbye π'''
'';
in
# ''
# well hello there
# Howdy π€
# \${greeting}
# ''goodbye π''
# ''
multiline
Examples of interpolation β
Interpolating two strings
let
apple = "apple";
banana = "banana";
fruits = "${apple}s and ${banana}s";
in
# "apples and bananas"
fruits
Interpolating a path
let
doggo = ./adorable-dog-photo.jpg;
in
{
# "open /nix/store/.../adorable-dog-photo.jpg"
script = "open ${doggo}";
}
Interpolating an attribute set
let
full-name = {
first = "Arn";
last = "Peerz";
# __toString takes in the attribute set itself
__toString = name: "${name.first} ${name.last}";
}
in
{
# "Hello, Arn Peerz!"
greeting = "Hello, ${full-name}!";
}
Derivations β
A derivation is a set of instructions which inform Nix how to build a package from scratch.
pkgs.writeShellApplication
β
pkgs.writeShellApplication
does three things:
- Creates a package which only contains your
.text
as an executable script - Automatically sets the
PATH
of the script to contain anyruntimeInputs
- Sets some sanity options
errexit
,nounset
,pipefail
- Checks the script with shellcheck, and throws compile errors for any issues
Here's a function for installing a script managed using writeShellApplication
:
{ pkgs, ...}: let
# Here we define a script called screenshot-region
screenshot-region = pkgs.writeShellApplication {
name = "screenshot-region";
# Define all the dependencies for the PATH
runtimeInputs = [pkgs.grim pkgs.slurp pkgs.wl-clipboard];
text = ''
grim -g "$(slurp -d)" - | wl-copy && notify-send "Copied region to clipboard"
'';
};
in {
# Make the script accessible to the user
home.packages = [screenshot-region];
# Make the script accessible to the entire system
environment.systemPackages = [screenshot-region];
}
pkgs.writeTextFile
β
pkgs.writeTextFile
and other basic text builders will write text files into the Nix stores as a derivation.
If provided with a .destination
option, it will write that to a file contained inside the derivation. If not provided, the file will be at the root of the derivation.
This can be used with Home Manager to add it to your XDG config, or just anywhere in your $HOME
directory.
Or it can be used with NixOS to write out a config file into /etc/
.
Here's a sample for adding a workstyle config:
{ pkgs, ... }: let
workstyle-config = pkgs.writeTextFile {
name = "config.toml";
# Only the best settings
text = ''
"foot" = "π¦Ά"
"discord" = "π£οΈ"
"code" = "π»"
"obsidian" = "π"
'';
};
in {
# Write to $XDG_CONFIG/workstyle/config.toml
xdg.configFile.workstyle = {
target = "./workstyle/config.toml";
source = workstyle-config;
};
# Write to $HOME/.workstyle.toml
home.file.".workstyle.toml".source = workstyle-config;
# Write to /etc/workstyle
environment.etc.workstyle.source = workstyle-config;
}
Note
For any of these options, you can also define the text
key inline:
{ pkgs, ... }: {
# Write to $XDG_CONFIG/workstyle/config.toml
xdg.configFile.workstyle = {
target = "./workstyle/config.toml";
text = ''
"foot" = "π¦Ά"
"discord" = "π£οΈ"
"code" = "π»"
"obsidian" = "π"
'';
};
# Write to $HOME/.workstyle.toml
home.file.".workstyle.toml".text = ''
"foot" = "π¦Ά"
"discord" = "π£οΈ"
"code" = "π»"
"obsidian" = "π"
'';
# Write to /etc/workstyle
environment.etc.workstyle.text = ''
"foot" = "π¦Ά"
"discord" = "π£οΈ"
"code" = "π»"
"obsidian" = "π"
'';
}
pkgs.writeTextDir
β
pkgs.writeTextDir
is a shorthand for pkgs.writeTextFile
with executable = false;
and taking in an argument for destination = ...
:
let
zsh-config = pkgs.writeTextDir ".zshrc" ''
source "${pkgs.zsh-powerlevel-10k}"
'';
in