8

Novice Nix: Flake Templates

 2 years ago
source link: https://peppe.rs/posts/novice_nix:_flake_templates/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Novice Nix: Flake Templates

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK