initial commit
All checks were successful
Deploy docs / build-and-deploy (push) Successful in 3s

This commit is contained in:
sid 2026-02-23 20:34:35 +01:00
commit 95a533c876
451 changed files with 18255 additions and 0 deletions

View file

@ -0,0 +1,209 @@
# Flakes
> Flakes are still an experimental feature in Nix. However, they are so widely used by the community that they almost became standard. Furthermore, *synix* uses Flakes.
Nix flakes are a reproducible way to define, build, and deploy Nix projects, making them reliable and portable.
Flakes accomplish that by:
## Standardized Input
They define a fixed, declarative input (the `flake.nix` file) that specifies all project dependencies, sources, and outputs. This eliminates implicit dependencies or environment variables that could cause builds to differ.
Example in `flake.nix`:
```nix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; # Declare we need nixpkgs, specifically this branch
};
```
## Reproducible "Lock File"
When you build or develop with a flake, Nix generates a `flake.lock` file. This file records the *exact* content-addressable hashes of *all* transitive inputs used for that specific build. This lock file can be committed to version control, ensuring that anyone else cloning the repository (or a CI system) will use precisely the same set of inputs and thus achieve the identical result.
Example `flake.lock` entry for `nixpkgs`:
```json
"nixpkgs": {
"locked": {
"lastModified": 1709259160,
"narHash": "sha256-...",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b2f67f0b5d1a8e1b3c9f2d1e0f0e0c0b0a090807", // The exact commit!
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github",
"url": "github:NixOS/nixpkgs/nixos-23.11"
}
}
```
## Flake Schema
The `flake.nix` has a well-defined structure for `inputs` (sources like Git repos, other flakes) and `outputs` (packages, applications, modules, etc.). This consistent schema makes flakes composable and predictable.
A `flake.nix` file typically looks like this:
```nix
# flake.nix
{
description = "A simple example flake";
inputs = {
# Inputs are other flakes or external resources
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; # Locked to a specific branch/version
# This is how you would add synix to your flake:
# synix.url = "git+https://git.sid.ovh/sid/synix"
};
outputs = { self, nixpkgs, ... }@inputs: # 'self' refers to this flake, inputs are available
let
# Define common arguments for packages from nixpkgs
# This ensures all packages use the same version of Nixpkgs on this system
pkgs = import nixpkgs {
system = "x86_64-linux"; # The target system architecture
};
in
{
# Outputs include packages, devShells, modules, etc.
# Packages that can be built by `nix build .#<package-name>`
packages.x86_64-linux.my-app = pkgs.callPackage ./pkgs/my-app { };
packages.x86_64-linux.my-other-app = pkgs.hello; # From nixpkgs directly
# Development shells that can be entered using `nix develop`
devShells.x86_64-linux.default = pkgs.mkShell {
name = "my-dev-env";
buildInputs = [ pkgs.nodejs pkgs.python3 ];
shellHook = "echo 'Welcome to my dev environment!'";
};
# NixOS modules (for system config)
# nixosConfigurations.<hostname>.modules = [ ./nixos-modules/webserver.nix ];
# (This is more advanced and will be covered in NixOS section)
};
}
```
Key parts of a `flake.nix`:
- `description`: A human-readable description of your flake.
- `inputs`: Defines all dependencies of your flake. Each input has a `url` pointing to another flake (e.g., a GitHub repository, a local path, or a Git URL) and an optional `follows` attribute to link inputs.
- `outputs`: A function that takes `self` (this flake) and all `inputs` as arguments. It returns an attribute set defining what this flake provides. Common outputs are `packages`, `devShells`, `nixosConfigurations`, etc., usually segregated by system architecture. You can read more about flake outputs in the [NixOS & Flakes Book](https://nixos-and-flakes.thiscute.world/other-usage-of-flakes/outputs).
## `nix flake` Commands
The `nix flake` subcommand is your primary interface for interacting with flakes. Let's create a new flake to demonstrate them:
Initialize the flake:
```bash
mkdir my-flake && cd my-flake
nix flake init
```
This creates a minimal `flake.nix`.
Lock your flake:
```bash
nix flake lock
```
This creates `flake.lock`, a file that locks the exact versions of your inputs.
Update flake inputs:
```bash
nix flake update
```
This updates all inputs to their latest versions allowed by their `url` (e.g., the latest commit on `nixos-unstable` for `nixpkgs`) and then updates the `flake.lock` file. Since we just locked the flake for the first time, there probably won't be any updates available.
Print flake inputs:
```bash
nix flake metadata
```
Print flake outputs:
```bash
nix flake show
```
Build packages from a flake:
```bash
nix build .#hello # The '.' refers to the current directory's flake
./result/bin/hello
```
Run a package from a flake:
```bash
nix run .#hello
```
Since the `packages.<system>.default` output exists, you can just do `nix run`.
## `nix develop`
This command spins up a temporary shell environment with all the tools and dependencies specified in your flake's `devShells` output.
Let's expand your `flake.nix`:
```nix
# flake.nix
{
description = "A very basic flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs =
{ self, nixpkgs }:
let
# Define `pkgs` for the current system
pkgs = import nixpkgs {
system = "x86_64-linux";
};
in
{
packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
# With `pkgs` defined, we could also do this:
# packages.x86_64-linux.hello = pkgs.hello;
packages.x86_64-linux.default = self.packages.x86_64-linux.hello;
devShells.x86_64-linux.default = pkgs.mkShell {
# Packages available in the shell
packages = [
pkgs.git
pkgs.go
pkgs.neovim
];
# Environment variables for the shell
GIT_COMMITTER_EMAIL = "your-email@example.com";
# Commands to run when entering the shell
shellHook = ''
echo "Entering development shell for my project."
echo "You have Git, Go, and Neovim available."
'';
};
};
}
```
Now, from your project directory:
```bash
nix develop
```
You'll instantly find yourself in a shell where `git`, `go`, and `nvim` are available, and your `GIT_COMMITTER_EMAIL` is set. When you exit, your regular shell environment is restored no lingering installations or modified global state. This makes it incredibly easy to switch between projects, each with its specific toolchain and dependencies, without conflicts.