Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional, Declarative and Modular System Environment 
with Nix and NixOS

Functional, Declarative and Modular System Environment 
with Nix and NixOS

身為長年的 Linux 使用者,你是否覺得維護作業系統環境是一大困擾?無論是那些套件服務的組態相依、或者那堆針對各個程式打的 patch,這些散落各處、無法被管理或重現的設定是否讓你徹夜難眠:哪天要搬系統怎麼辦?環境壞了是不是很難修?會不會有人偷偷動了我的設定?

又或者你是開發者,常常苦於為新機器設定開發環境都要花上近一整天、或是不同專案倚賴於不同系統套件不知道該如何解決。

Nix 或許可以解決你的煩惱!本議程將簡單介紹 Nix 套件管理工具以及 NixOS 的基本概念:Nix Store、Nix Language、Nix Derivation、Nixpkgs、NixOS、nix-env,來看看 "Purely Functional"、"Declarative" 的 Nix 套件管理工具以及 NixOS 如何解決系統環境問題吧!

個人套件集與 NixOS 設定檔:

- https://github.com/zetavg/nix-packages
- https://github.com/zetavg/nixos-configs

## 參考資料

- [Nix Pills](https://nixos.org/nixos/nix-pills/)
個人最推薦的入門指南,共有 20 篇短篇文章,從安裝、基本使用、原理,一路涵蓋到語言、如何寫套件、一些架構和設計模式,不僅教你如何用 Nix,讀完之後還能任意暴改你的系統以及包裝你自己的 package。
- [Continuous integration for iOS with Nix and Buildkite - Pinterest Engineering](https://medium.com/@Pinterest_Engineering/continuous-integration-for-ios-with-nix-and-buildkite-ef5b36c5292d)
Pinterest 的工程師分享他們如何用 Nix 來統一他們 mobile app 在開發者的機器以及 CI 上的環境,並用 [Buildkite](https://buildkite.com/) 這套 CI Interface as a Service 來打造他們的 CI 環境。
- [Nix: Haskell Concepts for Package Management - HackerNoon.com](https://hackernoon.com/nix-haskell-concepts-for-package-management-65830ac89659)
介紹 Nix 如何利用 Functional、Declarative 的特性,解決傳統系統環境容易被污染、無法版本控管等問題,也提出了每次都要從原始碼編譯很耗時(但我想 binary cache 可以解決這個問題,現在也有很方便的 binary cache as a service,CI 也可以用 Hydra 來獨立測試每個單元,因此除了像是 node 的 npm 一個程式 depend on 數千個 package 會造成就算有 cache 但用正常的方式 handle 數千個 deps 的計算量就很大會慢之外,不算太大的問題)的問題。
- [Eelco Dolstra 在荷蘭烏特勒支大學的博士論文](https://nixos.org/~eelco/pubs/phd-thesis.pdf)
是 Nix 套件管理工具的前身 ([Nix Community - Academia - NixOS Wiki](https://nixos.wiki/wiki/Nix_Community#Academia)) 。
- [Cheatsheet - NixOS Wiki](https://nixos.wiki/index.php?title=Cheatsheet&useskin=vector)
- [How we use Nix at IOHK - Input Output](https://iohk.io/blog/how-we-use-nix-at-iohk/)

## 社群

- [r/NixOS on Reddit](https://www.reddit.com/r/NixOS/)

Pokai Chang

August 17, 2019
Tweet

More Decks by Pokai Chang

Other Decks in Technology

Transcript

  1. VPS

  2. Develop Environment ▪ Your project still have some system dependencies.

    ▪ How to write instructions for setting up the develop environment? ▪ Write automated scripts instead of instructions. ▪ The script can act as documentation.
 (A kind of doc that you can get benefit from without reading it.) ▪ Forgot to check/install something...
 (Especially when you added or updated some dependencies) ▪ Script broken on a different OS distribution or package manager. ▪ Spend three days to onboard a new member with a working development environment.
  3. ???

  4. Nix Store Nix Language / Derivation <nixpkgs> NixOS / nix-env

    /nix-shell { च๜禊盢
 膏戔懯߽䋊 䋿褬ֵአ {
  5. Nix Store Packages should not depend on global system stuff

    /usr/lib libssl.so App ruby-2.5.4 Global Variables Are Evil!
  6. Nix Store Packages can depend on other packages in the

    Nix Store /usr/lib libssl.so App ruby-2.5.4 Nix Store ruby-2.5.4 openssl-1.0.2
  7. Nix Store Nix Store Packages Are Read-only upon Build glibc-2.27

    bash-4.4 zsh-5.7.1 ncurses-6.1 readline-7.0 pcre-8.42 ghc-8.4.4 nodejs-8.15.1 ruby-2.5.4 python-2.7.15
  8. Nix Store: Cryptographic Hash Hash
 Function Source Code Dependencies Build

    Script Build Arguments Environment Variables Build Shell Package Name mn4jdnhkz12a6yd6jg6wvb4mqpxf8q1f Cryptographic Hash
  9. Nix Store This is Possible Same Package Name And "Version"

    bash-4.4 bash-4.4 Cryptographic Hashes are different With Patches
  10. Nix Store: Cryptographic Hash Hash
 Function Source Code Dependencies Build

    Script Build Arguments Environment Variables Build Shell Package Name mn4jdnhkz12a6yd6jg6wvb4mqpxf8q1f { Build Inputs Cryptographic Hash
  11. Nix Store: Cryptographic Hash Hash
 Function Source Code Dependencies Build

    Script Build Arguments Environment Variables Build Shell Package Name mn4jdnhkz12a6yd6jg6wvb4mqpxf8q1f { Build Inputs Cryptographic Hash #PurelyFunctional
  12. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 default.nix let pkgs = import <nixpkgs> { }; in derivation { name = "hello"; system = "x86_64-linux"; builder = "${pkgs.bash}/bin/bash"; args = [ "-c" '' export PATH="${pkgs.coreutils}/bin:${pkgs.gcc}/bin" mkdir $out gcc "${./hello.c}" -o "$out/hello" '' ]; }
  13. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 default.nix let pkgs = import <nixpkgs> { }; in derivation { name = "hello"; system = "x86_64-linux"; builder = "${pkgs.bash}/bin/bash"; args = [ "-c" '' export PATH="${pkgs.coreutils}/bin:${pkgs.gcc}/bin" mkdir $out gcc "${./hello.c}" -o "$out/hello" '' ]; }
  14. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 default.nix let pkgs = import <nixpkgs> { }; in derivation { name = "hello"; system = "x86_64-linux"; builder = "${pkgs.bash}/bin/bash"; args = [ "-c" '' export PATH="${pkgs.coreutils}/bin:${pkgs.gcc}/bin" mkdir $out gcc "${./hello.c}" -o "$out/hello" '' ]; } Build Inputs
  15. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 default.nix let pkgs = import <nixpkgs> { }; in derivation { name = "hello"; system = "x86_64-linux"; builder = "${pkgs.bash}/bin/bash"; args = [ "-c" '' export PATH="${pkgs.coreutils}/bin:${pkgs.gcc}/bin" mkdir $out gcc "${./hello.c}" -o "$out/hello" '' ]; } bash from Nixpkgs gcc from Nixpkgs
  16. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 default.nix let pkgs = import <nixpkgs> { }; in derivation { name = "hello"; system = "x86_64-linux"; builder = "${pkgs.bash}/bin/bash"; args = [ "-c" '' export PATH="${pkgs.coreutils}/bin:${pkgs.gcc}/bin" mkdir $out gcc "${./hello.c}" -o "$out/hello" '' ]; } bash from Nixpkgs gcc from Nixpkgs #Lazy
  17. You can create a custom package collection that adds or

    overrides packages in Nixpkgs https://github.com/zetavg/nix-packages
  18. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 configuration.nix { config, pkgs, lib, ... }: { fileSystems."/home" = { device = "/dev/disk/by-label/home"; }; environment.systemPackages = [ pkgs.git pkgs.vim ]; services.nginx = { enable = true; package = pkgs.nginx.overrideAttrs (oldAttrs: { patches = [ (builtins.toFile "patch" '' --- ./src/core/ngx_conf_file.c +++ ./src/core/ngx_conf_file.c @@ -2,10 +2,10 @@ -#define NGX_CONF_BUFFER 4096 +#define NGX_CONF_BUFFER 131072 '') ]; }); virtualHosts."example.com" = { serverAliases = [ "www.example.com" ]; enableACME = true; forceSSL = true; root = someSitePackage.root; }; }; }
  19. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 configuration.nix { config, pkgs, lib, ... }: { fileSystems."/home" = { device = "/dev/disk/by-label/home"; }; environment.systemPackages = [ pkgs.git pkgs.vim ]; services.nginx = { enable = true; package = pkgs.nginx.overrideAttrs (oldAttrs: { patches = [ (builtins.toFile "patch" '' --- ./src/core/ngx_conf_file.c +++ ./src/core/ngx_conf_file.c @@ -2,10 +2,10 @@ -#define NGX_CONF_BUFFER 4096 +#define NGX_CONF_BUFFER 131072 '') ]; }); virtualHosts."example.com" = { serverAliases = [ "www.example.com" ]; enableACME = true; forceSSL = true; root = someSitePackage.root; }; }; } #Declarative
  20. NixOS Whole System in the Nix Store Nix Store nixos-system

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 pcre-8.42 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 etc etc-user.conf nginx.service ... *Lots of stuff are omitted or simplified to fit in this limited space. nginx.conf
  21. NixOS Switch Between System Versions: Update Nix Store nixos-system-xxx-1 nixos-system-xxx-2

    nixos-system-xxx-3 bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space. nixos rebuild --switch
  22. NixOS Switch Between System Versions Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  23. NixOS Switch Between System Versions Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  24. NixOS Switch Between System Versions Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  25. NixOS Multiple Systems Coexist Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3 bash-interactive-4.4

    glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  26. NixOS Switch Between System Versions Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  27. NixOS Switch Between System Versions Nix Store nixos-system-xxx-1 nixos-system-xxx-2 nixos-system-xxx-3

    bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 pcre-8.42 nginx-1.14.2 passenger-6.0.2 pcre-8.43 openssl-1.1.1 libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 ncurses-6.1 readline-7.0 zlib-1.2.11 *Lots of stuff are omitted or simplified to fit in this limited space.
  28. Nix Store: Cryptographic Hash Hash
 Function Source Code Dependencies Build

    Script Build Arguments Environment Variables Build Shell Package Name mn4jdnhkz12a6yd6jg6wvb4mqpxf8q1f { Build Inputs Cryptographic Hash #PurelyFunctional
  29. NixOS Whole System in the Nix Store nixos-system 42 penssl-1.1.1

    libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 zlib-1.2.11 etc etc-user.conf nginx.service ... *Lots of stuff are omitted or simplified to fit in this limited space. nginx.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 configuration.nix { config, pkgs, lib, ... }: { fileSystems."/home" = { device = "/dev/disk/by-label/home"; }; environment.systemPackages = [ pkgs.git services.nginx = { enable = true; package = pkgs.nginx.overrideAttrs (o patches = [ (builtins.toFile "patch --- ./src/core/ngx_conf_file.c +++ ./src/core/ngx_conf_file.c @@ -2,10 +2,10 @@ -#define NGX_CONF_BUFFER 4096 +#define NGX_CONF_BUFFER 131072 '') ]; }); virtualHosts."example.com" = { serverAliases = [ "www.example.com" #Declarative
  30. NixOS Whole System in the Nix Store nixos-system 42 penssl-1.1.1

    libxslt-1.1.33 libxml2-2.9.9 nginx-1.14.2 zlib-1.2.11 etc etc-user.conf nginx.service ... *Lots of stuff are omitted or simplified to fit in this limited space. nginx.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 configuration.nix { config, pkgs, lib, ... }: { fileSystems."/home" = { device = "/dev/disk/by-label/home"; }; environment.systemPackages = [ pkgs.git services.nginx = { enable = true; package = pkgs.nginx.overrideAttrs (o patches = [ (builtins.toFile "patch --- ./src/core/ngx_conf_file.c +++ ./src/core/ngx_conf_file.c @@ -2,10 +2,10 @@ -#define NGX_CONF_BUFFER 4096 +#define NGX_CONF_BUFFER 131072 '') ]; }); virtualHosts."example.com" = { serverAliases = [ "www.example.com" #Lazy #Declarative
  31. Nix Store Package Removal bash-interactive-4.4 glibc-2.27 bash-4.4 zsh-5.6.2 zsh-5.7.1 ncurses-6.1

    readline-7.0 pcre-8.42 pcre-8.43 GC Roots GC Roots #GarbageCollection
  32. More ▪ Cachix: Nix binary cache as a service ▪

    Hydra: A Nix build farm ▪ NixOps: Use Nix to declaratively deploy infrastructures
  33. Stuff I Done ▪ NixOS on GCP ▪ https://github.com/zetavg/nixos-configs ▪

    https://github.com/zetavg/nix-packages ▪ Phusion Passenger and nginx-mod-passenger ▪ "NPM" implemented with Nix ▪ Patched version of some programms
  34. Recommend Materials ▪ Functional Thursday: Nix and NixOS牧9/5 at Mozilla

    מ嬝玟旰獍ਰ牐 ▪ Nix Pills: https://nixos.org/nixos/nix-pills/
 㮆Ո磧വ萃ጱ獈槹瞲ܖ牧و磪 20 缰Ꭸ缰෈ᒍ牧ℂਞ蕕牏च๜ֵአ牏ܻቘ牧Ӟ ᪠窩荠ک承᥺牏ই֜䌃ॺկ牏Ӟ犚礍䯤޾戔懯秇ୗ牧犋㰍硽֦ই֜አ Nix牧捝 ਠԏ盅螭胼犨఺ู硬֦ጱ羬翄犥现۱蕕֦ᛔ૩ጱ package牐 ▪ Continuous integration for iOS with Nix and Buildkite - Pinterest Engineering
 Pinterest ጱૡ纷䒍獤Ձ犢㮉ই֜አ Nix 㬵翄Ӟ犢㮉 mobile app ࣁ樄咳ᘏጱ秚 瑊犥现 CI Ӥጱ絑ह牧㪔አ Buildkite 蝡ॺ CI Interface as a Service 㬵಑蝨犢 㮉ጱ CI 絑ह牐 ▪ Nix: Haskell Concepts for Package Management - HackerNoon.com
 Օ奧 Nix ই֜ڥአ Functional牏Declarative ጱ粬௔牧薹究㯽翄羬翄絑ह਻ฃ ᤩ࿱礕牏篷ဩ粚๜矒ᓕ缛㺔氂牐 ▪ Eelco Dolstra ࣁ艰葦僂粬ۦඪय़䋊ጱ玡ॊ抷෈
 ฎ Nix ॺկᓕቘૡٍጱ獮蛪牐