summaryrefslogtreecommitdiffstats
path: root/slides.md
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2019-09-29 18:41:06 +0200
committerMinijackson <minijackson@riseup.net>2019-10-06 19:52:48 +0200
commitbfe04cc037a15676b173fe8214909d45551ad42c (patch)
tree7cf2a03a499daa2f3cb3c882b19528bef49df2e1 /slides.md
parent7eb42e35175c55737bdd3b4ef10fb55550928b5c (diff)
downloadnixos-embedded-slides-bfe04cc037a15676b173fe8214909d45551ad42c.tar.gz
nixos-embedded-slides-bfe04cc037a15676b173fe8214909d45551ad42c.zip
Add first very WIP version
Diffstat (limited to 'slides.md')
-rw-r--r--slides.md717
1 files changed, 717 insertions, 0 deletions
diff --git a/slides.md b/slides.md
new file mode 100644
index 0000000..cb61c9c
--- /dev/null
+++ b/slides.md
@@ -0,0 +1,717 @@
1---
2title: NixOS for Embedded systems
3author: Rémi Nicole
4date: 2019-10-09
5slide-level: 2
6aspectratio: 169
7theme: metropolis
8toc: true
9highlightstyle: breezedark
10lang: en-US
11
12header-includes: |
13 \usepackage{csquotes}
14 \usepackage{pgfpages}
15 \setbeameroption{show notes on second screen=right}
16
17 \usecolortheme{owl}
18 \setbeamercolor{section in toc}{
19 use=normal text,
20 fg=normal text.fg
21 }
22 \setbeamercolor{subsection in toc}{
23 use=normal text,
24 fg=normal text.fg
25 }
26
27 \usepackage{fvextra}
28---
29
30# Projects and concepts
31
32## {.standout}
33
34Heads Up
35
36::: notes
37
38- This is not a "what are you doing not using this" talk
39- We will see some drawbacks that makes these tools not suitable for production
40 yet.
41- This is more a call to try, tinker, experiment, contribute to the project so
42 it would be production ready
43
44:::
45
46## Definitions
47
48NixOS
49
50: Distribution
51
52Nix
53
54: Source-based package manager
55
56Nixpkgs
57
58: "Standard library"
59
60::: notes
61
62- All 3 are useful in the Embedded system context
63
64- "Standard library" is quoted, because it contains:
65
66 - Packages
67 - Functions
68 - Compiling instructions for multiple languages / tools
69 - NixOS modules and options
70
71- NixOS is more of a "complete application" of the Nix package manager's
72 philosophy, implemented inside Nixpkgs
73
74:::
75
76## Other projects
77
78Hydra
79
80: Continuous Integration server based on Nix
81
82NixOps
83
84: NixOS cloud deployment tool
85
86Disnix
87
88: Distributed service deployment toolset
89
90::: notes
91
92Hydra
93
94: Can be used to produce a binary cache. Because Nix is deterministic, it is
95 like deploying automated Debian repository. No more need to compile Chromium
96 on each individual developer machine.
97
98NixOps
99
100: Like Amazon EC2
101
102Disnix
103
104: More like Chef / Puppet for multiple hosts
105
106:::
107
108# The Nix language
109
110## Nix---overview
111
112- Source based
113- Functional
114 - A package is a function that returns instructions on how to build a path
115 - Each output is in its own directory forever
116 `/nix/store/<hash>-<name>/...`
117 - You can have multiple versions of the same package
118- Binary caches
119- Dynamically typed
120- Lazy
121
122::: notes
123
124- Based on the ML family
125
126- A package is a function that depends on its dependencies, compile time
127 options, etc.
128
129- Most of the time, "how to build a path" implies building the package, and
130 then installing into that path
131
132- The hash is the sha256 of the configuration of the package, meaning the result
133of the "package function".
134
135- A package which has the same hash does **not** need to be recompiled
136
137- When you have multiple versions of the same package, they are under different
138 store paths, and it can mean
139 - different upstream version
140 - different compilation options
141 - different applied patches
142 - different anything that would make the files in the output path different
143
144**TODO**: have a section to show off how to *use* different versions
145
146:::
147
148## Nix---Process
149
150- Use the Nix language to write derivations
151
152 Derivation
153 : Data structure that describes how to create an output path (file / directory)
154
155- The derivation is compiled into a `.drv` file.
156- Realising a derivation creates the output path
157- The closure of an output path is the path and all its dependencies
158
159::: notes
160
161- Most of the time the output path is a directory which contains an FHS-like
162 structure
163
164- You can think of the `.drv` file as the result of the evaluation of your
165 `.nix` files
166
167- In simpler terms, because a package is a function, the `.drv` is the result
168 of that function
169
170:::
171
172## Nix---Example output paths
173
174```
175/nix/store/8is5yfpd095i8pcg71pb9wxv6y6d4gfv-openssh-7.9p1
176├── bin
177│   ├── ssh
178│   └── ...
179├── etc
180│   └── ssh
181│   ├── ssh_config
182│   └── ...
183└── share
184 └── man
185 └── ...
186/nix/store/chdjidjcmjs610024chncbin4bx211f2-asound.conf
187/nix/store/486r3d12gc042yric302jg14in7j3jwm-i3.conf
188```
189
190## Nix---Language (Types)
191
192```nix
193{
194 int = 1;
195 boolean = true;
196 string = "hello ${world}!";
197 "attribute set" = { a = 1; b = 2; };
198 list = [ 1 2 "hello" ];
199 function = a: builtins.toString a;
200 "function w/ named parameters" = { a, b, c ? "default"}: a;
201}
202```
203
204::: notes
205
206- There's also the "derivation", which is his own type.
207
208- Function are just another type, they have a name when assigned to a variable
209
210- Functions only take one parameter. To have more than one parameter, you write
211a function that returns a function ("currying"), or use named parameters.
212
213:::
214
215## Nix---Language (Control Flow)
216
217
218:::::: {.columns}
219::: {.column witdh="60%"}
220
221```nix
222let
223 a = 1;
224 b = a + 1;
225 c = var: "hello ${var}!";
226in
227 {
228 d = if a == 1 then 2 else 3;
229 e = c "world";
230 }
231```
232
233:::
234::: {.column witdh="40%"}
235
236Gives:
237
238```nix
239{
240 d = 2;
241 e = "hello world!";
242}
243```
244
245:::
246::::::
247
248::: notes
249
250- This is a functional language, so every expression **must** return a value:
251 a `let` returns a value, an `if` returns a value so it must have an `else`
252 clause, etc.
253
254- Implies that every time you can input a value, you can input a control flow
255 expression
256
257- Functions do not need parentheses nor commas
258 - You can wrap everything around parentheses to force the order
259 - It kind of is like Lisp languages but the parentheses are optional
260
261:::
262
263## Nix---Language (Control Flow continued)
264
265
266:::::: {.columns}
267::: {.column witdh="60%"}
268
269```nix
270let
271 a = 1;
272 b = a + 1;
273 c = { d = 42; inherit b; };
274in
275 rec {
276 inherit (c) b;
277 e = with c; d + 3;
278 f = e + 1;
279 }
280```
281
282:::
283::: {.column witdh="40%"}
284
285Gives:
286
287```nix
288{
289 b = 2;
290 e = 45;
291 f = 46;
292}
293```
294
295:::
296::::::
297
298::: notes
299
300- If we want to do it almost like the Nix interpreter, we start by the end, and
301 look for what we want, as needed.
302
303:::
304
305## Puzzle
306
307What does that do?
308
309```nix
310rec {
311 a = {
312 inherit a;
313 };
314}
315```
316
317::: notes
318
319- Because the language is lazy, the question we have to ask is "What do we want
320 from that attribute set"
321
322:::
323
324# How 2 perfect packaging with Nixpkgs
325
326## An example Nixpkgs derivation
327
328```nix
329{ stdenv, fetchurl }:
330
331stdenv.mkDerivation rec {
332 name = "hello-${version}";
333 version = "2.10";
334
335 src = fetchurl {
336 url = "mirror://gnu/hello/${name}.tar.gz";
337 sha256 = "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i";
338 };
339
340 doCheck = true;
341```
342
343::: notes
344
345- `stdenv` (standard environment) is a collection of packages: contains
346 a C compiler, autotools, make, etc.
347- `stdenv` also contains the function `mkDerivation` which automates a lot of
348 package building
349- In this example, the package is build using the standard `./configure; make;
350 make install` and in this case, also `make test`
351- You **have** to specify the `sha256` in the `fetchurl` function to make the
352 network access deterministic.
353 - It would invalidate a lot of Nix's assumptions if the upstream mirror
354 changed the tarball
355
356:::
357
358---
359
360```nix
361 meta = with stdenv.lib; {
362 description = "A program that produces a familiar, friendly greeting";
363 longDescription = ''
364 GNU Hello is a program that prints "Hello, world!" when you run it.
365 It is fully customizable.
366 '';
367 homepage = "https://www.gnu.org/software/hello/manual/";
368 license = licenses.gpl3Plus;
369 maintainers = [ maintainers.eelco ];
370 platforms = platforms.all;
371 };
372}
373```
374
375## Other examples {.shrink}
376
377
378:::::: {.columns}
379::: {.column}
380
381```nix
382{ stdenv, meson, ninja, pkgconfig
383, qtbase, qtconnectivity }:
384
385stdenv.mkDerivation rec {
386 pname = "setup-poc";
387 version = "0.1.0";
388 nativeBuildInputs =
389 [ meson ninja pkgconfig ];
390 buildInputs =
391 [ qtbase qtconnectivity ];
392 mesonBuildType = "debug";
393 src = ./.;
394}
395```
396
397:::
398::: {.column}
399
400```nix
401derive2 {
402 name = "ggplot2";
403 version = "3.2.0";
404 sha256 = "1cvk9pw...";
405 depends = [ digest gtable lazyeval
406 MASS mgcv reshape2 rlang
407 scales tibble viridisLite
408 withr ];
409};
410```
411
412:::
413::::::
414
415::: notes
416
417- In the meson derivation, you don't need to specify a sha256 sum for the
418 source: because it is local, Nix will integrate recursively the local files
419 into the derivation's final hash.
420 - This means: if a file changes, the hash changes, and it is another
421 package, in another path in the store
422 - This also means: if a file changes, Nix will know that it has to
423 recompile this package. And because this package is passed as an argument
424 to other packages, it will also recompile every packages that depends on
425 it.
426
427- **TODO**: Explain setup-hooks, and not only for build managers
428
429
430:::
431
432## How do you call the function
433
434default.nix:
435
436```nix
437let
438 pkgs = import <nixpkgs> {};
439in
440 pkgs.callPackage ./derivation.nix {}
441```
442
443We run:
444
445```bash
446nix build --file default.nix
447```
448
449::: notes
450
451- Most of the time we use a function with default parameters, but this is for
452 simplicity's sake
453- `callPackage` will pass the dependencies as arguments to the derivation
454 function
455- `--file default.nix` is the default
456
457:::
458
459---
460
461If we have derivation.nix:
462
463```nix
464{ writeShellScriptBin }:
465
466writeShellScriptBin "myScript" "echo 'Hello, World!'"
467```
468
469We get as output path:
470
471```
472./result/
473└── bin
474    └── myScript
475```
476
477```
478$ ./result/bin/myScript
479Hello, World!
480```
481
482::: notes
483
484- `writeShellScriptBin` is a commodity function, called a "trivial builder"
485
486
487:::
488
489---
490
491```
492$ ls -l result
493result -> /nix/store/a7db5d4v5b2pxppl8drb30ljx9z0kwg0-myScript
494```
495
496. . .
497
498`./result/bin/myScript` is:
499
500```bash
501#!/nix/store/cinw572b38aln37glr0zb8lxwrgaffl4-bash-4.4-p23/bin/bash
502echo 'Hello, World!'
503```
504
505::: notes
506
507- Everything needed by Nix or produced by Nix must be in the store
508- Prevents contamination from the environment
509- Build is in a chroot, with stripped env
510
511---
512
513- This derivation depends on a specific version of Bash (because every final
514 dependency is specific)
515- In Nix's terms, this specific Bash is in the closure of the "myScript"
516 derivation's output path
517
518:::
519
520## Using different versions of the same package---Generic
521
522```bash
523#! /nix/store/...-bash-4.4-p23/bin/bash -e
524export PATH='/nix/store/...-python-2.7.16/bin:
525 /nix/store/...-glxinfo-8.4.0/bin:
526 /nix/store/...-xdpyinfo-1.3.2/bin'${PATH:+':'}$PATH
527export LD_LIBRARY_PATH='/nix/store/...-curl-7.64.0/lib:
528 /nix/store/...-systemd-239.20190219-lib/lib:
529 /nix/store/...-libmad-0.15.1b/lib:
530 /nix/store/...-libvdpau-1.1.1/lib:
531 ...'${LD_LIBRARY_PATH:+':'}$LD_LIBRARY_PATH
532exec -a "$0" "/nix/store/...-kodi-18.1/bin/.kodi-wrapped" \
533 "${extraFlagsArray[@]}" "$@"
534```
535
536::: notes
537
538- This is actually called by another wrapper who tells Kodi where to find its
539 data
540
541:::
542
543## Using different versions of the same package---ELF
544
545```
546$ readelf -d coreutils
547...
548Bibliothèque partagée: [librt.so.1]
549Bibliothèque partagée: [libpthread.so.0]
550Bibliothèque partagée: [libacl.so.1]
551...
552Bibliothèque runpath:[
553 /nix/store/...-acl-2.2.53/lib:
554 /nix/store/...-attr-2.4.48/lib:
555 /nix/store/...-openssl-1.0.2t/lib:
556 /nix/store/...-glibc-2.27/lib
557]
558...
559```
560
561## Using different versions of the same package---Python
562
563```python
564# imports...
565sys.argv[0] = '/nix/store/...-carla-2.0.0/share/carla/carla'
566functools.reduce(
567 lambda k, p: site.addsitedir(p, k),
568 [
569 '/nix/store/...-python3.7-rdflib-4.2.2/lib/python3.7/site-packages',
570 '/nix/store/...-python3.7-isodate-0.6.0/lib/python3.7/site-packages',
571 '/nix/store/...-python3.7-six-1.12.0/lib/python3.7/site-packages',
572 # ...
573 ],
574 site._init_pathinfo())
575# ...
576```
577
578::: notes
579
580- Because these paths are in the closure of the app, they are guaranteed by Nix
581 to be there
582
583:::
584
585# NixOS
586
587## How do you make a Linux distribution out of that?
588
589- A distribution is a bunch of files
590- In the end, the Nix package manager creates files
591- Let's use Nix to create *every* (non user data) file
592
593## Adding yourself to the environment---Symbolic links
594
595```
596$ ls -l /etc/static/ssh/ssh_config
597/etc/static/ssh/ssh_config -> /nix/store/...-etc-ssh_config
598```
599
600---
601
602```
603$ systemctl cat sshd.service
604
605# /nix/store/...-unit-sshd.service/sshd.service
606# ...
607[Service]
608Environment="LD_LIBRARY_PATH=..."
609Environment="PATH=..."
610
611ExecStart=/nix/store/...-openssh-7.9p1/bin/sshd -f /etc/ssh/sshd_config
612ExecStartPre=/nix/store/...-unit-script-sshd-pre-start
613KillMode=process
614Restart=always
615Type=simple
616```
617
618::: notes
619
620- The service file is in the nix store, especially in its own path!
621- All linked into `/etc/systemd` so systemd can find them
622- The maintainers could have put a nix store path for the sshd_config
623 - The decision was made for sysadmins to be able to quick look their config
624 (`nixpkgs/pull/41744`)
625- The pre start script generates host key if non-existent
626
627
628:::
629
630## Adding yourself to the environment---Environment variables
631
632```
633$ echo $XDG_DATA_DIRS
634/run/opengl-driver/share:
635/run/opengl-driver-32/share:
636/home/minijackson/.nix-profile/share:
637/etc/profiles/per-user/minijackson/share:
638/nix/var/nix/profiles/default/share:
639/run/current-system/sw/share
640```
641
642::: notes
643
644- Inside these dirs are symbolic links
645- Environment variables with hardcoded nix store paths are quite rare in the
646 user environment
647 - When possible, we usually do this in the packaging
648
649
650:::
651
652## Adding yourself to the environment---Tool specific
653
654TODO: find a tool
655
656## How we do it
657
658::: notes
659
660- We talked about how it is possible for NixOS to do it, now we talk about how
661 us devs write the code
662
663
664:::
665
666## Assertions
667
668```
669Failed assertions:
670- services.xserver.xkbOptions = "eurosign:e" is useless on fr/ch
671 layouts and plays badly with bépo
672```
673
674# The embedded world
675
676## TODO
677
678- [x] Use good Markdown / Beamer template
679- [ ] Pinning repo version
680- [x] How to use different versions
681- [ ] How to build an image
682- [ ] Add some images to temporise the talk
683- [ ] Talk about service tests!!!
684 - [ ] Single-node
685 - [ ] Multi-node
686- [ ] Add derivation example with compilation options
687- [ ] Add intro? about problems that I had in Buildroot (non-determinism, no
688 auto-recompile)
689- [ ] Talk about nix-shell
690- [ ] Talk about nixops
691- [ ] Talk about choosing generation at boot
692- [ ] Have a functional programming intro
693- [ ] You **don't** need to run NixOS to develop with Nix
694- [ ] https://r13y.com/
695- [ ] Drawbacks
696 - [ ] Harder to compile anything, especially packages with bad build systems
697 - [ ] If one package doesn't compile, harder to compile the system, since
698 it's a dependency of the system closure
699 - [ ] You need deeper understanding of the ecosystem to package random
700 programs
701 - [ ] Sometimes need to patch software to bypass hardcoded paths (e.g.
702 locale archive)
703 - [ ] For now, only world readable store, makes it kinda harder for
704 passwords and other secrets
705 - Documentation / developer experience is sub-optimal
706- [ ] A burnable image is just a file that depends on every package of your
707 system
708 - [ ] instead of depending manually on each package, we depend on the
709 top-level system closure (output and all dependencies)
710
711## The End {.standout}
712
713That's all folks!
714
715. . .
716
717Questions?