[00:00.000 --> 00:10.440] All right. Thank you all for coming. [00:10.440 --> 00:14.240] Yeah, I had to fit a 40-minute talk into 20 minutes, [00:14.240 --> 00:15.560] so let's see how it goes. [00:15.560 --> 00:17.480] Sorry. No problem. [00:17.480 --> 00:19.880] Yeah, I want to talk about developer environments, [00:19.880 --> 00:21.040] and I don't mean this room, [00:21.040 --> 00:26.680] but I mean how to get software that we need in a project [00:26.680 --> 00:29.840] together and do it this, obviously, with Nix, [00:29.840 --> 00:31.400] and in a simple way. [00:31.400 --> 00:35.080] And first, just briefly about me. [00:35.080 --> 00:37.520] I started with Gentoo in high school. [00:37.520 --> 00:39.800] I did Google Summer of Code. [00:39.800 --> 00:42.400] Switched in 2012 to NixOS. [00:42.400 --> 00:43.400] Thanks, Florian. [00:43.400 --> 00:45.800] Fris'd off for this. [00:45.800 --> 00:49.920] In 2014, I wrote a pretty viral blog post, [00:49.920 --> 00:51.760] like how we can do better than what [00:51.760 --> 00:54.120] is the current state of software in the world. [00:55.040 --> 00:57.360] Four years later, I created Cashix, [00:57.360 --> 01:03.680] which allows you to host binary caches for open source projects. [01:03.680 --> 01:08.160] I started Nix.dev, which is about 15 tutorials right now, [01:08.160 --> 01:11.000] how to get started with Nix in different ways. [01:11.000 --> 01:13.280] Last year, we kind of restructured the foundation. [01:13.280 --> 01:19.480] I became a bone member, and also I started dev in November. [01:19.480 --> 01:20.560] Very quickly. [01:20.560 --> 01:23.160] So how many of you are using this just to get an idea [01:23.200 --> 01:25.400] to who I'm talking with? [01:25.400 --> 01:27.040] All right, about one third. [01:27.040 --> 01:29.040] That's good. [01:29.040 --> 01:32.560] So like developer environments, right? [01:32.560 --> 01:37.200] A few kind of design decisions are important things. [01:37.200 --> 01:40.760] We want to support all the major kind of operating systems [01:40.760 --> 01:43.560] so that when you have a team of diverse developers [01:43.560 --> 01:48.880] that everyone can go and install it, [01:48.880 --> 01:52.360] we want to have hermicity or determinism [01:52.360 --> 01:55.120] so that if you come to a project, let's say, 10 years later, [01:55.120 --> 01:56.760] it should still kind of work, right? [01:56.760 --> 01:57.640] It should still build. [01:57.640 --> 02:00.600] It should still do exactly what it did 10 years ago. [02:03.600 --> 02:05.400] Yeah, we can talk about that in detail later. [02:05.400 --> 02:08.040] But we want to configure garbage collection. [02:08.040 --> 02:11.880] So Nix, we kind of like just download things. [02:11.880 --> 02:14.400] We don't really remove things by default. [02:14.400 --> 02:17.280] And when we do remove it, we call this garbage collection, [02:17.280 --> 02:20.040] which is an analog to how we handle memory. [02:20.040 --> 02:22.240] So we kind of want to have our developer environment [02:22.240 --> 02:24.040] to take care of that for us. [02:24.040 --> 02:28.120] Because by default, in Nix, it's kind of like an optional thing. [02:28.120 --> 02:30.040] We want to integrate durian of integration, [02:30.040 --> 02:32.280] which is kind of a nice little tool [02:32.280 --> 02:34.040] where you just enter a directory [02:34.040 --> 02:36.280] and it activates something for you. [02:36.280 --> 02:38.080] And you exit and it deactivates that. [02:38.080 --> 02:41.920] So it's kind of like you don't have to run any commands. [02:41.920 --> 02:44.720] And we want a high level abstraction [02:44.720 --> 02:47.240] that we can use to kind of pull things together [02:47.240 --> 02:51.280] and glue them and abstract and have a nice little language, [02:51.320 --> 02:53.240] which we will use here at Nix. [02:53.240 --> 02:56.080] So how does it look in practice? [02:56.080 --> 02:58.920] You create a, I don't know if you can read that from that far, [02:58.920 --> 03:01.400] but you create a devmf.nix file [03:01.400 --> 03:03.160] where you have at the top a little function [03:03.160 --> 03:05.080] that passes in a few parameters. [03:06.000 --> 03:09.480] Most common one that you would want to use is packages. [03:09.480 --> 03:11.560] And then you can define like environment variables, [03:11.560 --> 03:13.440] packages, and kind of like a shell code [03:13.440 --> 03:16.160] that executes once you enter the environment. [03:16.160 --> 03:18.160] And bear in mind, there's no containers or anything. [03:18.160 --> 03:20.080] This is just kind of like, you know, [03:20.080 --> 03:23.440] virtual and on steroids or whatever you want to call it. [03:23.440 --> 03:24.880] And at the bottom, you kind of see like, [03:24.880 --> 03:27.400] okay, let's say there's no git installed. [03:27.400 --> 03:29.560] You kind of say devm shelf. [03:29.560 --> 03:31.480] You see hello determinism and you know, [03:31.480 --> 03:34.280] there's git available in this environment. [03:34.280 --> 03:35.720] And there's like devm search [03:35.720 --> 03:38.360] and you can, for example, search for packages. [03:38.360 --> 03:42.280] This will kind of like search the whole Nix packages [03:42.280 --> 03:44.000] repository that we have and you know, [03:44.000 --> 03:46.160] over 80,000 packages and so on. [03:48.280 --> 03:51.200] This is kind of like, you know, [03:51.200 --> 03:53.640] this is those that are using Nix OS [03:53.640 --> 03:57.760] or Nix Darwin or Home Manager, very familiar with this. [03:57.760 --> 04:02.000] So once you kind of familiarize with how the modules work, [04:02.000 --> 04:05.120] you know, you can switch between different components [04:05.120 --> 04:09.080] and be happily using kind of the same idea [04:09.080 --> 04:10.560] for your operating system. [04:11.640 --> 04:13.520] On the other hand, we kind of want to specify [04:13.520 --> 04:15.200] how these environments are created. [04:15.200 --> 04:17.760] And this is devm.yaml file [04:17.760 --> 04:19.480] where we can specify the inputs. [04:19.480 --> 04:22.920] As I said before, the environment is kind of fixed [04:22.920 --> 04:25.240] according to these inputs, kind of pinned. [04:25.240 --> 04:29.000] And by default, it will use the Nix packages and stable. [04:29.000 --> 04:31.520] But you can customize that, add new inputs and so on. [04:31.520 --> 04:32.560] Inputs can be, you know, [04:32.560 --> 04:35.360] tarble, GitHub repository, whatever you can fetch [04:35.360 --> 04:36.200] from somewhere. [04:39.240 --> 04:41.080] And then we want to have these environments [04:41.080 --> 04:42.120] kind of composable. [04:42.120 --> 04:45.880] So what's happening here is that like, [04:45.880 --> 04:48.000] we have still some inputs, [04:48.000 --> 04:51.360] but we can, for example, fetch the devm repository [04:51.360 --> 04:54.800] and we can reference a devm.nix file [04:54.800 --> 04:58.040] from this GitHub repository, but also like locally. [04:58.040 --> 05:00.200] So like if you have like a typical setup [05:00.200 --> 05:02.200] where front and back end and so on, [05:02.200 --> 05:05.720] or you just have some like general stuff you want to reuse, [05:05.720 --> 05:08.600] you can like pull it in with the inputs [05:08.600 --> 05:12.040] and then say import that developer environment. [05:12.040 --> 05:14.920] And you can kind of like compose these together. [05:16.880 --> 05:20.120] That's more of a already advanced use. [05:20.120 --> 05:22.040] So fast, what does it mean fast? [05:22.040 --> 05:24.320] So in Nix, we have the binary caches idea. [05:24.320 --> 05:27.040] So anything you build, you can upload to binary cache. [05:27.040 --> 05:29.680] And when you say dev and shelf, that will be downloaded. [05:29.680 --> 05:31.560] So as long as everything is downloaded, [05:31.560 --> 05:33.320] this will take usually a second or two [05:33.320 --> 05:35.480] to kind of activate the whole thing. [05:35.480 --> 05:37.280] If not, then possibly a bit longer. [05:38.240 --> 05:40.360] But there's also a CI command, [05:40.360 --> 05:42.280] which you should run on your CI, [05:42.280 --> 05:44.920] which will kind of check that if you say, [05:45.040 --> 05:47.720] there's a way to declare, for example, [05:47.720 --> 05:51.240] Git pre-commit hooks and build packages [05:51.240 --> 05:52.560] and all these things, it will make sure [05:52.560 --> 05:53.400] that everything is good. [05:53.400 --> 05:57.640] So you just run this on CI and upload things to binary cache. [05:57.640 --> 06:01.320] And the next time developer invokes dev and shelf, [06:01.320 --> 06:03.600] things should be there and things should work. [06:05.280 --> 06:07.560] So just briefly the different files. [06:07.560 --> 06:09.160] There's like dev and dot Nix as I said, [06:09.160 --> 06:10.720] there's dev and dot local dot Nix, [06:10.720 --> 06:13.240] which is something that is not committed [06:13.280 --> 06:15.320] to Git repository where you can kind of like [06:15.320 --> 06:16.400] overwrite something. [06:17.880 --> 06:19.360] There's the YAML file. [06:19.360 --> 06:20.440] And then there's the log file. [06:20.440 --> 06:24.040] This is actually dev and uses Nix flakes underneath. [06:24.040 --> 06:28.080] And this will uniquely like pin down your environment [06:28.080 --> 06:30.480] that you should commit to a Git repository [06:30.480 --> 06:34.600] so that if it's generated every time somebody uses dev [06:34.600 --> 06:39.080] and then you will get a different kind of like pinned inputs. [06:39.080 --> 06:41.040] And then there is dot NNFRC, [06:41.040 --> 06:44.280] which is the dear end kind of like glue code [06:44.280 --> 06:47.960] that kind of allows you to hop into different folders [06:47.960 --> 06:51.040] and activate and deactivate these environments. [06:52.000 --> 06:54.320] As I said, there's garbage collection built in. [06:55.880 --> 06:57.520] Yeah, there's many details to it. [06:57.520 --> 06:59.320] There's like a bit of a, [06:59.320 --> 07:01.000] it currently works pretty slowly, [07:01.000 --> 07:03.320] but I think Teofan helped to improve that. [07:03.320 --> 07:07.400] And let's see, we still have to work on improving this bits. [07:08.400 --> 07:10.600] We have right now 36 languages [07:10.720 --> 07:13.880] that you can kind of like just get a basing tooling for. [07:13.880 --> 07:16.640] So you say like languages Python enable, [07:16.640 --> 07:18.920] languages Python virtual enable, [07:18.920 --> 07:20.680] and it will like create this for you. [07:22.400 --> 07:27.400] Type script, and I think most of the top 20 use languages [07:27.480 --> 07:28.260] are supported. [07:31.200 --> 07:34.080] And all right, so to give you a bit more advanced example, [07:34.080 --> 07:37.800] for example Rust, you can say enable Rust, [07:37.800 --> 07:39.160] you can pick a version, you know, [07:39.160 --> 07:42.280] your difficulty level, nightly, latest stable. [07:43.760 --> 07:45.280] We can define some pre-commit hooks. [07:45.280 --> 07:47.160] So for example, if you have four matters, [07:47.160 --> 07:49.360] linters and so on, you can just flip a toggle [07:49.360 --> 07:53.480] and it will kind of configure this for you. [07:53.480 --> 07:56.560] And for example, you can specify packages. [07:56.560 --> 07:58.840] In this case, it's a bit of an advanced case [07:58.840 --> 08:02.640] where you can say that enable security SDK [08:02.640 --> 08:06.840] from Apple in case we are running this on macOS. [08:06.840 --> 08:09.120] And if we're not, then this package will not be added [08:09.120 --> 08:10.520] on Linux, for example. [08:13.040 --> 08:15.640] There's quite a few people who use it for PHP nowadays. [08:15.640 --> 08:18.560] So in PHP, one interesting thing is like [08:18.560 --> 08:21.400] if you enable debug, PHP gets really slow. [08:21.400 --> 08:24.000] So what you want to do is you want to have a PHP [08:24.000 --> 08:25.600] with debug and without debug. [08:25.600 --> 08:28.200] And you know, sometimes you want to use the debug version [08:28.200 --> 08:29.200] and sometimes not. [08:30.480 --> 08:33.360] And here you can see, you can specify like the ini file, [08:33.360 --> 08:35.160] which version of PHP to pull in, [08:35.160 --> 08:37.360] which is kind of useful when you have different projects [08:37.360 --> 08:39.240] that require different versions [08:39.240 --> 08:41.520] and which extensions to enable and so on. [08:45.480 --> 08:48.720] But that's kind of like just providing the basic tooling. [08:48.720 --> 08:51.600] What's usually useful is when we have an environment [08:51.600 --> 08:53.120] that we want to start some processes, [08:53.120 --> 08:55.240] development processes or whatever. [08:55.240 --> 08:57.760] So of course, that's also included [08:57.760 --> 09:01.080] as a declarative interface, so you can set processes [09:01.080 --> 09:03.600] and it's kind of like bash code that you execute. [09:04.600 --> 09:07.800] And the implementation for processes is pluggable. [09:07.800 --> 09:09.200] By default, it uses Honcho, [09:09.200 --> 09:11.720] which is like a four-man implementation [09:11.720 --> 09:14.760] in written in Rust or Python, Rust, I think. [09:15.680 --> 09:17.280] Python, thank you. [09:17.280 --> 09:18.520] But you can plug that in. [09:18.520 --> 09:20.400] There's like Overmind and Hivemind, [09:20.400 --> 09:22.240] which will spawn TMAX processes [09:22.240 --> 09:25.240] that you can then enter and exit and so on. [09:25.240 --> 09:28.400] So you can pick your difficulty level there as well. [09:28.960 --> 09:33.960] And then we can go one abstraction further [09:33.960 --> 09:36.920] and we can say, okay, now we have these processes. [09:36.920 --> 09:38.800] What if we just create recipes [09:38.800 --> 09:41.600] that it will just automatically configure the process for us? [09:41.600 --> 09:44.520] So if I say, for example, Redis enable, [09:44.520 --> 09:46.520] this will just start a Redis process [09:46.520 --> 09:48.440] with some default configuration. [09:48.440 --> 09:50.400] And then you can kind of like, you know, [09:50.400 --> 09:54.600] configure the Redis port or PostgreSQL port and so on. [09:54.600 --> 09:56.800] So any software can be kind of abstracted [09:56.800 --> 09:58.840] on top of those processes. [09:58.840 --> 10:00.320] And we support a bunch of them. [10:00.320 --> 10:02.280] I haven't even listed all of them here. [10:04.720 --> 10:06.320] How much time do I have left? [10:08.080 --> 10:13.080] Yeah, so, and then there's like a bunch of ideas [10:13.520 --> 10:15.720] behind like, for example, [10:15.720 --> 10:18.680] we have like a scripts kind of entry point [10:18.680 --> 10:21.280] where you can kind of define declaratively a script. [10:21.280 --> 10:23.280] In this case, I define my script. [10:24.440 --> 10:26.040] And you know, once you enter your environment, [10:26.040 --> 10:28.640] you can type my script and it will execute this code. [10:30.280 --> 10:32.280] And in there, you can reference the packages [10:32.280 --> 10:33.520] that you specified before, [10:33.520 --> 10:36.640] or you can even hard code them with the NICs, [10:36.640 --> 10:40.840] like how do we call it now, string interpolation feature? [10:40.840 --> 10:43.800] Yes, it used to be called anti-quartation. [10:45.480 --> 10:47.520] Here you can, there's like a nice, [10:47.520 --> 10:51.400] I think it's called host CTL command line [10:51.400 --> 10:54.000] that you can kind of manage hosts on macOS [10:54.200 --> 10:58.200] or Linux, like kind of as a abstract interface. [10:58.200 --> 11:01.080] So we, you can configure hosts. [11:01.080 --> 11:03.880] Again, this does not use containers behind it. [11:03.880 --> 11:07.640] So it will actually manipulate your machine's hosts. [11:08.560 --> 11:10.760] And I think we have kind of a prototype [11:10.760 --> 11:13.760] to provision certificates in this way as well. [11:15.720 --> 11:16.920] But there is no limit to it. [11:16.920 --> 11:18.960] You can take any software, for example, [11:18.960 --> 11:21.000] I don't know if you know Difftastic, [11:21.000 --> 11:23.440] which is like a synthetic, [11:23.440 --> 11:25.080] kind of like a Diffing protocol [11:25.080 --> 11:27.560] that is understands the language [11:27.560 --> 11:31.280] and it tries to do a Diff in a semantic way. [11:31.280 --> 11:33.240] You can just flip a toggle for your project [11:33.240 --> 11:36.960] and it's available for anyone that uses this. [11:36.960 --> 11:38.600] There's DevContainer, for example, [11:38.600 --> 11:41.240] also there that you can use and so on. [11:41.240 --> 11:45.000] So any software can be turned into a toggle [11:45.000 --> 11:47.960] where you can just flip that thing [11:47.960 --> 11:51.680] and your environment has this now available. [11:53.680 --> 11:54.520] All right, that's it. [11:54.520 --> 11:58.520] So I went briefly through all the features of DevEnf [11:58.520 --> 12:01.840] and you can go to that URL. [12:01.840 --> 12:03.440] There's a ton of documentation. [12:03.440 --> 12:06.080] If there's anything unclear, please let me know. [12:06.080 --> 12:08.760] There's also a link to, I think we have a Discord [12:08.760 --> 12:11.320] where you can complain about the lack of documentation [12:11.320 --> 12:13.320] or if something is unclear. [12:13.320 --> 12:14.600] It's really important to me. [12:14.600 --> 12:18.440] So please let me know if you get stuck [12:18.440 --> 12:21.600] or if it's unclear and yeah, [12:21.600 --> 12:25.520] I hope that you'll find it useful. [12:26.800 --> 12:31.800] Okay, we have five minutes. [12:34.160 --> 12:35.600] Five minutes of question. [12:35.600 --> 12:36.600] I saw this one first. [12:36.600 --> 12:38.720] Hi, Domen, thank you very much. [12:38.720 --> 12:42.120] You haven't mentioned the Flakes integration. [12:42.120 --> 12:47.120] How much serious you are with supporting moving with Flakes? [12:49.000 --> 12:54.000] I've submitted all the issues that doesn't work. [12:54.400 --> 12:57.360] Yeah, so Flakes integration for me. [12:57.360 --> 12:58.200] Oh, to repeat the question. [12:58.200 --> 13:00.960] So the question is, there's also Flakes integration. [13:00.960 --> 13:03.080] You don't have to use the common line of DevEnf. [13:03.080 --> 13:05.280] You can use the experimental Flakes [13:06.280 --> 13:10.800] with the DevEnf kind of like modules [13:11.800 --> 13:13.720] and the question was how serious I am. [13:13.720 --> 13:14.560] I'm quite serious. [13:14.560 --> 13:15.640] I don't use it myself. [13:15.640 --> 13:18.280] So I'm serious about like, you know, let's get it in. [13:18.280 --> 13:21.760] Let's get the tests there and let's fix all the issues. [13:21.760 --> 13:24.080] I think we fixed quite a few in the last month. [13:25.240 --> 13:27.760] You know, DevEnf was created like in October [13:27.760 --> 13:30.920] and in November, people started using it widely [13:30.920 --> 13:34.680] and we did a lot of work in the last month and two months. [13:35.720 --> 13:38.560] So the Flakes still need a bit of polishing [13:38.560 --> 13:40.240] but I'm quite serious about it [13:40.240 --> 13:44.000] because I understand that some people want to use more [13:44.000 --> 13:47.400] than just the developer environments and that's great. [13:48.480 --> 13:50.040] But I think to getting the tests in, [13:50.040 --> 13:52.000] that's the crucial bit. [13:58.920 --> 14:03.040] Is it possible to edit in from next? [14:03.040 --> 14:05.200] Like how close is the relationship between the next build [14:05.200 --> 14:06.480] and what goes on in DevEnf? [14:06.480 --> 14:08.520] Like could you say, I want a PHP environment [14:08.520 --> 14:12.360] but I want to edit a dependency of PHP [14:12.360 --> 14:14.720] and have it built from that source. [14:14.720 --> 14:16.880] Ryan, so the question is like, [14:16.880 --> 14:19.560] how does Nick interact with, [14:19.560 --> 14:22.000] if I understand like kind of patching some of the things [14:22.000 --> 14:23.280] that you're pulling in, right? [14:23.280 --> 14:25.280] Yeah, because you could, you fetch your inputs, [14:25.280 --> 14:27.200] like you could defensively fetch some of the updates [14:27.200 --> 14:28.640] here on the board or after you edit them [14:28.640 --> 14:32.040] and then on the fly and build Dev or something like that. [14:32.040 --> 14:36.520] So like, so the answer is kind of two phase. [14:36.520 --> 14:40.160] One is that Nick's is really good at customizing things [14:40.160 --> 14:42.400] and overriding things and patching [14:42.400 --> 14:45.320] and you can take any package and apply a patch to it, [14:45.320 --> 14:46.720] for example, and it will just, [14:46.720 --> 14:49.520] instead of getting it as a binary, it will just compile. [14:50.920 --> 14:52.560] But I don't think there is a really good [14:52.560 --> 14:54.440] and simple interface for this. [14:54.440 --> 14:55.640] I know that like in JavaScript, [14:55.640 --> 14:58.320] there is like patch something package, I think, [14:58.320 --> 15:00.320] which is really nice interface. [15:00.320 --> 15:03.120] So I've been looking into how to integrate that [15:03.120 --> 15:06.120] so that it's really easy to just take software [15:06.120 --> 15:09.040] from somewhere in the world and kind of hack something [15:09.040 --> 15:11.800] on top and override it and do that. [15:11.800 --> 15:14.720] So my answer is it doesn't really exist in an elegant way, [15:14.720 --> 15:17.360] but it's possible to do it right now. [15:17.360 --> 15:18.200] Yeah. [15:19.760 --> 15:22.360] You mentioned DRAMF, is it already integrated [15:22.360 --> 15:25.240] or is it a missing feature? [15:25.240 --> 15:30.120] DRAMF is integrated as long as you, yeah, sorry. [15:30.120 --> 15:32.440] So is DRAMF already integrated? [15:32.440 --> 15:33.280] Yes, it is. [15:34.280 --> 15:36.280] It's, as long as you install it, [15:36.280 --> 15:39.920] then it will, you know, kind of work. [15:39.920 --> 15:42.400] When you say, for example, Devin in it [15:42.400 --> 15:44.920] and it creates a template, it will already use it [15:44.920 --> 15:46.640] and so on as long as you have it installed. [15:46.640 --> 15:49.280] So is it like use Flake or something like that? [15:49.280 --> 15:51.120] No, it will just generate a template for you, [15:51.120 --> 15:52.440] so that's it. [15:52.440 --> 15:53.960] You don't have to do anything. [15:55.200 --> 15:56.040] All right.