about summary refs log tree commit diff
path: root/users/flokli/presentations/2023-09-09-nixcon-tvix/presentation.md
blob: b37554e1881834e8a1c7501dcbef8b289a6015ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
---
author:
- Florian Klink
date: 2023-09-09
title: "Tvix: Status update"
theme: moon
revealOptions:
  transition: 'fade'
---

# Tvix: Status update

![Tvix Logo](tvix-logo.png)

2023-09-09

Florian Klink

---

## Whoami

- flokli
- nixpkgs contributor since 2018, maintaining systemd, nsncd and some
  more stuff
- Freelance Nix/DevOps consultant
- I spend too much time on computers :-)

---

## What is Tvix?

- A new implementation of Nix
- modular
- written in Rust
- developed in the [TVL](https://tvl.fyi) monorepo
- subtree exported to [github:tvlfyi/tvix](https://github.com/tvlfyi/tvix)

---

## Structure

- strong separation between **Evaluator**, **Store** and **Builder**
- Defined interfaces between different components (Protobuf/gRPC) <!-- .element: class="fragment" -->
  - Allows adding to/combining with your own components <!-- .element: class="fragment" -->
- <!-- .element: class="fragment" --> A lot of helper code for some of the Nix internals in the `nix-compat` crate

Note: Derivation types, serializers. NAR writers, nixbase32 enc/dec, Nix Hash function, stringparsing etc.

----

![crate-deps.svg](crate-deps.svg)

---

## Evaluator: Design

- <!-- .element: class="fragment" --> 
  Nix code is parsed via [rnix](https://github.com/nix-community/rnix-parser)
- <!-- .element: class="fragment" -->
  AST traversal, generate bytecode (with some transformations)
- <!-- .element: class="fragment" -->
  Bytecode is executed by an abstract machine with a Nix-specific instruction set

----

## Evaluator: Design

- <!-- .element: class="fragment" -->
  Builtins are separate from the "evaluator core"
  - <!-- .element: class="fragment" -->
    inject your own builtins
  - <!-- .element: class="fragment" -->
    this includes `builtins.derivation`!
- <!-- .element: class="fragment" -->
  IO is nicely abstracted away
  - <!-- .element: class="fragment" -->
    We can run a Nixlang subset without IO in wasm (see [tvixbolt](https://bolt.tvix.dev/)),
    or parse Nix into a config struct with `tvix-serde`

----

<!-- <video class="r-stretch" src="./tvixbolt.webm"></video> -->
<a href="./tvixbolt.webm">Tvixbolt Demo</a>

----

### Evaluator: Current Work

- <!-- .element: class="fragment" -->
  Current goal: **evaluate nixpkgs the same way as Nix does**
- <!-- .element: class="fragment" -->
  Checked by comparing the calculated output paths, which checks correctness of all \"parent\" output paths too.
- <!-- .element: class="fragment" -->
  Required implementing a lot of Nix internals in `nix-compat`, and `tvix-store` (A-Term, hash modulo, NAR writer/hasher)

Note: Getting output hashing correct, and exposing this in a re-usable fashion took quite some iterations to get right.

----

### Evaluator: Current Work (cont.)
- <!-- .element: class="fragment" -->
  🎉 Already correct for (and continously checked by CI on every commit):
  - <!-- .element: class="fragment" -->
  `stdenv`, `hello`
  - <!-- .element: class="fragment" -->
  `pkgsCross.aarch64-multiplatform.stdenv`, `pkgsCross.aarch64-multiplatform.hello`
- <!-- .element: class="fragment" -->
  Some work left for more complicated expressions
  - <!-- .element: class="fragment" -->
    infinite recursion [when inheriting from a `builtins.tryEval` multiple times](https://b.tvl.fyi/281)
  - <!-- .element: class="fragment" -->
    small details around file imports
- <!-- .element: class="fragment" -->
  Not too much performance finetuning until we're correct first.

----

### Evaluator: Demo

[![asciicast](https://asciinema.org/a/MH4tuVPLsKewJSGJUYEyIKUpj.svg)](https://asciinema.org/a/MH4tuVPLsKewJSGJUYEyIKUpj)

---

## Store: Design

- <!-- .element: class="fragment" -->
  Uses a very different underlying data model:
  - <!-- .element: class="fragment" -->
    Nix stores on a per- `StorePath` granularity
  - <!-- .element: class="fragment" -->
    tvix-store uses a Merkle DAG of directories, similar to git trees, but with [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) digests as pointers.
  - <!-- .element: class="fragment" -->
    Compat layer in front to still render/calculate NAR on demand where needed
  - <!-- .element: class="fragment" -->
    Substitution, caching, ... possible to describe via composition/layering

----

![tvix-store graph](tvix-store-graph.svg)

----

### Store: Advantages

- <!-- .element: class="fragment" -->
  Less downloading of data that didn't change
- <!-- .element: class="fragment" -->
  Less duplicate data on disk/storage
- <!-- .element: class="fragment" -->
  Inherently content-addressed, so P2P substitution possible
- <!-- .element: class="fragment" -->
  Allows doing verified blob streaming ([BAO](https://github.com/oconnor663/bao), [bao-tree](https://github.com/n0-computer/bao-tree))
- <!-- .element: class="fragment" -->
  Protocol has some \"smarter\" methods to avoid roundtrips, but could all be statically pre-rendered
- <!-- .element: class="fragment" -->
  Very little data that needs to be fetched from a trusted party (or be signed)

Note: Our way of addressing blobs by their raw blake3 digest is natively compatible with iroh, the IPFS Re-implementation in Rust

----

### Store: Status

- <!-- .element: class="fragment" -->
  Whole Merkle-based store implementation (and Nix NAR compat layer) is there
  - <!-- .element: class="fragment" -->
    exercised by the output path CI tests, and a test suite.
  - <!-- .element: class="fragment" -->
    three backends (Sled, in-memory, gRPC client)
  - <!-- .element: class="fragment" -->
    more backends and more test suites planned.
- <!-- .element: class="fragment" -->
  FUSE filesystem to expose the store (to Tvix Builders, \"appliances\") <!-- .element: class="fragment" -->

Note: backends: RocksDB, sqlite, s3. fuse: lazy fetching of build input files | think about a minimal initrd to bring up network and mount the store, then run any closure.

----

### Store: Demo

[![asciicast](https://asciinema.org/a/YFB9yycHdx0OUH9N0WdAkIYua.svg)](https://asciinema.org/a/YFB9yycHdx0OUH9N0WdAkIYua)

----

### Store: Status (cont.)
- <!-- .element: class="fragment" -->
  More work on store composition needed (necessary for substition and caching)
- <!-- .element: class="fragment" -->
  More work on more granular blob substititon needed.
- <!-- .element: class="fragment" -->
  More work on bridges with Nix needed
  - <!-- .element: class="fragment" -->
    Get Nix to talk to a tvix-store
  - <!-- .element: class="fragment" -->
    Expose existing binary caches to tvix-store

---

### Builder: Design

- <!-- .element: class="fragment" -->
  Build requests/Build protocol is less Nix-specific
  - <!-- .element: class="fragment" -->
    allows reusing builders for other usages (non-sandboxed builds, other build systems, playing with other addressing mechanisms)
- <!-- .element: class="fragment" -->
  Distinction between a **specific build attempt** and the **general build recipe**
  - <!-- .element: class="fragment" -->
    allows keeping metadata about failed builds
  - <!-- .element: class="fragment" -->
    stats (memory/cpu consumption)
  - <!-- .element: class="fragment" -->
    comparing different produced binary outputs (r11y)

----

### Builder: Design

- <!-- .element: class="fragment" -->
  Invididual builds can be run in your desired container/virt engine/scheduler, as long as it speaks the same Build API
- <!-- .element: class="fragment" -->
  Build API composition/proxying, similar to Store composition
- <!-- .element: class="fragment" -->
  allows "unattended building" (evaluate nixpkgs locally and send all build requests to a remote builder)
- <!-- .element: class="fragment" -->
  allows tailing logs from currently/already running builds

----

### Builder: Status

- <!-- .element: class="fragment" -->
  Dummy Builder implementation in `go-nix` (using OCI)
- <!-- .element: class="fragment" -->
  Some scribble notes on the Build Protocol
- <!-- .element: class="fragment" -->
  Glue code to trigger builds from inside `builtins.derivation` needs to be written
- <!-- .element: class="fragment" -->
  Builder implementation (using `systemd-nspwan` or some container engine needs to be written.
- <!-- .element: class="fragment" -->
  Web interface to visualize store contents and build graphs/builds/logs

---

## Contributing

- <!-- .element: class="fragment" -->
  Join the IRC channel (`#tvl` on `hackint`), bridged to Matrix and XMPP
- <!-- .element: class="fragment" -->
  Check our issue tracker
- <!-- .element: class="fragment" -->
  Try to use it and tell us how you broke it!
- <!-- .element: class="fragment" -->
  Add various Nix bits to `nix-compat`

Note: or if you like what you seeing and want to sponsor parts, that's also cool :-)

---

# Thanks to...

- <!-- .element: class="fragment" -->
  all TVL contributors (some drive-by, some long-term contributors)
- <!-- .element: class="fragment" -->
  countless Nix community members for their input on the architecture and rubberducking
- <!-- .element: class="fragment" -->
  NLNET and others to sponsor parts of this

----

# Questions?

<style>
.container{
    display: flex;
}
.col{
    flex: 1;
}
</style>

<div class="container">

<div class="col">
Florian Klink / <a href="https://flokli.de">flokli.de</a><br />
<img src="qrcode-flokli.svg" />
</div>

<div class="col">
Tvix / <a href="https://tvix.dev">tvix.dev</a><br />
<img src="qrcode-tvix.svg" />
</div>

</div>