Check out FlakeHub — the best place to discover and publish Nix flakes, from Determinate Systems.

We use a single, first-party analytics cookie to focus our limited time and energy on the most important documentation. Check out our privacy policy .

The Nix language

The language you use to define Nix package builds, development environments, NixOS configurations, and more.

Concepts / The Nix language

We recommend starting with the Nix quick start and consulting concept docs primarily for clarification. Feel free to click x to the right to disable this notification on all concept docs.

Nix is the programming language that powers the Nix packaging system.

Why a programming language?

You might ask yourself why Nix even needs a programming language. Why can’t packages be declared via some JSON, YAML, or TOML schema? The problem with that lies in the dynamic nature of how Nix configures packages and allows them to be combined. Nix as a programming language can be thought of as a kind of “JSON, but with functions”. All statements are declarative, meaning that there’s no sequential flow of instructions that makes up a Nix package. Instead functions are called that assign values to fields in attribute sets, which in turn may get assigned to other values.

How does Nix work?

Nix uses a few important characteristics in programming language design to work. Some of these terms can seem daunting, when you’re not already familiar with what they mean and how they work with each other. So first, let’s cover these principles:

Nix is a pure, functional, lazy, declarative, and reproducible programming language.

ConceptDescription
PureA programming-language design concept by which functions can not cause side effects. The only result is the one a function returns
FunctionalA programming-language design concept by which functions can be passed as function arguments, and returned as results
LazyA programming-language design concept by which functions and data collections are not evaluated until they are needed to complete a computation
DeclarativeDescribing a system outcome, instead of instructing the computer how to achieve the outcome
ReproducibleAn operation that is performed twice yields the same result. The same inputs map to the same outputs

Syntax basics

As mentioned previously, Nix uses assignments to compute and process data for packages, modules, and other utilities. The code below, for example, calls a function called my_function with the parameters 2 and 3, and assigns its output to the my_value field.

Assignments
{
my_value = my_function 2 3;
}

Functions are defined using this syntax, where x and y are attributes passed into the function:

Functions
{
my_function = x: y: x + y;
}

The body of the function automatically returns the result of the function. As you can see in the example above, functions are called by spaces between it and its parameters. No commas are needed to separate parameters.

The two most common data structures are attribute sets and lists. Attribute sets are key-value stores. Lists can contain different types of values and don’t need to be comma separated.

Recursive attributes
rec {
number_key = 5;
list_key = [ number_key true "Hello" ];
}

The rec keyword allows the attribute set to reference itself.

For a more detailed breakdown of syntax, check out the Nix language manual section.

Derivations

One thing that sets Nix apart from other programming languages—and makes it much more than just a configuration language—is the derivation function. This is a built-in function that you use to define the build process for packages. See the derivations concept doc for more info.


Was this page helpful?