From 89b779f6bfbd476d5302e740a4ad3263a15a8974 Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 5 Oct 2021 22:21:58 +0530 Subject: new post: "Novice Nix: Flake Templates" --- posts/novice_nix:_flake_templates.md | 229 +++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 posts/novice_nix:_flake_templates.md (limited to 'posts') diff --git a/posts/novice_nix:_flake_templates.md b/posts/novice_nix:_flake_templates.md new file mode 100644 index 0000000..3b38b46 --- /dev/null +++ b/posts/novice_nix:_flake_templates.md @@ -0,0 +1,229 @@ +Flakes are very handy to setup entirely pure, +project-specific dependencies (not just dependencies, but +build steps, shell environments and more) in a declarative +way. Writing Flake expressions can get repetitive though, +oftentimes, you'd much rather start off with a skeleton. +Luckily, `nix` already supports templates! + +You might already be familiar with `nix flake init`, that +drops a "default" flake expression into your current working +directory. If you head over to the manpage: + +``` +nix flake init --help +``` + +You will read that `nix flake init` creates a flake using +the "default template". Additionally, you can create a flake +from a specific template by passing the `-t` flag. Where +does this default originate from? + +## Flake Registries + +Quick detour into registries! Registries are a way to alias +popular flakes using identifiers: + +``` +# list a few predefined registries +$ nix registry list +. . . +global flake:nixpkgs github:NixOS/nixpkgs +global flake:patchelf github:NixOS/patchelf +global flake:nix-serve github:edolstra/nix-serve +global flake:templates github:NixOS/templates +global flake:nickel github:tweag/nickel +. . . + +# you can do +$ nix flake show nickel + +# instead of +$ nix flake show github:tweag/nickel + +# which is short for +$ nix flake show git+https://github.com/tweag/nickel +``` + +You might notice a registry called `templates` aliased to +`github:NixOS/templates`. Take a peek with `nix flake show`: + +``` +$ nix flake show templates +github:NixOS/templates/79f48a7b822f35c068c5e235da2e9fbd154cecee +├───defaultTemplate: template: A very basic flake +└───templates + ├───bash-hello: template: An over-engineered Hello World in bash + ├───c-hello: template: An over-engineered Hello World in C + ├───rust-web-server: template: A Rust web server including a NixOS module + ├───simpleContainer: template: A NixOS container running apache-httpd + └───trivial: template: A very basic flake +``` + +Aha! There is a flake output called `defaultTemplate`. This +is the template being sourced when you run `nix flake init`. +Astute readers may conclude the following: + +``` +$ nix flake init + +# is equivalent to +$ nix flake init -t templates#defaultTemplate + +# is equivalent to +$ nix flake init -t github:NixOS/templates#defaultTemplate + +# which is short for +$ nix flake init -t git+https://NixOS/templates#defaultTemplate +``` + +Similarly, the other templates can be accessed via: + +``` +$ nix flake init -t templates#c-hello +$ nix flake init -t templates#simpleContainer +# I think you get the drift ... +``` + +## Rolling your own templates + +Alright, so all we need to do is: + + - create a flake with a `templates` output + - populate our template directories with content + - (**optionally**) alias our custom templates flake to an + identifier using registries, for easier access + +Start off by creating a directory to store your templates in +(we will be converting this to a registry later): + +``` +$ mkdir ~/mytemplates +``` + +A flake that exposes a "template" as its output looks +something like this: + +``` +# inside ~/mytemplates/flake.nix + +{ + description = "Pepper's flake templates"; + + outputs = { self, ... }: { + templates = { + latex-report = { + path = ./latex-report-template; + description = "A latex whitepaper project"; + }; + rust-hello = { + path = ./rust-hello-template; + description = "Simple Hello World in Rust"; + }; + }; + }; +} +``` + +The `path` attribute to each template is what gets copied +over when you initialize a flake. Running `nix flake init -t +.#latex-report` will initialize the current directory with +the contents of `./latex-report-template` (we are yet to +populate these directories). + +The output of `nix flake show` should be something like: + +``` +$ nix flake show +path:/home/np/code/nix-stuff/template-tests?narHash=sha256-{...} +└───templates + ├───latex-report: template: A latex whitepaper project + └───rust-hello: template: Simple Hello World in Rust +``` + +Populate your template directories with content, here are my +template directories for example: + +``` +$ tree mytemplates +mytemplates/ +├── flake.nix +├── latex-report-template +│   ├── flake.nix +│   ├── makefile +│   └── src +│   ├── meta.sty +│   └── report.tex +└── rust-hello-template + ├── Cargo.toml + ├── flake.nix + └── src + └── main.rs +``` + +And that's it! Start using your templates with: + +``` +$ nix flake init -t ~/mytemplates#rust-hello +$ tree . +. +├── Cargo.toml +├── flake.nix +└── src + └── main.rs +``` + +To avoid writing `~/mytemplates` each time, simply alias it +to a registry: + +``` +# alias it to `biscuits` +$ nix registry add biscuits ~/mytemplates + +# you will see it listed under `user` registries +$ nix registry list +. . . +user flake:biscuits path:/home/np/template-tests +. . . + +$ nix flake init -t biscuits#latex-report +``` + +## Extending the official templates + +I personally, would like the `biscuits` registry to include +not just my homemade templates, but also the templates from +`NixOS/templates` (and maybe a couple of other repositories +in the wild): + +``` + { + description = "Pepper's flake templates"; + ++ inputs = { ++ official-templates.url = github:NixOS/templates; ++ other-templates.url = github:some-other/templates; ++ }; + + outputs = { self, official-templates, other-templates ... }: { + + templates = { + latex-report = { + path = ./latex-report-template; + description = "A latex whitepaper project"; + }; + rust-hello = { + path = ./rust-hello-template; + description = "Simple Hello World in Rust, with overloaded Rust toolchain"; + }; + } ++ // official-templates.templates ++ // other-templates.templates; + + }; + } +``` + +Running `nix flake show biscuits` will now list templates +from the `biscuits` registry as well as the ones from +`NixOS/templates`. Ensure that the names don't collide +though. -- cgit v1.2.3