diff options
author | Minijackson <minijackson@riseup.net> | 2019-10-06 19:49:50 +0200 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2019-10-06 19:52:49 +0200 |
commit | 1b4c03ac98ded631108e417f01940b7680ddc4ca (patch) | |
tree | ab347d6bf7fe9b2f4997c44c0cfb00c1939f0334 | |
parent | 34aeabeeb9a02d31baff861aff69bb4308f81bd9 (diff) | |
download | nixos-embedded-slides-1b4c03ac98ded631108e417f01940b7680ddc4ca.tar.gz nixos-embedded-slides-1b4c03ac98ded631108e417f01940b7680ddc4ca.zip |
somewhat final version
-rw-r--r-- | slides.md | 383 |
1 files changed, 314 insertions, 69 deletions
@@ -170,10 +170,10 @@ of the "package function". | |||
170 | 170 | ||
171 | - Use the Nix language to write derivations | 171 | - Use the Nix language to write derivations |
172 | 172 | ||
173 | Derivation | 173 | Derivation: |
174 | : Data structure that describes how to create an output path (file / directory) | 174 | : Data structure that describes how to create an output path (file / directory) |
175 | 175 | ||
176 | - The derivation is compiled into a `.drv` file. | 176 | - The derivation is compiled into a `.drv` file (evaluation). |
177 | - Realising a derivation creates the output path | 177 | - Realising a derivation creates the output path |
178 | - The closure of an output path is the path and all its dependencies | 178 | - The closure of an output path is the path and all its dependencies |
179 | 179 | ||
@@ -213,7 +213,7 @@ of the "package function". | |||
213 | /nix/store/486r3d12gc042yric302jg14in7j3jwm-i3.conf | 213 | /nix/store/486r3d12gc042yric302jg14in7j3jwm-i3.conf |
214 | ``` | 214 | ``` |
215 | 215 | ||
216 | ## Nix---Language (Types){.fragile} | 216 | ## Nix---Language (Types){.fragile .shrink} |
217 | 217 | ||
218 | ```{=latex} | 218 | ```{=latex} |
219 | \begin{minted}{nix} | 219 | \begin{minted}{nix} |
@@ -226,6 +226,7 @@ of the "package function". | |||
226 | initial indentation is removed! | 226 | initial indentation is removed! |
227 | ''; | 227 | ''; |
228 | "attribute set" = { a = 1; b = 2; }; | 228 | "attribute set" = { a = 1; b = 2; }; |
229 | a.b.c = 1; # same as a = { b = { c = 1; }; }; | ||
229 | list = [ 1 2 "hello" ]; | 230 | list = [ 1 2 "hello" ]; |
230 | function = a: toString a; | 231 | function = a: toString a; |
231 | "function w/ named parameters" = { a, b, c ? "default"}: a; | 232 | "function w/ named parameters" = { a, b, c ? "default"}: a; |
@@ -454,10 +455,10 @@ derive2 { | |||
454 | name = "ggplot2"; | 455 | name = "ggplot2"; |
455 | version = "3.2.0"; | 456 | version = "3.2.0"; |
456 | sha256 = "1cvk9pw..."; | 457 | sha256 = "1cvk9pw..."; |
457 | depends = [ digest gtable lazyeval | 458 | depends = [ digest gtable |
458 | MASS mgcv reshape2 rlang | 459 | lazyeval MASS mgcv reshape2 |
459 | scales tibble viridisLite | 460 | rlang scales tibble |
460 | withr ]; | 461 | viridisLite withr ]; |
461 | }; | 462 | }; |
462 | \end{minted} | 463 | \end{minted} |
463 | ``` | 464 | ``` |
@@ -496,9 +497,7 @@ stdenv.mkDerivation rec { | |||
496 | nativeBuildInputs = [ cmake ninja ]; | 497 | nativeBuildInputs = [ cmake ninja ]; |
497 | 498 | ||
498 | cmakeFlags = stdenv.lib.optional (!static) "-DBUILD_SHARED_LIBS=ON"; | 499 | cmakeFlags = stdenv.lib.optional (!static) "-DBUILD_SHARED_LIBS=ON"; |
499 | # src = ...; | 500 | # src = ...; patches = ...; meta = ...; |
500 | # patches = [ ... ]; | ||
501 | # meta = ...; | ||
502 | } | 501 | } |
503 | \end{minted} | 502 | \end{minted} |
504 | ``` | 503 | ``` |
@@ -548,11 +547,11 @@ in | |||
548 | \end{minted} | 547 | \end{minted} |
549 | ``` | 548 | ``` |
550 | 549 | ||
551 | We run: | 550 | - We run: |
552 | 551 | ||
553 | ```{=latex} | 552 | ```{=latex} |
554 | \begin{minted}{console} | 553 | \begin{minted}{console} |
555 | $ nix build --file default.nix | 554 | roger@os $ nix build --file default.nix |
556 | \end{minted} | 555 | \end{minted} |
557 | ``` | 556 | ``` |
558 | 557 | ||
@@ -590,7 +589,7 @@ We get as output path: | |||
590 | 589 | ||
591 | ```{=latex} | 590 | ```{=latex} |
592 | \begin{minted}{console} | 591 | \begin{minted}{console} |
593 | $ ./result/bin/myScript | 592 | slartibartfast@magrathea $ ./result/bin/myScript |
594 | Hello, World! | 593 | Hello, World! |
595 | \end{minted} | 594 | \end{minted} |
596 | ``` | 595 | ``` |
@@ -606,7 +605,7 @@ Hello, World! | |||
606 | 605 | ||
607 | ```{=latex} | 606 | ```{=latex} |
608 | \begin{minted}{console} | 607 | \begin{minted}{console} |
609 | $ ls -l result | 608 | slartibartfast@magrathea $ ls -l result |
610 | result -> /nix/store/a7db5d4v5b2pxppl8drb30ljx9z0kwg0-myScript | 609 | result -> /nix/store/a7db5d4v5b2pxppl8drb30ljx9z0kwg0-myScript |
611 | \end{minted} | 610 | \end{minted} |
612 | ``` | 611 | ``` |
@@ -644,8 +643,7 @@ let | |||
644 | overlays = [ | 643 | overlays = [ |
645 | (self: super: { | 644 | (self: super: { |
646 | myAlias = super.pandoc; | 645 | myAlias = super.pandoc; |
647 | inherit (super.llvmPackages_7) | 646 | inherit (super.llvmPackages_7) clang libclang llvm; |
648 | clang libclang llvm; | ||
649 | myPackage = self.callPackage ./myProject/default.nix { }; | 647 | myPackage = self.callPackage ./myProject/default.nix { }; |
650 | } ) | 648 | } ) |
651 | ]; | 649 | ]; |
@@ -730,6 +728,7 @@ exec -a "$0" "/nix/store/...-kodi-18.1/bin/.kodi-wrapped" \ | |||
730 | 728 | ||
731 | ::: notes | 729 | ::: notes |
732 | 730 | ||
731 | - *Strategic pause* | ||
733 | - This is actually called by another wrapper who tells Kodi where to find its | 732 | - This is actually called by another wrapper who tells Kodi where to find its |
734 | data. | 733 | data. |
735 | - Everything you see here is automated, writing derivations is much much less | 734 | - Everything you see here is automated, writing derivations is much much less |
@@ -742,7 +741,7 @@ exec -a "$0" "/nix/store/...-kodi-18.1/bin/.kodi-wrapped" \ | |||
742 | 741 | ||
743 | ```{=latex} | 742 | ```{=latex} |
744 | \begin{minted}{console} | 743 | \begin{minted}{console} |
745 | $ readelf -d coreutils | 744 | PinkiePie@Equestria $ readelf -d coreutils |
746 | ... | 745 | ... |
747 | Bibliothèque partagée: [librt.so.1] | 746 | Bibliothèque partagée: [librt.so.1] |
748 | Bibliothèque partagée: [libpthread.so.0] | 747 | Bibliothèque partagée: [libpthread.so.0] |
@@ -784,19 +783,47 @@ functools.reduce( | |||
784 | 783 | ||
785 | ::: | 784 | ::: |
786 | 785 | ||
786 | ## Shelling out{.fragile} | ||
787 | |||
788 | ```{=latex} | ||
789 | \begin{minted}{console} | ||
790 | roger@os $ nix-shell '<nixpkgs>' -A openssh | ||
791 | roger@os (nix-shell) $ echo $src | ||
792 | /nix/store/...-openssh-7.9p1.tar.gz | ||
793 | roger@os (nix-shell) $ pkg-config --cflags openssl | ||
794 | -I/nix/store/...-openssl-1.0.2t-dev/include | ||
795 | roger@os (nix-shell) $ unpackPhase | ||
796 | ... | ||
797 | roger@os (nix-shell) $ configurePhase | ||
798 | ... | ||
799 | \end{minted} | ||
800 | ``` | ||
801 | |||
802 | ::: notes | ||
803 | |||
804 | - pkg-config is here because it's in the native build inputs | ||
805 | - There is also the concept of nix-shell scripts, which declare their | ||
806 | dependencies, and Nix will download and provide the dependencies before | ||
807 | running the script. | ||
808 | |||
809 | |||
810 | ::: | ||
811 | |||
787 | # NixOS | 812 | # NixOS |
788 | 813 | ||
789 | ## How do you make a Linux distribution out of that? | 814 | ## How do you make a Linux distribution out of that? |
790 | 815 | ||
791 | - A distribution is a bunch of files | 816 | - A distribution is a bunch of files |
817 | |||
792 | - In the end, the Nix package manager creates files | 818 | - In the end, the Nix package manager creates files |
819 | |||
793 | - Let's use Nix to create *every* (non user data) file | 820 | - Let's use Nix to create *every* (non user data) file |
794 | 821 | ||
795 | ## Adding yourself to the environment---Symbolic links{.fragile} | 822 | ## Adding yourself to the environment---Symbolic links{.fragile} |
796 | 823 | ||
797 | ```{=latex} | 824 | ```{=latex} |
798 | \begin{minted}{console} | 825 | \begin{minted}{console} |
799 | $ ls -l /etc/static/ssh/ssh_config | 826 | roger@os $ ls -l /etc/static/ssh/ssh_config |
800 | /etc/static/ssh/ssh_config -> /nix/store/...-etc-ssh_config | 827 | /etc/static/ssh/ssh_config -> /nix/store/...-etc-ssh_config |
801 | \end{minted} | 828 | \end{minted} |
802 | ``` | 829 | ``` |
@@ -838,7 +865,7 @@ Type=simple | |||
838 | 865 | ||
839 | ```{=latex} | 866 | ```{=latex} |
840 | \begin{minted}{console} | 867 | \begin{minted}{console} |
841 | $ echo $PATH | 868 | roger@os $ echo $PATH |
842 | /home/minijackson/bin: | 869 | /home/minijackson/bin: |
843 | /run/wrappers/bin: | 870 | /run/wrappers/bin: |
844 | /home/minijackson/.nix-profile/bin: | 871 | /home/minijackson/.nix-profile/bin: |
@@ -1010,8 +1037,7 @@ Introducing: the module system! | |||
1010 | 1037 | ||
1011 | ```{=latex} | 1038 | ```{=latex} |
1012 | \begin{minted}{nix} | 1039 | \begin{minted}{nix} |
1013 | { ... }: | 1040 | { ... }: { |
1014 | { | ||
1015 | containers = { | 1041 | containers = { |
1016 | myContainer = { | 1042 | myContainer = { |
1017 | config = { ... }: { services.postgresql.enable = true; }; | 1043 | config = { ... }: { services.postgresql.enable = true; }; |
@@ -1203,7 +1229,7 @@ with lib; | |||
1203 | 1229 | ||
1204 | ::: notes | 1230 | ::: notes |
1205 | 1231 | ||
1206 | Sorry if the formatting is horrible, it had to fit in one slide. | 1232 | - Sorry if the formatting is horrible, it had to fit in one slide. |
1207 | 1233 | ||
1208 | 1234 | ||
1209 | ::: | 1235 | ::: |
@@ -1241,20 +1267,141 @@ Sorry if the formatting is horrible, it had to fit in one slide. | |||
1241 | ## Assertions{.fragile} | 1267 | ## Assertions{.fragile} |
1242 | 1268 | ||
1243 | ```{=latex} | 1269 | ```{=latex} |
1244 | \begin{minted}{text} | 1270 | \begin{minted}{md} |
1245 | Failed assertions: | 1271 | Failed assertions: |
1246 | - services.xserver.xkbOptions = "eurosign:e" is useless on fr/ch | 1272 | - The ‘fileSystems’ option does not specify your root file system. |
1247 | layouts and plays badly with bépo | 1273 | - You must set the option ‘boot.loader.grub.devices’ or |
1274 | 'boot.loader.grub.mirroredBoots' to make the system bootable. | ||
1275 | \end{minted} | ||
1276 | ``` | ||
1277 | |||
1278 | ## More Assertions | ||
1279 | |||
1280 | - *Synaptics and libinput are incompatible, you cannot enable both* (in | ||
1281 | `services.xserver`). | ||
1282 | |||
1283 | - *CONFIG_ZRAM is not built as a module!* (in `zramSwap`) | ||
1284 | |||
1285 | - *Yubikey and GPG Card may not be used at the same time.* (in | ||
1286 | `boot.initrd.luks`) | ||
1287 | |||
1288 | - *Trusted GRUB does not have EFI support* (in `boot.loader.grub`) | ||
1289 | |||
1290 | ## Assertion implementations{.fragile} | ||
1291 | |||
1292 | ```{=latex} | ||
1293 | \begin{minted}{nix} | ||
1294 | # in module configuration | ||
1295 | { | ||
1296 | assertions = [ | ||
1297 | { assertion = any (fs: fs.mountPoint == "/") fileSystems; | ||
1298 | message = "The ‘fileSystems’ option does not specify your root file system."; | ||
1299 | } | ||
1300 | ]; | ||
1301 | } | ||
1302 | \end{minted} | ||
1303 | ``` | ||
1304 | |||
1305 | |||
1306 | ::: notes | ||
1307 | |||
1308 | Yes, these assertions are also a NixOS module! | ||
1309 | |||
1310 | |||
1311 | ::: | ||
1312 | |||
1313 | ## Module tests{.fragile} | ||
1314 | |||
1315 | ```{=latex} | ||
1316 | \begin{minted}{nix} | ||
1317 | import ./make-test.nix ({ ... }: { | ||
1318 | name = "myService"; | ||
1319 | machine = { ... }: { | ||
1320 | services.myService.enable = true; | ||
1321 | }; | ||
1322 | |||
1323 | testScript = '' | ||
1324 | $machine->waitForUnit('myService.service'); | ||
1325 | $machine->waitForOpenPort('1337'); | ||
1326 | $machine->succeed("curl --fail http://localhost:1337/"); | ||
1327 | ''; | ||
1328 | }) | ||
1248 | \end{minted} | 1329 | \end{minted} |
1249 | ``` | 1330 | ``` |
1250 | 1331 | ||
1251 | ## More Assertions{.fragile} | 1332 | ::: notes |
1333 | |||
1334 | - Will create a VM with the given config, and run the Perl script on that | ||
1335 | |||
1336 | |||
1337 | ::: | ||
1252 | 1338 | ||
1253 | ```{=late} | 1339 | ## Module tests, The Empire Strikes Back{.fragile} |
1340 | |||
1341 | ```{=latex} | ||
1254 | \begin{minted}{nix} | 1342 | \begin{minted}{nix} |
1343 | import ./make-test.nix ({ pkgs, ... } : { | ||
1344 | name = "kernel-latest"; | ||
1345 | machine = { pkgs, ... }: { | ||
1346 | boot.kernelPackages = pkgs.linuxPackages_latest; | ||
1347 | }; | ||
1348 | |||
1349 | testScript = '' | ||
1350 | $machine->succeed("uname -s | grep 'Linux'"); | ||
1351 | $machine->succeed("uname -a | grep '${pkgs.linuxPackages_latest.kernel.version}'"); | ||
1352 | ''; | ||
1353 | }) | ||
1354 | \end{minted} | ||
1355 | ``` | ||
1356 | |||
1357 | ## Module tests, Return of the Jedi{.fragile} | ||
1358 | |||
1359 | ```{=latex} | ||
1360 | \begin{minted}[lastline=13]{nix} | ||
1361 | import ./make-test.nix ({ pkgs, ... } : with pkgs.lib; { | ||
1362 | name = "Bridge"; | ||
1363 | nodes.client1 = { pkgs, ... }: { | ||
1364 | virtualisation.vlans = [ 1 ]; | ||
1365 | networking = { | ||
1366 | useDHCP = false; | ||
1367 | interfaces.eth1.ipv4.addresses = [ { | ||
1368 | address = "192.168.1.2/24"; prefixLength = 24 | ||
1369 | } ]; | ||
1370 | }; | ||
1371 | }; | ||
1372 | nodes.client2 = { /* same but in vlan 2 @ 192.168.1.3 */ }; | ||
1373 | nodes.router = { /* bridges the vlans 1 and 2 */ }; | ||
1374 | }) | ||
1255 | \end{minted} | 1375 | \end{minted} |
1256 | ``` | 1376 | ``` |
1257 | 1377 | ||
1378 | ## Module tests, The Phantom Menace{.fragile} | ||
1379 | |||
1380 | Test script: | ||
1381 | |||
1382 | ```{=latex} | ||
1383 | \begin{minted}{perl} | ||
1384 | startAll; | ||
1385 | # Wait for networking to come up | ||
1386 | $client1->waitForUnit("network.target"); | ||
1387 | $client2->waitForUnit("network.target"); | ||
1388 | $router->waitForUnit("network.target"); | ||
1389 | # Test bridging | ||
1390 | $client1->waitUntilSucceeds("ping -c 1 192.168.1.1"); | ||
1391 | $client1->waitUntilSucceeds("ping -c 1 192.168.1.2"); | ||
1392 | $client1->waitUntilSucceeds("ping -c 1 192.168.1.3"); | ||
1393 | # Same with client2 and router | ||
1394 | \end{minted} | ||
1395 | ``` | ||
1396 | |||
1397 | ::: notes | ||
1398 | |||
1399 | - There are even the possibilities of: | ||
1400 | - Taking a screenshot | ||
1401 | - Running OCR on screenshot | ||
1402 | |||
1403 | ::: | ||
1404 | |||
1258 | # The embedded world | 1405 | # The embedded world |
1259 | 1406 | ||
1260 | ## Proper project structure{.fragile} | 1407 | ## Proper project structure{.fragile} |
@@ -1275,61 +1422,159 @@ Failed assertions: | |||
1275 | 1422 | ||
1276 | ```{=latex} | 1423 | ```{=latex} |
1277 | \begin{minted}{console} | 1424 | \begin{minted}{console} |
1278 | $ nix build -f default.nix \ | 1425 | roger@os $ nix build -f default.nix \ |
1279 | -I machine=./machines/MY_BOARD \ | 1426 | -I machine=./machines/MY_BOARD \ |
1280 | -I image=./images/MY_CONFIGURATION | 1427 | -I image=./images/MY_CONFIGURATION |
1281 | \end{minted} | 1428 | \end{minted} |
1282 | ``` | 1429 | ``` |
1283 | 1430 | ||
1284 | ## TODO | 1431 | ## Building an iso image{.fragile} |
1285 | 1432 | ||
1286 | - [x] Use good Markdown / Beamer template | 1433 | ```{=latex} |
1287 | - [ ] Pinning repo version | 1434 | \begin{minted}{nix} |
1288 | - [ ] `a.b.c` = `a = { b = { c = ...; }; };` | 1435 | { ... }: |
1289 | - [x] How to use different versions | 1436 | { |
1290 | - [ ] Modules can call other modules (and that's what they do **all** the time) | 1437 | imports = [ |
1291 | - [ ] How to build an image | 1438 | <nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix> |
1292 | - [ ] Add some images to temporise the talk | 1439 | ]; |
1293 | - [ ] Talk about service tests!!! | 1440 | |
1294 | - [ ] Single-node | 1441 | # ---8<--- |
1295 | - [ ] Multi-node | 1442 | } |
1296 | - [ ] Add derivation example with compilation options | 1443 | \end{minted} |
1297 | - [ ] Add intro? about problems that I had in Buildroot (non-determinism, no | 1444 | ``` |
1298 | auto-recompile) | 1445 | |
1299 | - [ ] Talk about nix-shell | 1446 | ```{=latex} |
1300 | - [ ] Talk about nix-shell scripts | 1447 | \begin{minted}{console} |
1301 | - [ ] Talk about nixops | 1448 | roger@os $ nix build -f default.nix config.system.build.sdImage |
1302 | - [ ] Talk about choosing generation at boot | 1449 | \end{minted} |
1303 | - [ ] Have a functional programming intro | 1450 | ``` |
1304 | - [ ] You **don't** need to run NixOS to develop with Nix | 1451 | |
1305 | - [ ] https://r13y.com/ | 1452 | ::: notes |
1306 | - [ ] Drawbacks | 1453 | |
1307 | - [ ] Harder to compile anything, especially packages with bad build systems | 1454 | - Yes, it's a module again! |
1308 | - [ ] If one package doesn't compile, harder to compile the system, since | 1455 | - In the end an image is just a file that depends on your system |
1309 | it's a dependency of the system closure | 1456 | - The sd-image module just uses the result of the `toplevel` derivation |
1310 | - [ ] You need deeper understanding of the ecosystem to package random | 1457 | |
1311 | programs | 1458 | |
1312 | - [ ] Sometimes need to patch software to bypass hardcoded paths (e.g. | 1459 | ::: |
1313 | locale archive) | 1460 | |
1314 | - [ ] For now, only world readable store, makes it kinda harder for | 1461 | ## Other useful features |
1315 | passwords and other secrets | 1462 | |
1316 | - Documentation / developer experience is sub-optimal | 1463 | - Repository pinning (a.k.a. just clone `nixpkgs`) |
1317 | - [ ] A burnable image is just a file that depends on every package of your | 1464 | |
1318 | system | 1465 | - Cross System (**no need to be on NixOS**) |
1319 | - [ ] instead of depending manually on each package, we depend on the | 1466 | - i686-linux / x86_64-linux |
1320 | top-level system closure (output and all dependencies) | 1467 | - x86_64-darwin (MacOS) |
1321 | 1468 | - *Beta*: aarch64-linux / FreeBSD | |
1322 | ## The End {.standout} | 1469 | |
1470 | - Rollbacks | ||
1471 | |||
1472 | - Declarative deployments (NixOps) | ||
1473 | |||
1474 | ::: notes | ||
1475 | |||
1476 | - To rollback, you can just switch to the previous configuration, either by | ||
1477 | manually changing the config files, or choosing a previous configuration at | ||
1478 | boot | ||
1479 | |||
1480 | ::: | ||
1481 | |||
1482 | # Recap | ||
1483 | |||
1484 | ## 4ever Drawbacks | ||
1485 | |||
1486 | ### Packaging | ||
1487 | |||
1488 | - The language is alien | ||
1489 | - harder (depends on the software / stack) | ||
1490 | - *1304 out of 1321 (98.71%) paths in the minimal installation image are | ||
1491 | reproducible*[^1] | ||
1492 | - You need deeper understanding of the ecosystem | ||
1493 | - Sometimes need to patch software to bypass hardcoded paths (e.g. locale archive) | ||
1494 | - No "smart" recompilation of dependents | ||
1495 | |||
1496 | [^1]: <https://r13y.com/> | ||
1497 | |||
1498 | ::: notes | ||
1499 | |||
1500 | - Not reprodocible paths includes: | ||
1501 | - Python bytecode with timestamps | ||
1502 | - Some autotools | ||
1503 | - EFI stuff | ||
1504 | |||
1505 | ::: | ||
1506 | |||
1507 | ### NixOS | ||
1508 | |||
1509 | - You can't compile part of a system without changing your configuration (all | ||
1510 | or nothing) | ||
1511 | - If something doesn't work, you will need to dive into the abstractions | ||
1512 | - Non POSIX compliant | ||
1513 | |||
1514 | |||
1515 | ::: notes | ||
1516 | |||
1517 | - The final systems depends on the success of all derivations | ||
1518 | - Non POSIX compliant means more work to make some tools work | ||
1519 | - Another way to see it, NixOS does things so differently, and developers don't | ||
1520 | tend to take that into account. | ||
1521 | |||
1522 | |||
1523 | ::: | ||
1524 | |||
1525 | ## Current drawbacks | ||
1526 | |||
1527 | - Documentation / developer experience is sub-optimal | ||
1528 | |||
1529 | - Maturity (especially for Embedded) | ||
1530 | |||
1531 | - For now, only world readable store, makes it kinda harder for passwords and | ||
1532 | other secrets | ||
1533 | |||
1534 | - Cross compilation is not well tested / integrated | ||
1535 | |||
1536 | |||
1537 | ::: notes | ||
1538 | |||
1539 | - Reading the code because the documentation isn't there yet happens way too | ||
1540 | much. | ||
1541 | |||
1542 | |||
1543 | ::: | ||
1544 | |||
1545 | ## Un-talked Advantages | ||
1546 | |||
1547 | - Made out of simple building blocks | ||
1548 | - Makes it possible to develop tools | ||
1549 | - Hydra | ||
1550 | - Safe binary cache | ||
1551 | - Distributed builds | ||
1552 | - Distributed Nix store | ||
1553 | - Very strong Haskell community for some reason :-) | ||
1554 | - Usage as a server or workstation | ||
1555 | - "Works for me" \rightarrow "Works for everybody" | ||
1556 | |||
1557 | |||
1558 | ## The End{.standout} | ||
1323 | 1559 | ||
1324 | That's all folks! | 1560 | That's all folks! |
1325 | 1561 | ||
1326 | --- | 1562 | ## {.standout} |
1327 | 1563 | ||
1328 | Questions? | 1564 | Questions? |
1329 | 1565 | ||
1330 | Slide sources | 1566 | ```{=latex} |
1567 | \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} | ||
1568 | ``` | ||
1569 | |||
1570 | Slide sources: | ||
1331 | ~ <https://github.com/minijackson/nixos-embedded-slides/> | 1571 | ~ <https://github.com/minijackson/nixos-embedded-slides/> |
1332 | 1572 | ||
1573 | |||
1574 | ```{=latex} | ||
1575 | \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} | ||
1576 | ``` | ||
1577 | |||
1333 | :::::: {.columns} | 1578 | :::::: {.columns} |
1334 | ::: {.column width="40%"} | 1579 | ::: {.column width="40%"} |
1335 | 1580 | ||