Nix: Container maintenance and management - Presentation
Video transcript
We utilized ChatGPT to enhance the grammar and syntax of the transcript.
Thank you for attending this talk. Today, I'll be discussing Nix and a little bit about container maintenance.
Who am I?
I'm a Product Manager at Platform.sh. I know there have been several speakers from Platform.sh, but if you'd like to discuss product-related topics or just chat about Platform.sh, feel free to reach out to me. I'll be around at the booth.
To introduce this talk, I need to explain why we adopted Nix, a technology that might seem unfamiliar to some. It's actually quite amazing. To set the stage, I'll first talk about containers at Platform.sh, including some details about the technology stack we use.
Containers at Platform.sh (Upsun)
We use containers, but not Docker. Instead, we use LXC (Linux Containers), which we chose for historical reasons. When Platform.sh started, Docker was still experimental, while LXC was more stable and well-known, similar to BSD jails or Solaris Zones.
We're also using an industrialized orchestration tool called "manufacturer" instead of Kubernetes. Maybe we'll open-source it at some point—I'd love that.
Platform scaling
Our goal is to be a horizontal Platform as a Service (PaaS) that can host any kind of application with any runtime. For example, we maintain containers for different versions of PHP, among other languages. Just for PHP, we have 11 different images across various OS versions, each with its dependencies. This means we can even host a PHP 5.4 application, though I wouldn't recommend it.
In total, we maintain 71 application images and 95 service images (e.g., for databases, cache stores, etc.), making 166 images in total. This workload is managed by a dedicated team of three people who do an excellent job.
Dependency hell
However, maintaining these containers is challenging, especially when dealing with package dependencies. For instance, if you need a specific version of ImageMagick or a PHP extension like SOAP, you may encounter what we call "dependency hell." This issue arises when different packages require conflicting versions of the same dependencies, making it nearly impossible to build a consistent environment.
This leads us to the solution: Nix.
Introducing Nix
Nix is a functional package manager supported by a functional programming language. This means that all packages are treated as immutable values, and they are built in total isolation without any side effects. With Nix, it's impossible to have undeclared dependencies, and if it works on one machine, it will work on another.
The Nix Store, where all packages are stored, uses a unique SHA-256 hash to capture the package itself and all its dependencies, ensuring that everything is run and built in complete isolation. This allows you to have multiple versions of the same package (e.g., PHP 5.4 alongside PHP 8.3) without conflicts.
Using Nix
When using Nix, you don't need to learn much about its underlying functional language unless you want to customize your packages further. Nix Expressions, which are simple scripts written in this language, allow you to define package dependencies and build processes. Nix is backed by the largest package repository in the world, with over 880,000 packages.
Even though everything is built from the ground up by default, Nix can use pre-built binaries from its cache to speed up the process.
Nix demo
Let's see Nix in action. I'll use the nix-shell
command to create a temporary environment with the packages I need, like PHP 8.3, the SOAP extension, Python 2.7, and ImageMagick. This command evaluates all the dependencies and sets up the environment.
For automation, you can create a script using simple Nix syntax. This makes it easier to load your environment without specifying each package every time.
Conclusion
Thanks to Nix, we can reduce the number of images we need to maintain from 166 to just a few composable ones. This is a huge win for us, and it also simplifies package management for developers.
Nix can be used to generate Docker images, making it easier to add packages and tools to your stack. It's not only beneficial for maintaining large infrastructures but also for individual developers facing dependency challenges.
Thank you for your attention, and now I'll take any questions you might have.
Q&A
Question: What base image are you using for your LXC images?
Answer: We're using a basic Debian base for our LXC images. It's essentially built from scratch.
Question: Can Nix fix the version of every package on my machine forever, until I upgrade?
Answer: Yes, Nix allows you to pin versions of packages, ensuring they don't upgrade until you decide to do so. This can be managed by specifying the commit hash of the package version you want to pin in your configuration.
Question: How do you share configurations between developers?
Answer: The easiest way is to write a Nix expression, such as a default.nix file, and include it in your repository. Everyone can then use the same configuration by running the appropriate Nix command.
Question: Is there any compatibility between Nix and Docker images?
Answer: Nix has tools to help generate Docker images, but there isn't direct compatibility with Dockerfiles.
Question: How do you deploy Nix configurations in a production environment?
Answer: Platform.sh will soon launch an experimental feature that allows you to deploy Nix configurations directly in production. For now, deployment of Nix configurations in production would require a customized solution.
Question: How does Nix work under the hood?
Answer: Nix uses a cache to pre-build common packages, but it can also compile packages on demand. You can even set up your own cache layer to prioritize local builds.