Skip to content

Commit

Permalink
nix-intro: 2024.05.19-wip
Browse files Browse the repository at this point in the history
  • Loading branch information
codgician committed May 19, 2024
1 parent a64efea commit 394a143
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 34 deletions.
2 changes: 1 addition & 1 deletion slides/nix-intro/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ lib.seelies.mkRevealJs {

name = "nix-intro";
title = "Introducing Nix: declarative builds and deployments";
version = "2024.05.18-wip";
version = "2024.05.19-wip";
src = ./.;
license = lib.licenses.cc-by-nc-sa-40;

Expand Down
194 changes: 161 additions & 33 deletions slides/nix-intro/slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,6 @@ subtitle: Declarative builds and deployments
date: 2024.05.20
---

# Test GraphViz

```{ .graphviz caption="This is an image, created by **Graphviz**'s dot." }
digraph finite_state_machine {
rankdir=LR;
size="8,5"
node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
node [shape = circle];
LR_0 -> LR_2 [ label = "SS(B)" ];
LR_0 -> LR_1 [ label = "SS(S)" ];
LR_1 -> LR_3 [ label = "S($end)" ];
LR_2 -> LR_6 [ label = "SS(b)" ];
LR_2 -> LR_5 [ label = "SS(a)" ];
LR_2 -> LR_4 [ label = "S(A)" ];
LR_5 -> LR_7 [ label = "S(b)" ];
LR_5 -> LR_5 [ label = "S(a)" ];
LR_6 -> LR_6 [ label = "S(b)" ];
LR_6 -> LR_5 [ label = "S(a)" ];
LR_7 -> LR_8 [ label = "S(b)" ];
LR_7 -> LR_5 [ label = "S(a)" ];
LR_8 -> LR_6 [ label = "S(b)" ];
LR_8 -> LR_5 [ label = "S(a)" ];
}
```

# Software deployment

::: { .incremental }
Expand Down Expand Up @@ -431,47 +406,121 @@ Source: https://repology.org/repositories/graphs (2024-05-14)

---

::: { .fragment .semi-fade-out }
Take [rust-analyzer](https://github.com/NixOS/nixpkgs/blob/9a50b221e403694b0cc824fc4600ab5930f3090c/pkgs/development/tools/rust/rust-analyzer/default.nix) as a real-life example.
:::

::: { .fragment .current-visible }
::: { .incremental }
- But I don't want to build software every time...
- Binary cache!
:::

---

*What about runtime dependencies?*

::: { .incremental }

- Nix automatically recognize runtime dependencies.
- Serialize the store paths (output paths) into Nix ARchive (NAR).
- Search for references to other store paths within it.
- **How can this even work?** It just works.
- Search references recursively, and form a *closure* of package to install.

:::

::: { .notes }

*Won't this include unnecessary dependencies?*

- Yes, because Nix's stdenv linker adds `-rpath` flag for every library directory mentioned through -L flags.
- Why? Because it needs to ensure every produced binary is statically composed.
- However we don't know in advance if this library is actually used by the linker. May cause retained but unnecessary dependencies.
- Add an additional "fixup" stage in the builder at the end.
- Use [patchelf](https://github.com/nixos/patchelf) to shrink rpath.
```bash
find $out -type f -exec patchelf --shrink-rpath '{}' \; -exec strip '{}' \; 2>/dev/null
```
:::

# Nix: package manager

- Build time dependencies are explictly specified.
- Runtime dependencies *automatically* recognized.
For each package:

* Build time dependencies explictly specified.
* Runtime dependencies automatically recognized.

::: { .fragment }

Form a *closure*: containing itself and all its dependencies
by searching for references recursively.

:::

## Installation

::: { .fragment .semi-fade-out data-fragment-index="1" }

Two possibilities:

- The closure is already in store or binary cache
- It has to be built fresh

:::

::: { .fragment data-fragment-index="1" }
*How to make the package accessible?*
:::

::: { .fragment }
- *Activation script*: an idempotent script making whatever in nix store visible.
- e.g. symlink all packages to `/usr/bin/`.
- Executed while initializing profile.
:::

## Removal

Garbage collection.

::: { .incremental }
- Register it as gcroot when installing a derivation.
- Deregister after uninstalling.
- Periodically, enumerate all reachable store paths from the gcroots, and remove all unreachable paths.
```bash
$ nix-collect-garbage
```
:::

## Advantages

::: { .incremental }
- No SAT solver.
- Different versions / variants of the same package can be installed together.
- Zero assumption about system global state.
- Atomic installs / upgrades.
:::


# NixOS

::: { .fragment .semi-fade-out data-fragment-index="1" }
*A working system = Software + Configurations*
:::

::: { .fragment }
::: { .fragment data-fragment-index="1" }
*Why separate packages and configurations?*

NixOS leverages Nix to manage both altogether.
:::

---

::: { .r-stack }

::: { .fragment .fade-out data-fragment-index="1" }
[Filesystem Hierarchy Standard](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard)

```
/
β”œβ”€β”€ boot
β”œβ”€β”€ bin
β”œβ”€β”€ etc
β”œβ”€β”€ lib
Expand All @@ -483,17 +532,96 @@ Garbage collection.
```
:::

::: { .fragment data-fragment-index="1" }

*However, in NixOS ...*

```{ .r-stretch }
/
β”œβ”€β”€ boot
β”œβ”€β”€ nix
β”‚ β”œβ”€β”€ store
β”‚ β”‚ β”œβ”€β”€ acr...kl-nixos-system-...
β”‚ β”‚ β”œβ”€β”€ 11w...cv-nixos-system-...
β”‚ β”‚ β”‚ β”œβ”€β”€ activate
β”‚ β”‚ β”‚ β”œβ”€β”€ kernel -> /nix/store/bcd...3h-linux-6.6.30/bzImage
β”‚ β”‚ β”‚ β”œβ”€β”€ systemd -> /nix/store/9cx...8s-systemd-255.4
β”‚ β”‚ β”‚ β”œβ”€β”€ ...
β”‚ β”‚ β”œβ”€β”€ bcd...3h-linux-6.6.30
β”‚ β”‚ β”œβ”€β”€ 9cx...8s-systemd-255.4
β”‚ β”‚ β”œβ”€β”€ ...
β”‚ β”œβ”€β”€ var/nix/profiles
β”‚ β”‚ β”œβ”€β”€ system -> system-250-link
β”‚ β”‚ β”œβ”€β”€ system-249-link -> /nix/store/acr...kl-nixos-system-...
β”‚ β”‚ β”œβ”€β”€ system-250-link -> /nix/store/11w...cv-nixos-system-...
```

- *Activation script*: `/nix/var/nix/profiles/system/activate`

:::
:::

---

*Why separate packages and configurations?*
*Declaratively describe your system in Nix*:

```nix { .r-stretch }
{ config, lib, pkgs, ...}: {
# Use systemd-boot EFI bootloader
boot.loader.systemd-boot.enable = true;
# Kernel configurations
boot.supportedFilesystems = [ "bcachefs" ];
boot.initrd.availableKernelModules = [ "xhci_pci" "sr_mod" ];
boot.kernelPackages = pkgs.linuxPackages_latest;
# Use zsh for shell
programs.zsh.enable = true;
programs.zsh.enableCompletion = true;
# Enable the OpenSSH daemon.
services.openssh.enable = true;
# Configure users
users.users.codgi = {
name = "codgician";
home = "/home/codgi";
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [ "..." ];
};
}
```

---

- Nixpkgs also provide configuration modules, [search here](https://search.nixos.org/options?).
- How I manage my devices: [github:codgician/serenitea-pot](https://github.com/codgician/serenitea-pot).
- Demo.

---

# References
> The power of NixOS roots in the Nix language.
- Validate configurations before deployment.
- Reference values accross modules of configurations.
- Effeciently reuse configurations.
- Unified language interface for any system component.

# Ending

todo...

## References

- [Dolstra, Eelco. The purely functional software deployment model. Utrecht University, 2006.](https://edolstra.github.io/pubs/phd-thesis.pdf)
- [Nix Pills](https://nixos.org/guides/nix-pills/)
- [Nix: from a build system to an ansible replacement (TUNA)](https://mirrors.tuna.tsinghua.edu.cn/tuna/tunight/2021-05-29-nix/slides.pdf)

---

To get started, or learn further about Nix:

- Official website: [nixos.org](https://nixos.org)
- Nix docs: [nix.dev](https://nix.dev)
- NixOS wiki: [wiki.nixos.org](https://wiki.nixos.org)
- Search packages / configurations: [search.nixos.org](https://search.nixos.org)
- Search for functions in nix (lang): [noogle.dev](https://noogle.dev)

---

Expand Down

0 comments on commit 394a143

Please sign in to comment.