diff options
Diffstat (limited to 'posts')
-rw-r--r-- | posts/novice_nix:_flake_templates.md | 229 |
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 @@ | |||
1 | Flakes are very handy to setup entirely pure, | ||
2 | project-specific dependencies (not just dependencies, but | ||
3 | build steps, shell environments and more) in a declarative | ||
4 | way. Writing Flake expressions can get repetitive though, | ||
5 | oftentimes, you'd much rather start off with a skeleton. | ||
6 | Luckily, `nix` already supports templates! | ||
7 | |||
8 | You might already be familiar with `nix flake init`, that | ||
9 | drops a "default" flake expression into your current working | ||
10 | directory. If you head over to the manpage: | ||
11 | |||
12 | ``` | ||
13 | nix flake init --help | ||
14 | ``` | ||
15 | |||
16 | You will read that `nix flake init` creates a flake using | ||
17 | the "default template". Additionally, you can create a flake | ||
18 | from a specific template by passing the `-t` flag. Where | ||
19 | does this default originate from? | ||
20 | |||
21 | ## Flake Registries | ||
22 | |||
23 | Quick detour into registries! Registries are a way to alias | ||
24 | popular flakes using identifiers: | ||
25 | |||
26 | ``` | ||
27 | # list a few predefined registries | ||
28 | $ nix registry list | ||
29 | . . . | ||
30 | global flake:nixpkgs github:NixOS/nixpkgs | ||
31 | global flake:patchelf github:NixOS/patchelf | ||
32 | global flake:nix-serve github:edolstra/nix-serve | ||
33 | global flake:templates github:NixOS/templates | ||
34 | global 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 | |||
47 | You 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 | ||
52 | github: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 | |||
62 | Aha! There is a flake output called `defaultTemplate`. This | ||
63 | is the template being sourced when you run `nix flake init`. | ||
64 | Astute 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 | |||
79 | Similarly, 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 | |||
89 | Alright, 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 | |||
96 | Start 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 | |||
103 | A flake that exposes a "template" as its output looks | ||
104 | something 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 | |||
127 | The `path` attribute to each template is what gets copied | ||
128 | over when you initialize a flake. Running `nix flake init -t | ||
129 | .#latex-report` will initialize the current directory with | ||
130 | the contents of `./latex-report-template` (we are yet to | ||
131 | populate these directories). | ||
132 | |||
133 | The output of `nix flake show` should be something like: | ||
134 | |||
135 | ``` | ||
136 | $ nix flake show | ||
137 | path:/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 | |||
143 | Populate your template directories with content, here are my | ||
144 | template directories for example: | ||
145 | |||
146 | ``` | ||
147 | $ tree mytemplates | ||
148 | mytemplates/ | ||
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 | |||
163 | And 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 | |||
175 | To avoid writing `~/mytemplates` each time, simply alias it | ||
176 | to 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 | . . . | ||
185 | user 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 | |||
193 | I personally, would like the `biscuits` registry to include | ||
194 | not just my homemade templates, but also the templates from | ||
195 | `NixOS/templates` (and maybe a couple of other repositories | ||
196 | in 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 | |||
226 | Running `nix flake show biscuits` will now list templates | ||
227 | from the `biscuits` registry as well as the ones from | ||
228 | `NixOS/templates`. Ensure that the names don't collide | ||
229 | though. | ||