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

NixOS: declarative configuration Linux distribution

00:00

Formal Metadata

Title
NixOS: declarative configuration Linux distribution
Title of Series
Number of Parts
199
Author
License
CC Attribution 2.0 Belgium:
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
In recent years, we've seen many advances from typical imperative configuration of Linux distributions to more sophisticated declarative configuration systems. NixOS takes a different path to achieve declarative configuration than current widely used state-of-art configuration management systems. By redefining how we package software today using Nix package manager, Linux distribution is configured stateless without examining current state of configuration on the machine. During the talk, we'll be looking at concepts behind NixOS stack and I'll show some real world examples of usage
65
Thumbnail
1:05:10
77
Thumbnail
22:24
78
Thumbnail
26:32
90
115
Thumbnail
41:20
139
Thumbnail
25:17
147
150
Thumbnail
26:18
154
158
161
Thumbnail
51:47
164
Thumbnail
17:38
168
Thumbnail
24:34
176
194
Thumbnail
32:39
195
Thumbnail
34:28
SummierbarkeitFigurate numberNormal (geometry)RoutingPublic domainRing (mathematics)PlanningQuicksortGoodness of fitUniform resource locatorSoftware testingLecture/Conference
Electronic mailing listJSON
Multiplication signConfiguration managementBitHydraulic jumpRevision controlQuicksortEvent horizonData managementLecture/Conference
EmailBitMultilaterationMachine codeWikiOpen sourceFunctional programmingData managementWebsiteDistribution (mathematics)File systemMaxima and minimaComputer fileFunctional (mathematics)Programming languageFunction (mathematics)Distribution (mathematics)Category of beingEndliche ModelltheorieoutputSet (mathematics)ResultantMultiplication signPattern languageSoftware developerRight angleExpressionClosed setWeb pageSystem call
State of matterFunction (mathematics)Revision controlFile systemDistribution (mathematics)BuildingFunctional programmingAnalytic continuationDecision theoryPoint (geometry)StapeldateiRun time (program lifecycle phase)Graph coloringFunctional (mathematics)Distribution (mathematics)Sound effectBinary codeDirectory serviceoutputRight angleSoftwareRule of inferencePatch (Unix)Service (economics)CASE <Informatik>Configuration managementWordLevel (video gaming)Data storage deviceProgramming languageMathematicsSoftware testingMachine codeMultiplication signBinary fileError messageInterpreter (computing)Term (mathematics)Lecture/ConferenceSource code
SoftwareRight angleSource codeMaxima and minimaArithmetic meanoutputResultantSet (mathematics)Multiplication signLocal ringIntegrated development environmentCASE <Informatik>Software testingStandard deviationLecture/Conference
outputPatch (Unix)TimestampData structurePattern languageBlock (periodic table)Binary codeComputer fileDeterminismOpen sourceFunctional (mathematics)Network topologyRight angleFunction (mathematics)Hash functionQuicksortLecture/Conference
Distribution (mathematics)Functional (mathematics)outputTheory of relativityComponent-based software engineeringFunction (mathematics)Type theoryIntegrated development environmentHash functionNetwork topologyOpen sourceBinary codeRoutingData storage deviceParameter (computer programming)Multiplication signDescriptive statisticsHessian matrixFitness functionGroup actionRevision controlDerivation (linguistics)Uniform resource locatorEmailLibrary (computing)CryptographyRootPatch (Unix)Meta elementCompilerBuildingScripting languageSoftwareSource code
Integrated development environmentRight angleData storage deviceOpen sourceHash functionSoftwareFunctional (mathematics)Parameter (computer programming)Substitute goodSet (mathematics)Component-based software engineeringLecture/Conference
Point (geometry)Profil (magazine)User interfaceWeb page
State of matterExistential quantificationRollback (data management)Electric generatorProfil (magazine)Set (mathematics)Scripting languageSpeicherbereinigungProjective planeWeb pagePoint (geometry)Integrated development environmentDifferent (Kate Ryan album)Right angleRevision controlPhysical systemMultilaterationoutputComputer fileData managementPole (complex analysis)Uniqueness quantificationMultiplicationPower (physics)Form (programming)MathematicsLink (knot theory)Functional (mathematics)Operator (mathematics)Open setCellular automatonHierarchyBinary fileVirtual realityLevel (video gaming)VirtualizationSpacetimeLibrary (computing)Data storage deviceAtomic numberLecture/Conference
Integrated development environmentDistribution (mathematics)MetreWorkstation <Musikinstrument>Open sourceComputer fileProfil (magazine)Functional (mathematics)User profileElectric generatorSoftware testingPhysical systemFile formatMathematicsLine (geometry)Parameter (computer programming)Machine codeoutputFlagDemonCASE <Informatik>Programming languageDirectory serviceConfiguration managementState of matterScripting languageControl flow graphVirtual machineComputer configurationData storage deviceNatural languageRight angleBulletin board systemRevision controlStudent's t-testModule (mathematics)Theory of relativityFood energyService (economics)Solid geometryPosition operatorExecution unitEndliche ModelltheorieDeclarative programmingCuboidFile systemBootingLecture/ConferenceComputer animation
Configuration managementCuboidVideo gameWebsiteLecture/ConferenceComputer animation
2 (number)Web pageLecture/Conference
Software testingOrder (biology)Multiplication signIntegrated development environmentMereologyPhysicalismConfiguration managementFlow separationFront and back endsProduct (business)Functional (mathematics)Spring (hydrology)Virtual machineSlide ruleMessage passingArithmetic meanCohesion (computer science)Fiber bundleVirtualizationDoubling the cubeDiffuser (automotive)CuboidComputer fileRevision controlArmWebsitePoint cloudComputer animationLecture/ConferenceSource codeJSON
Spring (hydrology)Block (periodic table)Figurate numberBitRight angleNumberGodProduct (business)FingerprintComputer animationLecture/ConferenceJSONXMLUML
Transcript: English(auto-generated)
Is Domen in the room, by chance? Our next speaker, Domen? No? For those leaving also,
there's two more talks and after that at 7 o'clock we're meeting outside of the room here to go and grab dinner, drinks or whatever it is that we're planning on doing.
But if you want to join, feel free to meet up here at 7 o'clock just outside the room.
So, is Domen in the room? Ah, there he is. Speaker located. We have some empty seats
there in the middle. If you guys could move over to the middle so we fill up all the empty seats. I see an empty seat over there, two empty seats in the back. We have an empty seat
over here. Can you turn it off? Test, test. All good. Plug you in. Should we start? Alright,
so the second to last talk, Domen is going to talk about NixOS. I think it's a very
interesting topic, a bit more exotic than most of the topics that we've had today. Before he starts, I wanted to quickly let everyone know that there is a config management camp in Ghent two days after FOSDEM, so it's on Monday and Tuesday. Unfortunately, it's totally full,
so for this year you're out of luck if you don't have a seat reserves already. But it's going to be a great conference, a two-day conference with basically all the configuration management tools. All the community is going to be there. As someone said today, it'll probably be the only time or one of the very few times that you'll see both the
people who started CF Engine, Puppet and Chef, talk at the same conference, all keynoting. So yeah, it's going to be great. For now, Domen is going to talk about NixOS. I'm curious to see what he has to say, so take it away. Alright, let's
get started. So a little bit about my background. I'm a Python and JavaScript developer, and I've used Gentoo for about eight years, and I've participated in Google Summer of Code trying to auto-generate Python packages. And I'm a NixOS user for about a year now, and this will become relevant later. I have no prior experience with functional languages.
So before we go and talk about Linux distribution, we have to rethink the package management. So this is where Nix comes in. It's a standalone package manager, so you can install it
basically onto any distribution. It's a DSL. It's lazy-evaluated. That's a very important feature and property that you will see later. Untyped and purely functional language. Because there is a little bit of Nix the package manager and Nix the language, we call Nix
expressions, the files and the language that we write. And Nix is the package manager. It tries to be minimal, to have minimal dependencies, so it's really easy to compile it from source if you want to do so. It's portable, as I said. I don't know if that's
the first release, but that's the first one listed on the website in 2004. It's written by Elko Dosto, and there's dozens of scientific papers published on the Nix side that are the theoretic base for the Nix and what's built on top of it.
So we're thinking the package management and if you think about how currently our distributions work, they would go into the file system and try to find headers there in a very funny
way because it breaks a lot of times, right? They will go into directly user include and try to find the correct headers, and that will break when you update some of the packages. So there is a set of problems that are called dependency hell, and there is a wiki page
which lists all of those problems that arise from dependency hell that we have today. And our motivation is to have really reproducible builds, right? So if I copy the instructions to another machine and run it, we should get the exact same result. So the idea behind Nix is apply functional language model to the packaging, right? So
a package is actually an output of some function, and all of those functions, all of those inputs to the functions are the instructions how this package is affected.
So this is, for example, we have a slash Nix slash store with all the packages that you have in your Linux distributions are stored, and there is a SHA-1 prefixed and then the name and the version, and inside this directory, this is basically the prefix where you install the packages. So inside you have directories like bin, lib, share,
and so on. Nix store is immutable. It's mounted as read-only, so you cannot modify it. So the idea is that when it's actually the package is built and stored inside the Nix store, you cannot modify it anymore. That's the way we ensure that it is really
an output of the function that you specified in your Nix package. So for the Nix to work, there is a term called purity, and that basically means that we are sure that the output is affected only by the inputs of the packaging function.
So nothing else should affect this package, right? And at the language level, this is solved by the way that we are using a functional language, so there is no state, no side effects. But on the level of a Linux distribution, we have to take a lot of steps to make sure, and some of them can't even be solved, and some of them are ongoing effort, right?
So for example, there is no user, there is no bin, so there is no global folders on your Linux distribution, because we don't want that to affect those packages that we prefix into the Nix store, right? There is also, we build packages in change root,
so that we are sure that they don't have access to the file system. So the store is immutable. So for example, one of the impurities is a lot of times code will have hard-coded bin bash, right? So that's again global. We want to patch
it so it points out to the exactly bash version that we are building this package, and the bash is a dependency, right? And then network, for example, we only allow network access when you download software, and when you actually test and do other stuff, and
build and so on, there is no network configured, right? We have patch-elf that will patch proprietary software binaries, and it will set the interpreter and the error path, so we can also make sure that the binary software points to the
correct Nix store packages. And there is this quote for the documentation that will tell you how actually we figure out what are the build dependencies and the runtime dependencies. So actually the output is searched for the Nix path output stores,
and then we know on which packages of all the build inputs the package depends on the runtime, right? You will think that this is probably wrong, but it works very well. There are zero problems that I've seen at least in the practice with this approach.
And this is of course possible because of this idea of purity. So there are also impurities. For example, network, a lot of times people will write tests for their software that will need network access, so in those cases we just disable those tests because there
is no way to ensure that the network is a result of the input instructions to the build of the package, right? It's something that is not deterministic. And for example, sometimes it will happen that the parallel builds of something will fail because the source
code needs to be fixed, right? That's also something that Nix cannot fix. So we have this concept of standard environment, which are the very minimal set of tools like the GCC and GNU set and so on that you need always when you package software. That's
the minimal set of packages that you need. And on OSX we actually use the OSX tools because it's more convenient and there is actually a ticket now to improve this in the future.
So there is also this idea to have a deterministic binary, so you will see about this hash, what it means when we prefix the package name. But basically this is the hash of all the inputs to the function that instructs how to package this software, right?
And the source is not the input, and also the binary blob is not the input. But we could extend this if we actually remove the impurities in the binary output. Sometimes people would store timestamps in the binary blob. For example, in Python
we have Python compiled files and we patch Python to not include the timestamps. But this is an ongoing effort. We don't have deterministic binaries yet.
And of course, like I said before, we patch software that has a character-coded path to the root. So this is, I don't know if you actually see, but this is an example of an Nginx, how we package it. So at the top, this is a function, and the parameters to the functions
are the standard environment, the two fetch functions, and then the dependencies that we will pass on. And the main derivation on the standard environment is the function that does the heavy lifting. So that's actually the function that will do all these phases and execute and package and store it into the Nginx store.
So as I've said before, if you remember, there was this hash before the name and the version. And actually the hash is calculated from all of those inputs to this function, except from the meta parameter, which is irrelevant for the output.
Because if you change a description of GCC, it shouldn't recompile the whole tree of what depends on GCC. So inside there you see a fetch URL function, and that's another way,
another type of how Nginx does the hashing, and it's called fixed output. So we know the hash, which is the SHA up front, right? So we don't need to actually hash all the inputs, because we already know what is the crypto output,
the crypt hash of the package. And then the fetch URL will actually, the output of the fetch URL function is actually the path to the Nginx store where this tarball is actually downloaded. And if you can imagine, the build inputs specifies the dependencies,
and those provide headers and libs and so on. So if any of those will change, the inputs also, the Nginx hash will change, so it will go and recompile and it will get the new prefix.
So I just put there configure flex and so on, to see that we have, this function accepts quite a lot of parameters that you can affect. But there are two more that I would mention. One is builder, which is actually the bash script that takes care of all the building.
And in the bash script we have phases, like you normally use build phase and install phase. And you can actually override here at this function those phases, or add a pre-phase or post-phase and so on. So when purity actually works, so that means that we've removed all the impurities,
we can actually have a distribution that has source and binary packages. So if you think about it, we have this hash that actually uniquely identifies all the inputs to this package. And if we have a build farm, which we do for NixOS, and we build a package on the build farm,
then you could use this as a replacement for the build function. So before Nix actually builds something, it will go and try to find a substitute, so something that already provides a binary package for this hash. So if I go and install Nginx now, it will download the binary blob,
but if I go and modify any of the parameters to the Nginx, then it will go and compile it from source, because the hash will change. So then comes the question of how do we get an actual environment?
We have this package software stored in prefix in NixStore, and how do we actually get to the environment? So there you see a package called userenv, and that's where all the packages will link into when you install them.
And from that point on, the symlink from the Nix profiles will point to the user environment. And as you can see, we keep a history of what you change.
So if you uninstall a package, we keep a history, because the Nix design brings us this benefit that we can actually have a history, and Nix provides rollbacks, so you can actually rollback. If you install a package and something is broken or you update, you can rollback to a previous state.
And then those profiles, generations that we call them, a history points to the Nix profile, and every user can have a different profile, or actually you can even generate a profile on demand for your project. So this actually replaces user space tools,
like in Python we have virtual environments and so on, and this is like a package management level virtual environment, so you can actually put a set of packages that are only specific for your project. And if you upgrade any other profile or install a package in another profile,
this will not affect the other profiles, so they are safe. And then, if you think about it, Nix is also atomic, so that means in the middle of an upgrade or installing, if it shuts down, if your power shuts down,
the changes won't be affected, because the last step is that this symlink to the profile is meant, and symlink is in Unix atomic by itself, so that's when everything is built and configured and put into the Nix store, when that switch is done, then actually you have the new environment activated.
Then when you think about garbage collection and how we uninstall packages, when you actually uninstall a package, it will just remove the symlink from your profile, it will not actually go and remove it from the store.
So that means that we need the concept of garbage collection, and it will collect those packages that are no longer referenced anywhere. So you could, because imagine if you're changing the inputs to different Firefox builds, then you could have multiple Firefoxes in your Nix store,
but maybe you don't have them installed in your profile, so then the garbage collection will say, okay, it's not referenced by anything else, let's delete it. So of course the cost here is file system hierarchy standard,
we still have the bin and lib and so on, but we don't have the user folders. And this also solves the dependency hell, so you can have different packages that depend on different versions of OpenSSL,
it doesn't matter, they're stored in the Nix store, and they're just linked to different versions of OpenSSL. So this is a very bad way to advertise how to get started with Nix, but it's a really cool way to express it in three lines.
I don't recommend to actually run it, so download the script first and check out the contents, but then you source into the Nix environment, and you can actually go and install packages, and you can do this on whatever Linux distribution, or S6 or FreeBSD if you want.
And if you want to uninstall it, just remove the slash Nix and all the profiles that it created, which is normally just your user profile. So NixOS is basically a generalization of the Nix package manager, and if you think about it, we don't have to do that much to get a Linux distribution on top of that.
So if we store packages in the Nix store, we can also store the configuration files, that's actually a simplification of a package. So Nix has this system profile, which is the NixOS profile. So when you upgrade NixOS,
you will upgrade the system profile and so on. And of course, then we need some configuration for the system, and this is the declarative configuration that you will see. And if you think about how NixOS works, it's different to Puppet, for example. If you're saying Puppet ensures packages install, it will go into the machine and inspect if it's installed,
and if it's not, then it will install it. So that's stateful, that's code that needs to work, and it needs to cover the edge cases. But with Nix, this comes out of the box, out of the design of the language and the system that we're using. So this is an example of configuration of a system,
and you declare a grub device and file system, and then enable the SSH daemon. And here I show, for example, how to configure Moon in a few lines of code. So if you want to install it, basically you create a partition,
you format it, mount it, generate a config, edit, NixOS, install, reboot, and you have your system with whatever you put in your configuration. And on the grub menu, you will see a history of your profiles, like the profile generation. So if something goes wrong when the system boots,
you can actually go and take the old profile that actually worked. So just to quickly go how to write the NixOS module, this is the package.writeText is the function that will actually store the file into the Nix store.
So this is like a complement to the makeDerivation function. And it's lazy-evaluated, and this is not calls. As you see, we already referenced the cfg.config, which is not defined, so that will get evaluated actually when it's referenced. And this is how you just define what options
the NixOS module provides, and here you say nginx enable, which package we will use, and what config will be used for the nginx. And in NixOS, we use systemd, because it really suits the thinking and the way Nix works.
So there we have a pre-start script that will start everything, configure everything, and then the actual execution. So there, when you see nginx, that's actually the path to the prefix of the nginx where it's packaged, and then it will pass the config file and the state directory.
And at the top, you see that it makes nginx available, installed on the system. And then you would use it something like this. So just enable nginx. And what we do actually here is, this is some kind of similar to the use flags in Gentoo.
You can have optional behavior, and the nginx is actually here, a function that we saw at the beginning, and we can pass parameters to it, right? So we could have a parameter, enable mp,
and if you turn it to true, then it would actually download the module and configure it and build nginx with it. But that means that you won't use the binary package anymore because you changed the inputs to the function, right? And when you make changes to your configuration file,
you run nyxos rebuild switch, and that will activate the changes. There is also nyxos rebuild test that will actually activate it, but on the next reboot, it will go to the previous generation, so it will not actually persist.
And there's also build VM, so it will actually build a virtual machine, like a virtual box, and it will configure everything in the site so you can actually see if it's working right. So this is the build farm, all the packages are built.
Is it? Okay. So we have packages stored on GitHub, and 300 seconds or something is the interval,
and it will pull the changes and build the packages and provide the binary packages for you, right? So here is the history of those builds, and you can see how many new packages succeed or how many fail. And we also have tests, so in order that nyxos channel is actually updated,
all those tests need to pass to make sure that at least something is working. And then as a last step, we have NixOps, and this is like deploying NixOS to the cloud and provisioning. So we have currently some backends,
four backends implemented, but of course more could be added. And this is a quick introduction. So install it with Nix, and then you define a machine, which is a function of a config and packages, and you, for example, here we configure Apache,
and NixOps has this separation of the physical and logical part. So the physical is, for example, this time we will deploy to VirtualBox, and we just say the target environment is VirtualBox. And then we say create, pass those two files, and name it trivial, and then deploy, and this will actually create a VirtualBox machine,
configure everything, and fire it up, and you have activated VirtualBox and configured with the packages. I have two or three more slides. So then you could have like a production version,
which would deploy to actual machine on some IP, and you deploy it the same way, just provide a different name. And we had a NixOS spring in Slovenia this summer, and I hope, last summer, and I hope we will have it this year again. It was supported by LogicBlocks and Shadowflow.net.
And that's it. Thank you very much. Domen, what was your name? Domen, was that your name?
Domen, thank you very much. I have one quick question. Is anyone using NixOS in production? Do you know? Yeah. Oh, we have one. Okay. That was the main question that I had. It looks quite interesting. I'm going to check it out a little bit more.
We have one more talk left, and then it's... You can do a quick question. Yeah, go ahead.
All right, cool. All right.