We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Nix Flakes

00:00

Formal Metadata

Title
Nix Flakes
Title of Series
Number of Parts
19
Author
License
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
This talk will give an overview of Nix flakes, a proposed mechanism to package Nix expressions into composable entities ("flakes"). Flakes allow hermetic, reproducible evaluation of multi-repository Nix projects; impose a discoverable, standard structure on Nix projects; and replace previous mechanisms such as Nix channels and the Nix search path. This talk will discuss the current state of the flakes project and possible future developments.
MultiplicationData structureElectric currentQuery languageSemantics (computer science)Repository (publishing)Revision controlVariable (mathematics)Integrated development environmentPerformance appraisalRegulärer Ausdruck <Textverarbeitung>Cache (computing)Attribute grammarSoftware repositoryNP-hardRevision controlRepository (publishing)Performance appraisalExpressionResultantInterface (computing)Physical systemMultiplicationData managementSoftware testingMixed realityStandard deviationConfiguration spaceCache (computing)Variable (mathematics)Disk read-and-write headIntegrated development environmentComputer fileModule (mathematics)Subject indexingDefault (computer science)CloningGastropod shellFormal languageBitLibrary (computing)Set (mathematics)Process (computing)Functional (mathematics)Projective planeData structureOrder (biology)BuildingMachine visionFile systemConnectivity (graph theory)Functional programmingDifferent (Kate Ryan album)Software developerUniform resource locatorRight angleMultiplication signExtension (kinesiology)Information securityMoving averageCore dumpService (economics)Goodness of fitUser interfaceNP-hardPersonal identification numberAuthorizationComputer animation
Electric currentConsistencyInterface (computing)Common Language InfrastructureRevision controlPatch (Unix)Windows RegistryCloningInstallation artUser profilePrice indexData structureRevision controlComputer fileMathematicsProfil (magazine)Installation artAttribute grammarWindows RegistryDifferent (Kate Ryan album)Uniform resource locatorOverlay-NetzBitBranch (computer science)Projective planeCloningPoint (geometry)Function (mathematics)Variable (mathematics)Patch (Unix)View (database)Software developerPersonal identification numberPosition operatorRepository (publishing)FreewareMixed realityDisk read-and-write headPerspective (visual)Default (computer science)NumberGastropod shellMoment (mathematics)Directory serviceService (economics)CASE <Informatik>QuicksortResultantIdeal (ethics)FlagMultiplicationHome pageUser interfaceDeclarative programmingMappingImperative programmingMultiplication signSoftware testingUsabilityHash functionModule (mathematics)Integrated development environmentOcean currentIdentifiabilityDerivation (linguistics)Type theoryDot productBuildingComputer animation
CloningPrice indexHome pageMetadataRepository (publishing)Physical systemInformationConfiguration spaceDefault (computer science)Derivation (linguistics)Modul <Datentyp>Integrated development environmentComputer fileAsynchronous Transfer ModePerformance appraisalHash functionRevision controlContent (media)outputState of matterData typeContinuous integrationVirtual machineOverlay-NetzSystem programmingBinary fileFunction (mathematics)Module (mathematics)File formatComputer fileoutputMusical ensembleBootingFeedbackLine (geometry)ExpressionProjective planeOverlay-NetzCloningConfiguration spaceCorrespondence (mathematics)Process (computing)Formal languageMultiplication signPoint (geometry)Field (computer science)AdditionDescriptive statisticsSystem callRevision controlScripting languageRepository (publishing)Gastropod shellLevel (video gaming)Server (computing)Wrapper (data mining)Integrated development environmentBitDerivation (linguistics)Attribute grammarMapping1 (number)Windows RegistryUniform resource locatorSet (mathematics)FlagMetadataMereologyDot productModulare ProgrammierungDefault (computer science)Data loggerParameter (computer programming)Semantics (computer science)InformationFile systemHome pageWeb 2.0Physical systemInternet service providerFunctional (mathematics)BuildingComputer animation
Configuration spaceInformationHome pageState of matterData typeContinuous integrationHome pageComputer fileComputing platformContext awarenessFlagSubject indexingCASE <Informatik>Function (mathematics)Revision controlCodeLine (geometry)BitAffine spacePhysical systemCross-platformConfiguration spaceSoftware repositoryQuicksortMultiplication signToken ringParameter (computer programming)Data storage deviceAttribute grammarMechanism designGame controllerFile archiverNormal (geometry)DemonComputer architectureModule (mathematics)Content (media)Overlay-NetzKey (cryptography)Repository (publishing)Dependent and independent variablesAuthorizationINTEGRALRight angleInstance (computer science)AuthenticationSoftware testingAngular resolutionPersonal identification numberBuildingLevel (video gaming)1 (number)Computer animation
Transcript: English(auto-generated)
Next up is our own Elko Dostra, the author of Nyx, with his Nyx flakes talk.
Give him a hand everyone. Can you hear me? Good sound.
Testing, testing. Sounds good. Like this.
Alright, so thank you all for coming. Welcome to NyxCon. And by the way, let me first give a big shout out to our release managers, Samuel and Linus, and everybody else who contributed to a really great release, extremely smooth. So yeah, it's really incredible to see that happening.
So yeah, this talk is about Nyx flakes, which is a new experimental feature in Nyx. It actually came out of a talk given by Shea Levy at last year's NyxCon about require.nyx. So that was about essentially being able to compose Nyx-based projects in multiple repositories,
making them more discoverable and giving them a standard structure. And yeah, that's something that I really wanted for a long time, and also address a bunch of other big problems that we've had in Nyx for years.
So yeah, for the last year I've been hacking on that. And so that has actually been funded by Shea's company, Target. So they've been paying my employer, Tweak, to work on that.
So let me first talk a bit about all the problems that we're trying to solve here, because there are quite a few. So very briefly, flakes are a way to package your Nyx files. So that might sound a bit strange, because Nyx is already a package manager, but it's a bit embarrassing.
So it's a very nice package manager, but it's not very good at actually packaging its own stuff. So Nyx expressions, well, I mean, we've had these things called channels, but other than that, and channels don't work very well, but other than that, yeah, getting your Nyx expressions to users or to other developers is kind of a mess.
So let's go through all these problems. So one problem that we've had is if you have a large system spread out across multiple repositories, then it's not convenient to build that with Nyx.
So, for example, at the previous job, we had this big system that was actually, so it was a multi-repo project, so it had components spread across, I think, dozens of repositories. So just building that system meant you had to more or less manually check out all those repositories, make sure that they're in the right place, maybe set up the Nyx path environment variable,
because these repositories were all depending on each other through Nyx path or just importing each other via dot dot slash, so every repository had to be in the right location relative to each other, and that's not a nice developer experience.
So basically, if you need a readme.md explaining how to build a project, you've already failed. So, for example, if you check out a Rust project, you can just do cargo builds and it will always work. And with a Nyx project, everything had a different convention,
and everybody developed their own ways of doing these things, so that's not good. So the vision here is that any Nyx-based project should be able to do a git clone and run Nyx build, and it should work. So related to that is that Nyx projects don't really have a standard structure.
As are a few conventions, you might have a shell dot Nyx file or a release dot Nyx file for your Hydra jobs, or maybe a default dot Nyx, but actually default dot Nyx doesn't actually have a standard structure, as it's not defined whether that's one package or a set of packages or arbitrary other stuff,
so, for example, all packages dot Nyx in Nyx packages is some weird mix of packages and library functions and builders. And then there are things like NyxOS modules, where there is really no convention,
so if you have a project that provides a NyxOS module, there is no convention on what that file should be named like and how you should pull it into your own system configuration. So we want to have a standard structure, just like, say, you have a cargo.toml in a Rust project,
there should be a standard interface to a Nyx-based project. So another goal is improving reproducibility. So a bit of another embarrassing thing about Nyx is that it pioneered reproducible builds,
but the evaluation of Nyx expressions themselves is not all that reproducible, despite the fact that it's a purely functional language. So the problem is not so much the purity of the language, but the fact that evaluation is not hermetic.
So a Nyx expression can pull in arbitrary files from your file system. So for example, it can, something that happens in Nyx packages, it will read in .config slash Nyx packages slash config dot Nyx or something like that. So that means that if two people check out the same repository and do a Nyx build on that,
they might get a different result, which is obviously a bad thing. And there are other sources of contamination, like using environment variables or calling fetchgit to fetch a git repository without specifying a revision,
so then it will just fetch the latest head revision. So yeah, that's not reproducible. And that also has implications like how you cannot cache evaluation results persistently. So the goal of flakes is if two people have built the same flake, they will always get the same result.
So another goal is replacing Nyx channel. So Nyx channel is the main way that we distribute Nyx packages and NyxOS to users,
but it's pretty limited. So it's hard to actually create a channel. I mean, it's not really that hard. I mean, it's just a tarball containing a dump of your repository, but just creating that thing is not something you want to do. You just want to point somebody at a git repository and it should just work.
So with Nyx channel, you also cannot easily pin a channel to a specific version. You can only say Nyx channel update and they will get the latest channel, but you cannot roll back to a previous version. Channels don't really auto-update, so that's kind of the opposite of pinning.
So if you don't run Nyx channel dash dash updates, then your system doesn't, or nothing updates at all, and that might not be what you want because you don't get any security fixes or other fixes. And they're completely self-contained, so channels cannot express dependencies on other channels,
which basically means that they're only useful for distributing Nyx packages because Nyx package is the only thing that doesn't depend on other repositories. Most other Nyx projects will depend on Nyx packages, so that means you can't really use them as a channel. I mean, you can hack things, or you can use the Nyx search path,
but then you're back to that problem of reproducibility. So yeah, we need to provide something nicer than Nyx channels. And then finally, we actually, I mean that's an extension of replacing Nyx channel, but we actually need to finish the Nyx CLI.
So this one command replacement for all the existing Nyx tools was actually something I first proposed at the first NyxCon in Berlin. And so, embarrassingly, we're still not there yet. So it doesn't have a replacement for Nyx ENV, Nyx shell and Nyx channel.
And actually, one major blocker there was that, well, so these commands, so they try to provide a unified interface for all these commands. So the old interface, for example, Nyx ENV and Nyx build have a completely different user interface. They have a completely different way of referring to packages.
So Nyx ENV uses package names, and Nyx build uses attribute names. And yeah, and Nyx channel, of course, is completely different. So the goal there was to unify these things, but it was always a blocker that,
I mean, I had in my head that Nyx channel is a mess, and Nyx path is a mess. So we need a replacement for that. So we need to have a good answer to the question of what does Nyx build, Nyx packages dot hello mean. So currently it means, well, look up Nyx packages in the search path,
so in the Nyx path environment variable, and probably that's populated using the Nyx channel command. So that's where you get your Nyx packages from. But so that has all these previous problems, so we need a better answer to that. So yeah, so flake provides an answer to that.
All right, so now let's get to the actual solution. So first before actually diving into what a flake looks like, let's look at it from a developer point of view. But very briefly, a flake is just, well, simply put, it's just a git repository that has a flake dot nyx file in it.
And the flake dot nyx file describes what that thing describes, like Nyx packages or modules or overlays or containers. Basically any kind of Nyx values, but it provides some standardized structure to them.
So suppose that we want to run Rust from Nyx packages. So yeah, you would say Nyx run, Nyx packages hash Rust C and then dash C Rust C dash version, so you run it. So this is almost exactly the same as what you would do in old school Nyx.
So the only difference is that the dot has changed into a hash, so you say Nyx packages hash Rust C instead of dot Rust C. But it does something completely different. So in the old Nyx, this would go through the Nyx path and through your Nyx channels and look for Nyx packages.
So here, so Nyx packages is a identifier that is so-called flake reference. And flake references describe, well, the location of the flake. And that can be a URL, so for example, a GitHub repository on GitHub. But that's not very user-friendly if you have to type that all the time.
So you can type it, but usually you use this so-called registry. So there is a global registry that has some mappings from well-known repositories or well-known flakes to their actual locations. So what this command will do is it will fetch the latest registry.
I mean, it caches it, so most of the time it won't actually be fetching anything. So it will look for the location of Nyx packages, and then it will fetch Nyx packages. So unlike Nyx channel, you don't have to add anything, you don't have to configure anything. This just works.
So alright, so it works, that's great. So these flake references, you can also vary on them. So Nyx packages is looked up on the registry, but you, and in the default registry, Nyx packages is mapped to the master branch, or the unstable branch of Nyx packages.
I might change that in the future because maybe it's not a good idea, but in any case. But suppose we want to use the release 1909 branch, then you just say, Nyx run Nyx packages slash release 1909, and that will fetch the head revision of 1909, which has an older Rust version.
So these commands, by the way, are not very reproducible because they're referring to head revisions of repositories. So there can be any number of flakes, so for example in the flake world, the patch shelf project has a flake.nyx file.
So if we want to run the latest and greatest patch shelf, we just say Nyx run patch shelf, and this will fetch the patch shelf repository, build it, and run it. Now, so if we want something more reproducible, we can also use a so-called immutable flake reference,
so that's one that doesn't refer to a branch or tag, but to an actual revision. And ideally doesn't indirect through the registry, because the registry might change. So I can say something like Nyx run GitHub, and then an actual project and a revision.
And so this will always provide the same result, of course, provided that this repository doesn't disappear. So that's something I don't have a solution for at the moment yet, but alright.
A little bit more user perspective, so the difference with Nyx channel here is that you get the latest version of Nyx packages by default, so it might not be what you want, so you can also pin a flake, so what that does actually is,
so you have a global registry, but there's also a per user registry, and these pin and add commands just register an overwrite in your local registry. So Nyx flake pin will add an overwrite that makes Nyx packages point to the current revision, and after that it doesn't change, so you always get the same thing.
Or you can say, you can explicitly make Nyx packages point to anything you want, so you can make it point to your own fork, or to some branch that you want, whatever. Very briefly I can mention that since a few days ago there was also a Nyx ENF replacement,
so you can now say Nyx profile install Nyx packages hash hello. And this is a little bit nicer than Nyx ENF, because it remembers where these things actually came from, so it will store in the profile that this Nyx packages hash hello resolved to a particular revision,
so yeah, you can always reproduce that thing, you always know exactly what's in your profile, but you can also upgrade that, and it also remembers your original URL that you used to install it,
so if you run upgrades it will fetch the latest Nyx package and rebuild from there, so you get a mix between imperative and declarative style. Alright, so that was the user perspective, now a bit of the developer perspective,
so suppose you want to hack on a flake, so there is actually a little convenience command, Nyx flake clone, so this will look up a flake in the registry, so here a Nyx OS homepage, that's the nyxos.org homepage is actually built using a flake, so this just runs a git clone,
so we can go into it, we can edit it a bit, and now we can run Nyx build. And yeah, so this just works, which is not entirely trivial, because the Nyx OS homepage actually depends on multiple versions of Nyx packages,
and it pulls in Hydra and NyxOps and the master of Nyx, because it needs to prettify their manual, so all sorts of silly things going on there, but yeah, you don't need to know about it, you just run Nyx build and it works. Alright, so Nyx build by default, it builds this so-called default package that a flake provides,
but a flake can provide more than one package obviously, as in the case of Nyx packages, so for example in Nyx OS homepage there is this packages explorer derivation, and if you want to test that thing independently, you would say something like nyx build dot hash packages explorer,
so dot refers to the current directory, and hash packages explorer is the attribute in the flake that you're interested in. Yeah, there's also a nyx shell replacement, it's called nyx dev shell, and that uses, well by default it uses the default package provided by your flake,
but you can also have an explicit dev shell thing provided by your flake, so if you want to set up a very fancy environment that differs from the actual package,
then you can declaratively specify that. Another thing worth mentioning is there is a nyx flake check command, so that will check whether everything in your flake evaluates correctly, and it will build special check attributes in your flake, so you can put some smoke tests in there,
so this is a nice way to verify that your flake is still correct. Yeah, and flakes can provide many things, so for example they can provide Nyx OS system configurations, so Nyx OS container has flake support,
so you can say run the Nyx OS homepage flake in a container, and that will build the Nyx OS configurations dot container attribute from the flake, and yeah, so that's all completely reproducible,
so if two people run this command on the same revision of this repository, they will always get exactly the same container, but then you can start it, then you can run it, and yeah, that's nice for the homepage, because all these things like packages.json work, because they need some special web server configuration,
so yeah, that's nice. All right, so now what actually is a flake, so how am I doing in time, by the way? I'll assume that's okay. So okay, so what is a flake? So a flake is actually just a little bit of metadata around the nyx expressions that you already have,
so your default dot nyx, or your release dot nyx, and so the metadata is things like a description and an addition, and the dependencies of the flake, so the other flakes that it depends on, like nyx packages,
and then the main thing is the outputs of the flake, so those are the values that it actually provides. So here's an example, so this is from a flake called DwarfFS, it's just a little FUSE file system for fetching Dwarf debug info on demand,
so it has a description, it has an edition field that's mandatory, so the edition currently needs to be 2019.09, and that's actually a nice feature, because this will allow us to evolve not just flakes themselves, but the nyx syntax and semantics in the future, so if we want to do things like,
I know, remove the URL syntax from the nyx language, then the edition field allows that, so at some point we would bump this to 2020 something, and then old flakes would still be parsed using the old syntax, and new flakes using the new one.
Alright, so the main thing here is the outputs, so there are some packages here, well there's actually only one package, there's a default package which just aliases that package, and there is a nyxos module dot DwarfFS, and this flake has some dependencies,
well actually it has only one dependencies, and these are passed in as function arguments, and those are other flakes, so there's one called self, which is just this flake itself, so you can refer to the flakes own outputs, so for example here we're referring to self dot packages, which is actually this thing up here, and that's sometimes useful for referring
to some meta data of the flake, but the main thing here is nyx packages, so we're not saying anything here about where we get nyx packages from, you actually can specify that, so it's not shown here, but you can specify an inputs attribute here, which actually specifies where the inputs come from,
but if you don't specify that, if you just have a function argument here, then it will be looked up in the registry, so nyx packages will be looked up in the registry, and that's what is used to build this thing,
now that sounds very non-reproducible, so the solution is that there is a lock file, just as you know from MPM or cargo, so when you build a flake, so you have a flake dot nyx, it will look up all these dependencies,
and that's extremely impure, but then it will generate a flake dot lock file, which maps those impure dependencies to concrete revisions, so for example, nyx packages will be mapped to nyx slash nyx packages
slash whatever revisions happens to be current at that time, and once the lock file exists, it will be used by any subsequent build, so if you run nyx build again, it will use the dependencies locked in the lock file,
and so you would generally commit that lock file as part of your repository, and then things are wonderfully reproducible, so for example, in Hydra, configuring Hydra jobsets has always been unpleasant, because you have to specify these jobset inputs,
so that can get very messy if you have dozens of repositories that you depend on, but now you no longer need to do any of that, but the only thing that you need to configure in Hydra is the URL of your flake, and that flake will have a lock file
that completely locks all the dependencies, so that's all Hydra needs to know. Another nice thing about reproducibility is that now if something fails in Hydra and you want to try that out yourself,
so Hydra has this little known feature where you can click somewhere in a menu and reproduce this build, so what it used to do is generate a shell script that tries to reproduce all the dependencies of your project, so that will generate all these calls to Git and Mercurial
to fetch all your dependencies, and most of the time that doesn't really work, but now that's completely unnecessary, because you can just cut and paste this one liner, so for example, nix build, and then the so-called immutable flake reference,
so for example, GitHub nix slash nix slash revision, and then the attribute that this Hydra job corresponds to, so hydra jobs dot build dot x86 64 Linux, and that's guaranteed to give you exactly the same thing as what Hydra was building.
I skipped this one, so what are the outputs of a flake? A flake can provide anything, but there are a few well-known outputs, so if they exist, a nix flake check actually requires them to have a certain format,
so for example, the packages attribute must be a set of derivations, so if you put other stuff in it, it will complain. But yeah, so other well-known ones are nix packages overlays, nix with modules, system configurations, ci jobs like hydra jobs, dev shell environments, and so on,
but other than that, you're completely free to have arbitrary outputs, so flakes are just a little bit of a wrapper around your nix expressions. Yeah, let me also still mention that there's some basic flake support in nix OS,
that's really nice, because it used to be very annoying in nix OS, if you want to pull in something that's not in the nix packages repository, there's not a super easy way to do it, but now you can, so for example, here's a nix OS configuration for a hydra server,
so I just say, well, I need hydra as an input, and then in my modules they say hydra.nixosmodules.hydra, and it just works. And this for the first time also allows us to get rid of things like hydra in nix packages,
so it was always very embarrassing in nix, that if you have a nix-based project, so something that has a nix expression or a nix OS module, it was very hard to actually ship that in nix packages, because we had to actually reproduce all that stuff in nix packages, so nix packages has an outdated clone of the nix OS module for hydra,
so that's not a very nice approach, so now we can just get rid of these things, and you can just use the hydra flake directly, or for that matter, the nix flake, so if you want the bleeding edge of nix, then these two lines are all you need to do,
you just pull in the nix overlay from the nix flake. Alright, so there is an RFC, so none of what I described here is actually in nix master, and none of it is set in stone,
so all of this is subject to change, or maybe we'll throw it away, we decide it's a bad idea, but hopefully not. But yeah, so you can play with it, so I'm very interested in feedback, and I think that's it. Questions?
Hi, so I'm curious,
clamping down on impurities seems to remove a really important lever for injecting authorization to get private stuff, like what's the story for that? Yeah, so basically that should just work, so for example for GitHub,
so currently flakes have, I mean flakes are fundamentally agnostic as to how flakes are fetched, but currently they're just Git and GitHub as a sort of transport mechanism, now so Git just uses whatever authentication mechanisms you have,
so it's not executed by the daemon, all that fetching, so it's just run as your normal user account, so it can use your SSH keys or whatever. For GitHub, I think we have some configuration setting where you can configure access tokens,
so you can use that for fetching private repos. So yeah, so this is a use case that we're aware of, because actually so Target, the customer that funded this, of course they have all these internal repos, so yeah, that's something that needs to work. Okay, cool.
Hi, how can we try this out? So there is a nixflakes attribute in nix packages, so you can set, in nix you can set config.nix.package to nixflakes, you get a nixflakes-enabled system,
or you can do nix run nixflakes from nix packages. The caveat that the one on release 1909 is currently sort of broken, because a few days ago GitHub changed their,
well, the ETags that they're serving for their archives, so I was abusing the fact that their ETags were actually Git revisions, and I had no reason to actually assume that that would always be the case, and that stopped being the case a few days ago. So I fixed that, but that's not on release 1909 yet,
so I'll have to backport that. We have some necessary impurities, like the current system, how are you handling this, like AR64 or x8664, it's an impurity,
but it's like a requirement to work. How are you handling it as a reproducible manner? I didn't actually see the... I think the question was about multiplatform support, right?
Yeah. Yeah, yeah, yeah, so I hoped you wouldn't ask that. So until last week or so, it didn't actually have multiplatform support, so the problem here is that you need to somehow pass in the system argument, well, you need to...
OK, so flakes want to be completely reproducible, and if you pass in something like a system argument as a function argument to the flake, then it would, well, it would be sort of reproducible, but it would no longer be innumerable, so you wouldn't be able to ask a flake what its contents are anymore.
And also passing in function arguments would open the door to all sorts of configuration, and then before you know it, you need a readme.md again to figure out how to build it, so I might still do that in the future,
so maybe this is the most practical way to just have a system function argument there, but for now what I've done is, so the next command will just evaluate packages.currentSystem, so it's up to the flake to decide which platforms it supports,
so this particular flake, so it doesn't actually look like this in the real world, it's written a bit more general, so it emits attributes for every platform that it supports, so that's a little bit more verbose, that's a line of code per output, but it's not too bad,
so it's the responsibility of the flake to actually say what it supports, now you could say that's a little bit nasty, because it means you cannot build the flake on platforms that the flake offered didn't choose to support, but sort of in the flake philosophy the solution to that would always be to
create another flake that pulls in the original flake, and for instance uses its overlay to instantiate that package for whatever architecture, or maybe even cross-compiled architecture you're interested in, so the package's output here is only something for the NIC CLI,
and things like overlays or modules would work on any platform, well I mean they would evaluate on any platform whether they work is another question, but yeah, so this is still a bit where we have to experiment about what the best approach is.
So we only have time for one more question, and I think it was... Hi, thanks for the talk, it was a feature we were all waiting for. The question I have, when you were talking about Hydra, and when you have the reproducible builds where you can click and you get the command,
so the question is what if you have, so this NIC's homepage depends on multiple other flakes, and when you specify the build, this doesn't pin the other flakes,
which are not kind of under your control, isn't that not reproducible then? So the lock file... To kind of lock file recursively for all the flakes that you also depend on. Well, so it's actually not done recursively, the top level flake.lock file locks all the dependencies,
also the transitive dependencies, so it would look at the flake.lock file of the NIC's homepage repository, and that locks everything, so not just the top level thing, but also the transitive ones. So you have to have flake.lock files always? Yes, exactly, so what that doesn't do is if you want Hydra to be testing,
well to do actual integration tests, so to build NIC's homepage against the latest version of those dependencies, you currently cannot do that, because it would require Hydra to update the flake.lock file, which in itself wouldn't be the problem, but then it would have to register that flake.lock file somewhere
to make it reproducible by user, so it would have to store it in the database, so I mean that's not an unsolvable problem obviously, but I haven't done that yet. Alright, thank you.