# NixOS

This document contains general notes about NixOS that are independent of my NixOS configuration.

## Table of Contents

<!-- TOC -->
* [NixOS](#nixos)
  * [Table of Contents](#table-of-contents)
  * [Misc](#misc)
  * [Upgrade from 23.05 to 23.11](#upgrade-from-2305-to-2311)
  * [niv: Dependency management](#niv-dependency-management)
    * [Add Home Manager with niv](#add-home-manager-with-niv)
    * [Add NUR with niv](#add-nur-with-niv)
  * [Garbage collection](#garbage-collection)
  * [System information](#system-information)
  * [Search for packages](#search-for-packages)
  * [Search for options](#search-for-options)
  * [Search which package owns a file](#search-which-package-owns-a-file)
  * [List files of package](#list-files-of-package)
  * [Compare two versions of NixOS system profile](#compare-two-versions-of-nixos-system-profile)
  * [NixOS configuration debugging](#nixos-configuration-debugging)
  * [Show Nix configuration](#show-nix-configuration)
  * [Evaluate NixOS configuration to JSON](#evaluate-nixos-configuration-to-json)
  * [Evaluate expressions](#evaluate-expressions)
  * [Escape strings](#escape-strings)
  * [Run AppImages](#run-appimages)
  * [Additional resources](#additional-resources)
    * [Nix Pills](#nix-pills)
    * [Papers](#papers)
<!-- TOC -->

## Misc

* There is controversy about flakes, rather use channels (e.g. with niv)
* Prins, P., Suresh, J. and Dolstra, E., "Nix fixes dependency hell on all Linux distributions," [Archived](https://web.archive.org/web/20081226010942/http://www.linux.com/feature/155922) December 26, 2008, at the Wayback Machine linux.com, December 22, 2008

## Upgrade from 23.05 to 23.11

* https://discourse.nixos.org/t/nixos-23-11-released/36210

Change the tracking branch of nixpkgs from 23.05 to 23.11:

```shell
niv modify nixpkgs      --branch   nixos-23.11
niv modify home-manager --branch release-23.11
```

Update `home.stateVersion` to `home.stateVersion = "23.11";` in order to match the NixOS channel. Read the corresponding release notes: https://nix-community.github.io/home-manager/release-notes.xhtml#sec-release-23.11

Read the release notes. GNOME 45: Notably, Loupe has replaced Eye of GNOME as the default image viewer, Snapshot has replaced Cheese as the default camera application, and Photos will no longer be installed.

Updating with nixos-rebuild boot and rebooting is recommended.

```shell
niv update && colmena build --on yodaTux   -v --show-trace && colmena apply-local --sudo   boot
niv update && colmena build --on remoteTab -v --show-trace && colmena apply --on remoteTab boot
niv update && colmena build --on @server   -v --show-trace && colmena apply --on @server   boot
```

Update channel (for `nix-shell` usage in a terminal):

```shell
sudo nix-channel --list
#=> nixos https://nixos.org/channels/nixos-23.05
sudo nix-channel --add https://nixos.org/channels/nixos-23.11 nixos
sudo nix-channel --update
```

## niv: Dependency management

* https://nix.dev/tutorials/first-steps/towards-reproducibility-pinning-nixpkgs#dependency-management-with-niv

niv:

> Easy dependency management for Nix projects.
>
> Nix is a very powerful tool for building code and setting up environments. niv complements it by making it easy to
> describe and update remote dependencies (URLs, GitHub repos, etc). It is a simple, practical alternative to Nix
> flakes.
>
> https://github.com/nmattia/niv

> Niv is an easy dependency management for Nix projects with package pinning.
>
> https://github.com/mikeroyal/NixOS-Guide

Initialize:

```shell
niv init
```

Change the tracking branch of nixpkgs from unstable to 23.05:

```shell
niv modify nixpkgs --branch nixos-23.05
```

Add nixpkgs unstable:

```shell
niv add NixOS/nixpkgs -n unstable -b nixpkgs-unstable
```

### Add Home Manager with niv

Home Manager:

> [Home Manager] allows declarative configuration of user specific (non-global) packages and dotfiles.
>
> To avoid breaking users' configurations, Home Manager is released in branches corresponding to NixOS releases (
> e.g. `release-23.05`).
>
> Home Manager provides both the channel-based setup and the flake-based one.
>
> https://github.com/nix-community/home-manager

Check your channel:

```shell
sudo nix-channel --list
#=> nixos https://nixos.org/channels/nixos-23.05
```

Use the corresponding branch:

```shell
niv add nix-community/home-manager -n home-manager -b release-23.05
```

### Add NUR with niv

> The Nix User Repository (NUR) is community-driven meta repository for Nix packages.
>
> ... packages are built from source and are not reviewed by any Nixpkgs member.
>
> https://github.com/nix-community/NUR

```shell
niv add nix-community/NUR -n NUR
```

## Garbage collection

* https://nixos.org/manual/nix/stable/package-management/garbage-collection.html
* https://discourse.nixos.org/t/why-doesnt-nix-collect-garbage-remove-old-generations-from-efi-menu/17592/4

This is automated in [base.nix](modules/base.nix) with the `nix.gc` option.

Run manually for all profiles:

```shell
sudo nix-collect-garbage --delete-older-than 14d
```

Remove leftover EFI entries of removed generations:

```shell
sudo /run/current-system/bin/switch-to-configuration boot
```

## System information

```shell
nix-info -m
```
```
 - system: `"x86_64-linux"`
 - host os: `Linux 6.1.51, NixOS, 23.05 (Stoat), 23.05.3242.da5adce0ffaf`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.13.5`
 - channels(root): `"nixos-23.05"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
```

## Search for packages

* https://search.nixos.org/packages?channel=23.05

## Search for options

* https://search.nixos.org/options?channel=23.05
    * Or `man configuration.nix`
* https://mipmip.github.io/home-manager-option-search
    * Or `man home-configuration.nix`

## Search which package owns a file

```shell
# Note how your shell prefix changes.
nix-shell -p nix-index
```
```shell
# Either build the index manually (requires >12GB RAM):
nix-index
# Or download weekly build:
mkdir -p ~/.cache/nix-index/ && wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/index-x86_64-linux -O ~/.cache/nix-index/files

# Then search for a file
nix-locate --whole-name '/bash'
```

## List files of package

* https://discourse.nixos.org/t/list-files-of-package/25830/2?u=langfingaz

Example for `nano`:

```shell
find $(nix-build '<nixpkgs>' -A nano --no-link)
```

Excerpt of the result:

```
/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano
/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano/asm.nanorc
/nix/store/jqvxmx65mfinbsm6db9kmcqmphl44xhp-nano-7.2/share/nano/autoconf.nanorc
```

## Compare two versions of NixOS system profile

Get latest system profile. This is the profile (usually) being active after booting the system:

```shell
ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 1
#=> 120
```

Compare current with previous profile:

```shell
# https://discourse.nixos.org/t/how-to-know-what-nixpkgs-changes-affect-me/18142/6
prev="$(ls -r /nix/var/nix/profiles/ | grep -E 'system\-' | sed -n '2 p')"
curr=/nix/var/nix/profiles/system
nix --extra-experimental-features nix-command store diff-closures /nix/var/nix/profiles/"${prev}" "${curr}"
```

```shell
# https://stackoverflow.com/a/36641298
prev="$(ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 2 | head -n 1)"
curr="$(ls -1 /nix/var/nix/profiles/ | sort -t'-' -n -k2 | tail -n 1)"
nix --extra-experimental-features nix-command store diff-closures /nix/var/nix/profiles/"${prev}" /nix/var/nix/profiles/"${curr}"
```

Compare two arbitrary system profiles:

```shell
nix --extra-experimental-features nix-command store diff-closures /nix/var/nix/profiles/system-110-link /nix/var/nix/profiles/system-116-link
```
```
cpupower: 6.1.47 → 6.1.51
element-desktop: 1.11.38 → 1.11.40, +2218.9 KiB
element-web: 1.11.38 → 1.11.40, -73.1 KiB
exempi: 2.6.3 → 2.6.4
firefox: 116.0.3 → 117.0
firefox-unwrapped: 116.0.3 → 117.0, -292.6 KiB
gnome-shell-extension-openweather: ∅ → 121, +590.5 KiB
hm_fontconfigconf.d10hmfonts.conf: ∅ → ε
initrd: ∅ → ε
initrd-linux: 6.1.47 → 6.1.51
libcap: 2.68 → 2.69
linux: 6.1.47, 6.1.47-modules → 6.1.51, 6.1.51-modules, -11.8 KiB
meld: ∅ → 3.22.0, +3858.5 KiB
net-snmp: 5.9.3 → 5.9.4
nixos-system-yodaTab: 23.05.3085.2ab91c8d65c0 → 23.05.3242.da5adce0ffaf
openjdk: +19.5 KiB
python3.10-pygobject: +27.0 KiB
stage: ∅ → 1-init.sh, +29.5 KiB
tor-browser-bundle-bin: 12.5.2 → 12.5.3, +18.1 KiB
user: +2885.0 KiB
```

## NixOS configuration debugging

* https://nixos.wiki/wiki/Nix_command/repl

Evaluating parts of the configuration.

First, start `nix repl`:

```shell
nix repl --file '<nixpkgs/nixos>' -I nixos-config=hosts/$(hostname)/configuration.nix
```

Example: `config.home-manager`

```shell
config.home-manager.
# Press `TAB`
#=> config.home-manager.backupFileExtension  config.home-manager.useUserPackages
#=> config.home-manager.extraSpecialArgs     config.home-manager.users
#=> config.home-manager.sharedModules        config.home-manager.verbose
#=> config.home-manager.useGlobalPkgs
```

Example: The `home` variable:

```shell
config.home-manager.users.yoda.home
```

Example: The value of one config option

```shell
# The following option is set to `"${config.xdg.dataHome}/.histfile";`
# where `config` is the Home Manager configuration.

config.home-manager.users.yoda.programs.zsh.history.path
#=> "/home/yoda/.local/share/.histfile"
```

## Show Nix configuration

* https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-show-config.html

```shell
nix --extra-experimental-features nix-command show-config
```

## Evaluate NixOS configuration to JSON

See also section "NixOS Configuration Debugging"!

* https://discourse.nixos.org/t/can-i-run-nix-instantiate-eval-strict-on-my-configuration-nix/7105/4

This evaluates `configuration.nix` (single module):

```shell
NIXPKGS_ALLOW_UNFREE=1 nix-instantiate --strict --json --eval -E '
import ./hosts/yodaTab/configuration.nix  {
  config = {};
  pkgs = import <nixpkgs> {};
  lib = import <nixpkgs/lib>;
}
' > evaluated-config.json
```

Then open `evaluated-config.json`.

## Evaluate expressions

* https://discourse.nixos.org/t/eval-nix-expression-from-the-command-line/8993/6

```shell
nix-instantiate --eval -E 'with import <nixpkgs> { }; vscode.version'
#=> "1.78.2"
```

Shell wrapper:

```shell
nix-eval() { nix-instantiate --eval -E "with import <nixpkgs> {}; ${*}"; }
```

Examples:

```shell
nix-eval 'vscode.version'
#=> "1.78.2"
nix-eval 'lib.forEach [ 1 2 ] (x: toString x)'
#=> [ "1" "2" ]
nix-eval 'lib.head [1 2]'
#=> 1
nix-eval 'lib.head (
  lib.forEach [ 1 2 ] (x: toString x)
)'
#=> "1"
nix-eval 'lib.head (
  lib.forEach [ {a=1;} {a=2;} ] (x: x.a)
)'
#=> 1
nix-eval 'lib.attrsets.mergeAttrsList [{a=1;} {b=2;}]'
#=> { a = 1; b = 2; }
nix-eval '{ a=1; }.b or 2'
#=> 2
nix-eval '{ a=false; }.a or true'
#=> false
nix-eval '{ a=1; }?a'
#=> true
nix-eval 'with lib.strings; concatMapStrings (x: " -a " + x + " -i 600") ["sda" "sdc"]'
#=> " -a sda -i 600 -a sdc -i 600"
```

## Escape strings

* https://nixos.org/manual/nix/stable/language/values

Double-quoted strings (e.g. `"foo bar"`):
```
"  -> \"
\  -> \\
${ -> \${
```

Indented strings (e.g. `''foo bar''`):
* `${` -> `''${`
* `''` -> `'''`

URIs can be written without quotes (e.g. `http://example.org/foo.bar`).

## Run AppImages

* https://nixos.wiki/wiki/Appimage

```shell
# Note how your shell prefix changes.
nix-shell -p appimage-run
```
```shell
# Inside the shell, you can run an AppImage:
appimage-run ~/Downloads/ubports-installer_0.10.0_linux_x86_64.AppImage
```

## Additional resources

* Simple NixOS flake template for NixOS with HomeManager. https://github.com/Misterio77/nix-starter-configs#readme
* NixOS guide (development environment, gaming, etc). https://github.com/mikeroyal/NixOS-Guide#table-of-contents
* nix function cheatsheet: https://nix-cheatsheet.pixie.homes/
* Documenting the Journey of Learning and Mastering Nix. https://ianthehenry.com/posts/how-to-learn-nix/
* Nix language basics. https://nix.dev/tutorials/nix-language.html
* Nix data types. https://nixos.org/manual/nix/stable/language/values
* MkIfElse. https://discourse.nixos.org/t/mkif-vs-if-then/28521/4?u=langfingaz
* Nix language basics - a one pager. https://github.com/tazjin/nix-1p#nix---a-one-pager

### Nix Pills

* https://nixos.org/guides/nix-pills/pr01

It provides a tutorial introduction into the Nix package manager and Nixpkgs package collection, in the form of short
chapters called 'pills'.

### Papers

Papers about Nix:

* The Purely Functional Software Deployment Model (2006). http://nixos.org/~eelco/pubs/phd-thesis.pdf, https://edolstra.github.io/pubs/phd-thesis.pdf, https://github.com/edolstra/edolstra.github.io/blob/master/pubs/phd-thesis.pdf
  * May 2023: Some insights from the thesis in short form. https://jonathanlorimer.dev/posts/nix-thesis.html
* NixOS: A Purely Functional Linux Distribution (2008): https://github.com/edolstra/edolstra.github.io/blob/master/pubs/nixos-icfp2008-final.pdf, https://github.com/edolstra/edolstra.github.io/blob/master/pubs/nixos-jfp-final.pdf
* Nix: A Safe and Policy-Free System for Software Deployment (2004): https://edolstra.github.io/pubs/nspfssd-lisa2004-final.pdf
