├── first_steps_with_nix.md ├── first_steps_with_nix_v2.md ├── hello ├── flake.lock ├── flake.nix └── nix.toml ├── my-hello-toml ├── flake.lock └── nix.toml ├── my-hello ├── flake.lock └── flake.nix └── nixpkgs-ng ├── flake.lock └── flake.nix /first_steps_with_nix.md: -------------------------------------------------------------------------------- 1 | # First steps with Nix 2 | 3 | Borrowed from [Cargo documentation](https://doc.rust-lang.org/cargo/getting-started/first-steps.html). 4 | 5 | To start a new project with Nix, use `nix new`: 6 | 7 | ```console 8 | $ nix new --template=templates#hello-world hello/ 9 | ``` 10 | 11 | or 12 | 13 | ```console 14 | $ mkdir hello/ 15 | $ nix init --template=templates#hello-world 16 | ``` 17 | 18 | Nix defaults to `only-flake` template. To use a different template we passed 19 | `--template=hello-world`. To list all available templates use 20 | `nix list-templates` . 21 | 22 | Let's check out what Nix has generated for us: 23 | 24 | ```console 25 | $ cd hello 26 | $ tree . 27 | ├── flake.nix 28 | └── src/ 29 | └── hello.sh 30 | 1 directory, 2 files 31 | ``` 32 | 33 | This is all we need to get started. First, let’s check out `flake.nix`: 34 | 35 | ```nix 36 | { 37 | inputs = 38 | { nixpkgs.url = "nixpkgs/nixos-unstable"; 39 | }; 40 | outpus = { self, nixpkgs }: 41 | let 42 | inherit (nixpkgs.lib) genAttrs; 43 | systems = 44 | [ "x86_64-linux" 45 | "i686-linux" 46 | "x86_64-darwin" 47 | "aarch64-linux" 48 | ]; 49 | forAllSystems = f: genAttrs systems (system: f (import nixpkgs { inherit system; })); 50 | project = pkgs: pkgs.stdenv.mkDerivation 51 | { name = "hello-0.1.0"; 52 | src = self; 53 | buildInputs = [ ]; 54 | buildPhase = '' 55 | echo "Building hello.sh ..." 56 | ''; 57 | installPhase = '' 58 | mkdir -p $out/bin 59 | cp ./src/hello.sh $out/bin 60 | chmod +x $out/bin/hello.sh 61 | ''; 62 | }; 63 | in rec { defaultPackage = packages.hello; 64 | defaultCommand = "./bin/hello.sh"; 65 | packages.hello = forAllSystems project; 66 | }; 67 | } 68 | ``` 69 | This is called a **manifest**, and it contains all of the metadata that Nix 70 | needs to build your project. 71 | 72 | Here's what is in `src/hello.sh`: 73 | 74 | ```bash 75 | echo "Hello, world!" 76 | ``` 77 | 78 | Nix generated a "hello world" project for us. Let's build it: 79 | 80 | ```console 81 | $ nix build 82 | Building hello-0.1.0 (file:///path/to/package/hello) 83 | ``` 84 | 85 | And then run it: 86 | 87 | ```console 88 | $ ./result/bin/hello 89 | Hello, world! 90 | ``` 91 | 92 | We can also use `nix run` to compile and then run it, all in one step: 93 | 94 | ```console 95 | $ nix run 96 | Fresh hello-0.1.0 (file:///path/to/package/hello) 97 | Running `result/bin/hello` 98 | Hello, world! 99 | ``` 100 | 101 | To enter development environment of you project use `nix develop` command: 102 | 103 | ```console 104 | $ nix develop 105 | Developing hello-0.1.0 (file:///path/to/package/hello) 106 | (dev) $ bash src/hello.sh 107 | Hello, world! 108 | (dev) $ # Let's edit `src/hello.sh` with sed and allow for argument to be passed 109 | (dev) $ sed -i -e 's|, world|, ${1:-world}|' src/hello.sh 110 | (dev) $ bash src/hello.sh Nix 111 | Hello, Nix! 112 | ``` 113 | 114 | Sometimes you want to just run a certain build phase inside a development 115 | environment that gives you an opportunity to inspect and retry. You know, the 116 | usual development cycle. 117 | 118 | ```console 119 | $ nix develop --run-phase=check 120 | Developing hello-0.1.0 (file:///path/to/package/hello) 121 | Running phase: check 122 | ... ... 123 | (dev) $ exit 124 | ``` 125 | 126 | Above command can be also used to run build phase and thus having incremental 127 | support for your build. 128 | 129 | ```console 130 | $ nix develop --run-phase=build --exit 131 | Developing hello-0.1.0 (file:///path/to/package/hello) 132 | Running phase: build 133 | Building hello.sh ... 134 | $ 135 | ``` 136 | 137 | 138 | ## Going further 139 | 140 | For more details on using Nix, check out the [Nix Guide](https://nixos.org/learn.html). 141 | -------------------------------------------------------------------------------- /first_steps_with_nix_v2.md: -------------------------------------------------------------------------------- 1 | # First steps with Nix 2 | 3 | Borrowed from [Cargo documentation](https://doc.rust-lang.org/cargo/getting-started/first-steps.html). 4 | 5 | To start a new project with Nix, use `nix new`: 6 | 7 | ```console 8 | $ nix new --template=templates#hello-world hello/ 9 | ``` 10 | 11 | or `nix init` 12 | 13 | ```console 14 | $ mkdir hello/ 15 | $ nix init --template=templates#hello-world 16 | ``` 17 | 18 | Nix defaults to `minimal` template. To use a different template we passed 19 | `--template=hello-world`. 20 | 21 | Let's check out what Nix has generated for us: 22 | 23 | ```console 24 | $ cd hello 25 | $ tree . 26 | ├── flake.toml 27 | └── src/ 28 | └── hello.sh 29 | 1 directory, 2 files 30 | ``` 31 | 32 | This is all we need to get started. First, let’s check out `flake.toml`: 33 | 34 | ```toml 35 | maintainers = [ "Name Surname " ] 36 | description = "A description of a flake" 37 | 38 | [inputs] 39 | nixpkgs = "nixos-unstable" 40 | 41 | [package] # or [[package]] 42 | name = "hello" 43 | version = "0.1.0" 44 | src = "./." 45 | platforms = [ "x86_64-linux" ] 46 | dependencies = [ 47 | "nixpkgs#bash", 48 | ] 49 | buildPhase = """ 50 | echo "Building hello.sh ..." 51 | """ 52 | installPhase = """ 53 | mkdir -p $out/bin 54 | echo -e "#!$(realpath bash)\n$(cat ./src/hello.sh)" > $out/bin/hello 55 | chmod +x $out/bin/hello 56 | """ 57 | ``` 58 | 59 | This is called a **manifest**, and it contains all of the metadata that Nix 60 | needs to build your project. 61 | 62 | Here's what is in `src/hello.sh`: 63 | 64 | ```bash 65 | echo "Hello, world!" 66 | ``` 67 | 68 | Nix generated a "hello world" project for us. Let's build it: 69 | 70 | ```console 71 | $ nix build 72 | Building hello-0.1.0 (file:///path/to/package/hello) 73 | ``` 74 | 75 | And then run it: 76 | 77 | ```console 78 | $ ./result/bin/hello 79 | Hello, world! 80 | ``` 81 | 82 | We can also use `nix run` to compile and then run it, all in one step: 83 | 84 | ```console 85 | $ nix run 86 | Fresh hello-0.1.0 (file:///path/to/package/hello) 87 | Running `result/bin/hello` 88 | Hello, world! 89 | ``` 90 | 91 | To add a additional dependencies to our package use `nix add` command: 92 | 93 | ```console 94 | $ nix add nixpkgs#cowsay 95 | nixpkgs#cowsay added to hello package in ./flake.toml 96 | ``` 97 | 98 | To enter development environment of you project use `nix develop` command: 99 | 100 | ```console 101 | $ nix develop 102 | Developing hello-0.1.0 (file:///path/to/package/hello) 103 | (dev) $ bash src/hello.sh 104 | Hello, world! 105 | (dev) $ sed -i -e "s|echo|cowsay|" src/hello.sh 106 | (dev) $ bash src/hello.sh 107 | _______________ 108 | < Hello, world! > 109 | --------------- 110 | \ ^__^ 111 | \ (oo)\_______ 112 | (__)\ )\/\ 113 | ||----w | 114 | || || 115 | 116 | ``` 117 | 118 | Sometimes you want to just run a certain phase inside a development environment 119 | that gives you an opportunity to inspect and retry. You know, the usual 120 | development cycle. 121 | 122 | ```console 123 | $ nix develop --run-phase=check 124 | Developing hello-0.1.0 (file:///path/to/package/hello) 125 | Running phase: check 126 | ... ... 127 | (dev) $ exit 128 | ``` 129 | 130 | Above command can be also used to run build phase and thus having incremental 131 | support for your build. 132 | 133 | ```console 134 | $ nix develop --run-phase=build --exit 135 | Developing hello-0.1.0 (file:///path/to/package/hello) 136 | Running phase: build 137 | Building hello.sh ... 138 | $ 139 | ``` 140 | 141 | 142 | ## Going further 143 | 144 | For more details on using Nix, check out the [Nix Guide](https://nixos.org/learn.html). 145 | -------------------------------------------------------------------------------- /hello/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1599137069, 6 | "narHash": "sha256-Mdauu2GJZ95DEI8R9CYRPcndSHTINjRET7diOtTbryU=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "f806b3c81b99ea402cad8d641323e61215a855b3", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "id": "nixpkgs", 14 | "type": "indirect" 15 | } 16 | }, 17 | "nixpkgs-ng": { 18 | "inputs": { 19 | "nixpkgs": "nixpkgs" 20 | }, 21 | "locked": { 22 | "dir": "nixpkgs-ng", 23 | "lastModified": 1602794404, 24 | "narHash": "sha256-LhG1NNX037g1nCmSkUKjBmSLjWtvxoQZVtkVCWWgKRQ=", 25 | "owner": "tweag", 26 | "repo": "nix-ux", 27 | "rev": "45dad35f0f7d1ecbe75ae63b9761e430cae77c13", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "dir": "nixpkgs-ng", 32 | "owner": "tweag", 33 | "repo": "nix-ux", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "nixpkgs-ng": "nixpkgs-ng" 40 | } 41 | } 42 | }, 43 | "root": "root", 44 | "version": 7 45 | } 46 | -------------------------------------------------------------------------------- /hello/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs.nixpkgs-ng = { url = github:tweag/nix-ux?dir=nixpkgs-ng; }; 3 | 4 | outputs = { self, nixpkgs-ng }: { 5 | 6 | modules.hello = module { 7 | doc = "A program that prints a friendly greeting."; 8 | 9 | extends = [ nixpkgs-ng.modules.package nixpkgs-ng.modules.stdenv ]; 10 | 11 | options = { 12 | 13 | who = { 14 | default = "World"; 15 | example = "Utrecht"; 16 | doc = "Who to greet."; 17 | }; 18 | 19 | }; 20 | 21 | config = { config }: { 22 | pname = "hello"; 23 | version = "1.12"; 24 | environment.WHO = config.who; 25 | buildCommand = 26 | '' 27 | mkdir -p $out/bin 28 | cat > $out/bin/hello <" ] 3 | description = "A program that prints a friendly greeting" 4 | 5 | [hello] # name of the module 6 | extends = ["package", "stdenv"] # modules that it extends 7 | pname = "hello" # set an option declared by the 'package' module 8 | version = "1.12" # idem 9 | environment.WHO = "World" # set an option declared by the 'derivation' module 10 | buildCommand = """ # idem 11 | mkdir -p $out/bin 12 | cat > $out/bin/hello <" ] 3 | 4 | [inputs] 5 | hello.url = "github:tweag/nix-ux?dir=hello" 6 | 7 | [my-hello] 8 | extends = [ "hello#hello" ] 9 | doc = ''' 10 | A specialized version of the Hello package! 11 | ''' 12 | who = "NixCon" 13 | -------------------------------------------------------------------------------- /my-hello/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "hello": { 4 | "inputs": { 5 | "nixpkgs-ng": "nixpkgs-ng" 6 | }, 7 | "locked": { 8 | "dir": "hello", 9 | "lastModified": 1602794404, 10 | "narHash": "sha256-LhG1NNX037g1nCmSkUKjBmSLjWtvxoQZVtkVCWWgKRQ=", 11 | "owner": "tweag", 12 | "repo": "nix-ux", 13 | "rev": "45dad35f0f7d1ecbe75ae63b9761e430cae77c13", 14 | "type": "github" 15 | }, 16 | "original": { 17 | "dir": "hello", 18 | "owner": "tweag", 19 | "repo": "nix-ux", 20 | "type": "github" 21 | } 22 | }, 23 | "nixpkgs": { 24 | "locked": { 25 | "lastModified": 1599137069, 26 | "narHash": "sha256-Mdauu2GJZ95DEI8R9CYRPcndSHTINjRET7diOtTbryU=", 27 | "owner": "NixOS", 28 | "repo": "nixpkgs", 29 | "rev": "f806b3c81b99ea402cad8d641323e61215a855b3", 30 | "type": "github" 31 | }, 32 | "original": { 33 | "id": "nixpkgs", 34 | "type": "indirect" 35 | } 36 | }, 37 | "nixpkgs-ng": { 38 | "inputs": { 39 | "nixpkgs": "nixpkgs" 40 | }, 41 | "locked": { 42 | "dir": "nixpkgs-ng", 43 | "lastModified": 1600865835, 44 | "narHash": "sha256-atOnS59bKbsFnQXJdv5XHGQzZBp/BFR/7lFzm5NEPFc=", 45 | "owner": "tweag", 46 | "repo": "nix-ux", 47 | "rev": "cbd9b06745b672cf103979477fa496128926cca2", 48 | "type": "github" 49 | }, 50 | "original": { 51 | "dir": "nixpkgs-ng", 52 | "owner": "tweag", 53 | "repo": "nix-ux", 54 | "type": "github" 55 | } 56 | }, 57 | "root": { 58 | "inputs": { 59 | "hello": "hello" 60 | } 61 | } 62 | }, 63 | "root": "root", 64 | "version": 7 65 | } 66 | -------------------------------------------------------------------------------- /my-hello/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs.hello.url = github:tweag/nix-ux?dir=hello; 3 | 4 | outputs = { self, hello }: { 5 | 6 | modules.my-hello = module { 7 | extends = [ hello.modules.hello ]; 8 | config = { config }: { 9 | who = "NixCon"; 10 | }; 11 | }; 12 | 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /nixpkgs-ng/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1599137069, 6 | "narHash": "sha256-Mdauu2GJZ95DEI8R9CYRPcndSHTINjRET7diOtTbryU=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "f806b3c81b99ea402cad8d641323e61215a855b3", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "id": "nixpkgs", 14 | "type": "indirect" 15 | } 16 | }, 17 | "root": { 18 | "inputs": { 19 | "nixpkgs": "nixpkgs" 20 | } 21 | } 22 | }, 23 | "root": "root", 24 | "version": 7 25 | } 26 | -------------------------------------------------------------------------------- /nixpkgs-ng/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | outputs = { self, nixpkgs }: let pkgs = import nixpkgs{ system = "x86_64-linux"; }; in { 3 | 4 | modules.derivation = module { 5 | doc = "A Nix derivation."; 6 | 7 | options = { 8 | 9 | name = { 10 | example = "hello-1.2.3"; 11 | doc = "The name component of the store paths produced by this derivation."; 12 | }; 13 | 14 | system = { 15 | default = "x86_64-linux"; 16 | example = "x86_64-darwin"; 17 | doc = "The platform type on which to build this derivation."; 18 | }; 19 | 20 | derivation = { 21 | doc = "The resulting derivation."; 22 | }; 23 | 24 | environment = { 25 | default = {}; 26 | doc = "Environment variables passed to the builder."; 27 | }; 28 | 29 | # TODO: outputs, builder, args, ... 30 | 31 | buildCommand = { 32 | doc = "The contents of the shell script that builds the derivation."; 33 | }; 34 | 35 | }; 36 | 37 | config = { config }: { 38 | 39 | derivation = derivation ({ 40 | __structuredAttrs = true; 41 | name = config.name; 42 | system = config.system; 43 | builder = "${pkgs.bash}/bin/bash"; 44 | args = [ "-c" ("source .attrs.sh; out=\${outputs[out]}; " + config.buildCommand) ]; 45 | } // config.environment); 46 | 47 | }; 48 | 49 | }; 50 | 51 | modules.stdenv = module { 52 | doc = 53 | '' 54 | This module provides a standard environment for building 55 | packages. 56 | ''; 57 | 58 | extends = [ self.modules.derivation ]; 59 | 60 | config = { config }: { 61 | environment.PATH = "${pkgs.coreutils}/bin:${pkgs.gnutar}/bin"; 62 | }; 63 | }; 64 | 65 | modules.package = module { 66 | doc = "An installable package."; 67 | 68 | extends = [ self.modules.derivation ]; 69 | 70 | options = { 71 | 72 | pname = { 73 | example = "hello"; 74 | doc = "Name of the package."; 75 | }; 76 | 77 | version = { 78 | default = null; 79 | example = "1.2.3"; 80 | doc = "The version of the package. Must be null or start with a digit."; 81 | }; 82 | 83 | }; 84 | 85 | config = { config }: { 86 | name = "${config.pname}${if config.version != null then "-" + config.version else ""}"; 87 | }; 88 | 89 | }; 90 | 91 | modules.bundle = module { 92 | 93 | extends = [ self.modules.derivation ]; 94 | 95 | options = { 96 | 97 | bundle = { 98 | doc = "A derivation that produces a tarball containing the closure of a package."; 99 | }; 100 | 101 | }; 102 | 103 | config = { config } @ outer: { 104 | 105 | bundle = (module { 106 | extends = [ self.modules.stdenv ]; 107 | config = { config }: { 108 | name = "${outer.config.pname}-closure-${outer.config.version}"; 109 | buildCommand = 110 | '' 111 | mkdir $out 112 | tar cvf $out/bundle.tar ${outer.config.derivation} 113 | ''; 114 | }; 115 | }).final.derivation; 116 | 117 | }; 118 | 119 | }; 120 | 121 | }; 122 | } 123 | --------------------------------------------------------------------------------