aboutsummaryrefslogtreecommitdiff
path: root/posts/novice_nix:_flake_templates.md
diff options
context:
space:
mode:
Diffstat (limited to 'posts/novice_nix:_flake_templates.md')
-rw-r--r--posts/novice_nix:_flake_templates.md229
1 files changed, 229 insertions, 0 deletions
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 @@
1Flakes are very handy to setup entirely pure,
2project-specific dependencies (not just dependencies, but
3build steps, shell environments and more) in a declarative
4way. Writing Flake expressions can get repetitive though,
5oftentimes, you'd much rather start off with a skeleton.
6Luckily, `nix` already supports templates!
7
8You might already be familiar with `nix flake init`, that
9drops a "default" flake expression into your current working
10directory. If you head over to the manpage:
11
12```
13nix flake init --help
14```
15
16You will read that `nix flake init` creates a flake using
17the "default template". Additionally, you can create a flake
18from a specific template by passing the `-t` flag. Where
19does this default originate from?
20
21## Flake Registries
22
23Quick detour into registries! Registries are a way to alias
24popular flakes using identifiers:
25
26```
27# list a few predefined registries
28$ nix registry list
29. . .
30global flake:nixpkgs github:NixOS/nixpkgs
31global flake:patchelf github:NixOS/patchelf
32global flake:nix-serve github:edolstra/nix-serve
33global flake:templates github:NixOS/templates
34global flake:nickel github:tweag/nickel
35. . .
36
37# you can do
38$ nix flake show nickel
39
40# instead of
41$ nix flake show github:tweag/nickel
42
43# which is short for
44$ nix flake show git+https://github.com/tweag/nickel
45```
46
47You might notice a registry called `templates` aliased to
48`github:NixOS/templates`. Take a peek with `nix flake show`:
49
50```
51$ nix flake show templates
52github:NixOS/templates/79f48a7b822f35c068c5e235da2e9fbd154cecee
53├───defaultTemplate: template: A very basic flake
54└───templates
55 ├───bash-hello: template: An over-engineered Hello World in bash
56 ├───c-hello: template: An over-engineered Hello World in C
57 ├───rust-web-server: template: A Rust web server including a NixOS module
58 ├───simpleContainer: template: A NixOS container running apache-httpd
59 └───trivial: template: A very basic flake
60```
61
62Aha! There is a flake output called `defaultTemplate`. This
63is the template being sourced when you run `nix flake init`.
64Astute readers may conclude the following:
65
66```
67$ nix flake init
68
69# is equivalent to
70$ nix flake init -t templates#defaultTemplate
71
72# is equivalent to
73$ nix flake init -t github:NixOS/templates#defaultTemplate
74
75# which is short for
76$ nix flake init -t git+https://NixOS/templates#defaultTemplate
77```
78
79Similarly, the other templates can be accessed via:
80
81```
82$ nix flake init -t templates#c-hello
83$ nix flake init -t templates#simpleContainer
84# I think you get the drift ...
85```
86
87## Rolling your own templates
88
89Alright, so all we need to do is:
90
91 - create a flake with a `templates` output
92 - populate our template directories with content
93 - (**optionally**) alias our custom templates flake to an
94 identifier using registries, for easier access
95
96Start off by creating a directory to store your templates in
97(we will be converting this to a registry later):
98
99```
100$ mkdir ~/mytemplates
101```
102
103A flake that exposes a "template" as its output looks
104something like this:
105
106```
107# inside ~/mytemplates/flake.nix
108
109{
110 description = "Pepper's flake templates";
111
112 outputs = { self, ... }: {
113 templates = {
114 latex-report = {
115 path = ./latex-report-template;
116 description = "A latex whitepaper project";
117 };
118 rust-hello = {
119 path = ./rust-hello-template;
120 description = "Simple Hello World in Rust";
121 };
122 };
123 };
124}
125```
126
127The `path` attribute to each template is what gets copied
128over when you initialize a flake. Running `nix flake init -t
129.#latex-report` will initialize the current directory with
130the contents of `./latex-report-template` (we are yet to
131populate these directories).
132
133The output of `nix flake show` should be something like:
134
135```
136$ nix flake show
137path:/home/np/code/nix-stuff/template-tests?narHash=sha256-{...}
138└───templates
139 ├───latex-report: template: A latex whitepaper project
140 └───rust-hello: template: Simple Hello World in Rust
141```
142
143Populate your template directories with content, here are my
144template directories for example:
145
146```
147$ tree mytemplates
148mytemplates/
149├── flake.nix
150├── latex-report-template
151│   ├── flake.nix
152│   ├── makefile
153│   └── src
154│   ├── meta.sty
155│   └── report.tex
156└── rust-hello-template
157 ├── Cargo.toml
158 ├── flake.nix
159 └── src
160 └── main.rs
161```
162
163And that's it! Start using your templates with:
164
165```
166$ nix flake init -t ~/mytemplates#rust-hello
167$ tree .
168.
169├── Cargo.toml
170├── flake.nix
171└── src
172 └── main.rs
173```
174
175To avoid writing `~/mytemplates` each time, simply alias it
176to a registry:
177
178```
179# alias it to `biscuits`
180$ nix registry add biscuits ~/mytemplates
181
182# you will see it listed under `user` registries
183$ nix registry list
184. . .
185user flake:biscuits path:/home/np/template-tests
186. . .
187
188$ nix flake init -t biscuits#latex-report
189```
190
191## Extending the official templates
192
193I personally, would like the `biscuits` registry to include
194not just my homemade templates, but also the templates from
195`NixOS/templates` (and maybe a couple of other repositories
196in the wild):
197
198```
199 {
200 description = "Pepper's flake templates";
201
202+ inputs = {
203+ official-templates.url = github:NixOS/templates;
204+ other-templates.url = github:some-other/templates;
205+ };
206
207 outputs = { self, official-templates, other-templates ... }: {
208
209 templates = {
210 latex-report = {
211 path = ./latex-report-template;
212 description = "A latex whitepaper project";
213 };
214 rust-hello = {
215 path = ./rust-hello-template;
216 description = "Simple Hello World in Rust, with overloaded Rust toolchain";
217 };
218 }
219+ // official-templates.templates
220+ // other-templates.templates;
221
222 };
223 }
224```
225
226Running `nix flake show biscuits` will now list templates
227from the `biscuits` registry as well as the ones from
228`NixOS/templates`. Ensure that the names don't collide
229though.