Back

How we use Nix at Twin

Sometimes Nix feels like a secret weapon

I've used NixOS personally for quite some time and was always amazed by it. But now, with LLMs, Nix is just an unmatched ecosystem

With Nix, you can make your whole system configuration expressible as code. In most systems, like other Linux distributions, macOS, and Windows, the configuration of the system is a set of diffuse knobs you adjust in different places, be it graphical interfaces or the terminal. Each application has its own configuration, and packages are installed iteratively

In Nix, your whole system can be expressed as a .nix file that contains the full definition of the system: how its filesystem is organized, network configuration, which packages are installed and how they're configured

This has some obvious benefits. For instance, if you have multiple machines, it means that you can have a single configuration and apply it to all of them; even if the machines have different hardware, you can still factor out the common parts of the system to reuse, similarly to how you'd reuse functions in any other programming language

It's incredible how well this matches with LLMs, for a few reasons. First, LLMs are great at coding, so making the task of configuring a system into a coding task just makes it much easier for the LLM to succeed. Second, because the system is itself expressed as code, the LLM can understand its full state by reading the code. If you ask an LLM to change some setting on a usual machine, it would have to probe around using various commands to discover how the system is configured in the first place, which is a non-issue with Nix

As a personal example: I recently wanted to stream some files from my computer to my TV, which can be done with a DLNA server. So I went into my system Nix config directory, opened my coding agent, and asked it to set it up. It added a few lines to a Nix file to add the DLNA server service to run under my user. I applied the changes, and everything was working in less than 5 minutes

Then there's reproducibility. One of the issues that Nix was created to solve was building reproducible systems. For instance, if you have a piece of source code, ideally you'd want to be able to compile and generate the same result every time. This seems obvious, but it's not trivial to achieve. For instance, many programs link to libraries dynamically, and different people running the software will have different versions of the libraries; in some languages, the dependencies used might differ; some packages download dependencies during build time, often a "latest" version, which means you'd build a different artifact depending on when you built it; and so on. In Nix this is avoided by making building packages pure: you give some inputs, like source code and dependencies, and it builds it in a sandboxed environment such that every build with the same inputs yields the same outputs

At Twin, we use Nix in a few different ways. First, it's how we define our development environments. This is a common problem that teams have: how do we ensure everyone is working with the same tooling to avoid non-reproducible problems? In Nix, you can define a dev shell, where you essentially describe which packages should be available, environment variables, and so on, and then Nix installs those packages. Combined with direnv, which auto-loads the Nix shell, this makes developer onboarding and setup extremely easy. By setting up additionally a private binary cache (eg Cachix), it also means less rebuilding of common tools, which can be reused among the team

Another way we use it at Twin is that all of our machines are defined as Nix configurations. Our infrastructure is basically a bunch of bare metal and virtual machines, each of them has a corresponding entry in our Nix file, which describes what should run where, how it should be configured, and so on. That means we can spin up local VMs that closely reproduce production, decreasing the discrepancy between the local and real environments. We tried a lot of different alternatives before (cloud native, k8s), but by far our current setup is the one where we spent the least amount of time solving infra issues, while handling our growth to 1M agents running in production

If you're looking to get started, try it out with a dev shell. Ask a coding LLM to set it up in your repo, and soon it starts to feel magical. Or if you're looking to join a company using Nix, send us a message at jobs@twin.so