2023-07-04 06:18:46 +02:00
# Enabling NixOS with Flakes
2023-06-23 14:29:12 +02:00
2023-06-30 11:00:03 +02:00
## Enabling Flakes Support
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
Flakes provide improved reproducibility and a more organized package structure, making it easier to maintain NixOS configurations compared to the traditional approach. Therefore, it is recommended to manage NixOS using Flakes.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
However, as Flakes is still an experimental feature, it is not enabled by default. To enable Flakes, you need to modify the `/etc/nixos/configuration.nix` file as follows:
2023-06-23 14:29:12 +02:00
2023-07-08 07:34:48 +02:00
```nix{15,18-19}
2023-06-23 14:29:12 +02:00
# Edit this configuration file to define what should be installed on
2023-07-04 06:18:46 +02:00
# your system. Help is available in the configuration.nix(5) man page
2023-06-23 14:29:12 +02:00
# and in the NixOS manual (accessible by running 'nixos-help').
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
2023-07-04 06:18:46 +02:00
# Omit the previous configuration...
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
# Enable Flakes and the new command-line tool
2023-07-08 06:42:00 +02:00
nix.settings.experimental-features = [ "nix-command" "flakes" ];
2023-06-23 14:29:12 +02:00
environment.systemPackages = with pkgs; [
2023-10-09 18:46:31 +02:00
# Flakes use Git to pull dependencies from data sources
2023-06-23 14:29:12 +02:00
git
vim
wget
curl
];
2023-08-13 06:37:28 +02:00
# Set default editor to vim
environment.variables.EDITOR = "vim";
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
# Omit the rest of the configuration...
2023-06-23 14:29:12 +02:00
}
```
2023-07-04 06:18:46 +02:00
To apply the changes, run `sudo nixos-rebuild switch` . After that, you can start writing the configuration for NixOS using Flakes.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
## Switching to `flake.nix` for System Configuration
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
After enabling `flakes` , whenever you run `sudo nixos-rebuild switch` , it will first attempt to read the `/etc/nixos/flake.nix` file. If the file is not found, it will fallback to `/etc/nixos/configuration.nix` .
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
To learn how to write a Flakes configuration, you can refer to the official Flakes templates provided by Nix. To check the available templates, run the following command:
2023-06-23 14:29:12 +02:00
```bash
nix flake show templates
```
2023-07-04 06:18:46 +02:00
The `templates#full` template contains examples covering various use cases. Let's take a look at them:
2023-06-23 14:29:12 +02:00
```bash
nix flake init -t templates#full
cat flake.nix
```
2023-07-04 06:18:46 +02:00
After reviewing the example, create a file named `/etc/nixos/flake.nix` and copy the content of the example into it. From now on, all system modifications will be managed by Flakes using `/etc/nixos/flake.nix` .
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
Note that the copied template cannot be used directly. You need to modify it to make it work. Here's an example of `/etc/nixos/flake.nix` :
2023-06-23 14:29:12 +02:00
```nix
{
description = "Ryan's NixOS Flake";
2023-07-08 12:07:25 +02:00
# This is the standard format for flake.nix.
# `inputs` are the dependencies of the flake,
2023-06-23 14:29:12 +02:00
# and `outputs` function will return all the build results of the flake.
2023-07-08 12:07:25 +02:00
# Each item in `inputs` will be passed as a parameter to
# the `outputs` function after being pulled and built.
2023-06-23 14:29:12 +02:00
inputs = {
2023-07-08 12:07:25 +02:00
# There are many ways to reference flake inputs.
# The most widely used is `github:owner/name/reference` ,
2023-06-23 14:29:12 +02:00
# which represents the GitHub repository URL + branch/commit-id/tag.
2023-12-05 03:51:12 +01:00
# Official NixOS package source, using nixos-23.11 branch here
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
2023-06-23 14:29:12 +02:00
# home-manager, used for managing user configuration
home-manager = {
2023-12-05 03:39:10 +01:00
url = "github:nix-community/home-manager/release-23.11";
2023-06-23 14:29:12 +02:00
# The `follows` keyword in inputs is used for inheritance.
2023-07-08 12:07:25 +02:00
# Here, `inputs.nixpkgs` of home-manager is kept consistent with
# the `inputs.nixpkgs` of the current flake,
2023-06-23 14:29:12 +02:00
# to avoid problems caused by different versions of nixpkgs.
inputs.nixpkgs.follows = "nixpkgs";
};
};
# `outputs` are all the build result of the flake.
2023-07-19 04:35:14 +02:00
#
2023-06-23 14:29:12 +02:00
# A flake can have many use cases and different types of outputs.
2023-07-19 04:35:14 +02:00
#
# parameters in function `outputs` are defined in `inputs` and
2023-07-08 12:07:25 +02:00
# can be referenced by their names. However, `self` is an exception,
# this special parameter points to the `outputs` itself(self-reference)
2023-07-19 04:35:14 +02:00
#
2023-07-08 12:07:25 +02:00
# The `@` syntax here is used to alias the attribute set of the
# inputs's parameter, making it convenient to use inside the function.
2023-06-23 14:29:12 +02:00
outputs = { self, nixpkgs, ... }@inputs: {
nixosConfigurations = {
2023-07-08 12:07:25 +02:00
# By default, NixOS will try to refer the nixosConfiguration with
# its hostname, so the system named `nixos-test` will use this one.
# However, the configuration name can also be specified using:
# sudo nixos-rebuild switch --flake /path/to/flakes/directory#< name >
#
# The `nixpkgs.lib.nixosSystem` function is used to build this
# configuration, the following attribute set is its parameter.
#
# Run the following command in the flake's directory to
# deploy this configuration on any NixOS system:
# sudo nixos-rebuild switch --flake .#nixos-test
2023-06-23 14:29:12 +02:00
"nixos-test" = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
2023-07-08 12:07:25 +02:00
# The Nix module system can modularize configuration,
# improving the maintainability of configuration.
2023-06-23 14:29:12 +02:00
#
2023-07-08 12:07:25 +02:00
# Each parameter in the `modules` is a Nix Module, and
# there is a partial introduction to it in the nixpkgs manual:
2023-06-23 14:29:12 +02:00
# < https: / / nixos . org / manual / nixpkgs / unstable / # module-system-introduction >
2023-07-08 12:07:25 +02:00
# It is said to be partial because the documentation is not
# complete, only some simple introductions.
# such is the current state of Nix documentation...
2023-06-23 14:29:12 +02:00
#
2023-07-08 12:07:25 +02:00
# A Nix Module can be an attribute set, or a function that
# returns an attribute set. By default, if a Nix Module is a
2023-10-04 09:00:55 +02:00
# function, this function have the following default parameters:
2023-07-08 12:07:25 +02:00
#
# lib: the nixpkgs function library, which provides many
# useful functions for operating Nix expressions:
# https://nixos.org/manual/nixpkgs/stable/#id-1.4
2023-10-31 14:36:09 +01:00
# config: all config options of the current flake, very useful
2023-07-08 12:07:25 +02:00
# options: all options defined in all NixOS Modules
# in the current flake
2023-07-19 04:58:23 +02:00
# pkgs: a collection of all packages defined in nixpkgs,
# plus a set of functions related to packaging.
2023-07-08 12:07:25 +02:00
# you can assume its default value is
# `nixpkgs.legacyPackages."${system}"` for now.
# can be customed by `nixpkgs.pkgs` option
# modulesPath: the default path of nixpkgs's modules folder,
2023-06-23 14:29:12 +02:00
# used to import some extra modules from nixpkgs.
2023-07-08 12:07:25 +02:00
# this parameter is rarely used,
# you can ignore it for now.
2023-06-23 14:29:12 +02:00
#
2023-10-09 18:46:31 +02:00
# The default parameters mentioned above are automatically
# generated by Nixpkgs.
# However, if you need to pass other non-default parameters
# to the submodules,
# you'll have to manually configure these parameters using
# `specialArgs` .
2023-07-08 12:07:25 +02:00
# you must use `specialArgs` by uncomment the following line:
#
2023-10-04 09:00:55 +02:00
# specialArgs = {...}; # pass custom arguments into all sub module.
2023-06-23 14:29:12 +02:00
modules = [
2023-07-08 12:07:25 +02:00
# Import the configuration.nix here, so that the
# old configuration file can still take effect.
# Note: configuration.nix itself is also a Nix Module,
2023-06-23 14:29:12 +02:00
./configuration.nix
];
};
};
};
}
```
2023-06-28 10:53:32 +02:00
We defined a NixOS system called `nixos-test` with a configuration file at `./configuration.nix` , which is the classic configuration we modified before. Therefore, we can still make use of it.
2023-06-23 14:29:12 +02:00
2023-09-04 10:15:08 +02:00
To apply the configuration to a system with hostname `nixos-test` , run `sudo nixos-rebuild switch --flake /etc/nixos#nixos-test` . No changes will be made to the system because we imported the old configuration file in `/etc/nixos/flake.nix` , so the actual state we declared remains unchanged.
2023-06-23 14:29:12 +02:00
2023-10-04 09:00:55 +02:00
The comments in the above code are already quite detailed, but let's emphasize a few points here:
1. Default parameters like `lib` , `pkgs` , `config` , and others are automatically generated by Nixpkgs and can be automatically injected into submodules without the need for additional declarations here.
2. In `specialArgs = {...};` , the content of the attribute set is omitted here. Its contents are automatically injected into submodules through name matching.
1. A common usage, for instance, is to directly write `specialArgs = inputs;` , enabling all data sources from the `inputs` attribute set to be used in the submodules.
2023-07-04 06:18:46 +02:00
## Managing System Packages with Flakes
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
After the switch, we can manage the system using Flakes. One common requirement is installing packages. We have previously seen how to install packages using `environment.systemPackages` from the official `nixpkgs` repository.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
Now let's learn how to install packages from other sources using Flakes. This provides greater flexibility, particularly when it comes to specifying software versions. Let's use [Helix ](https://github.com/helix-editor/helix ) editor as an example.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
First, we need to add Helix as an input in `flake.nix` :
2023-06-23 14:29:12 +02:00
2023-07-08 07:36:47 +02:00
```nix{10,20}
2023-06-23 14:29:12 +02:00
{
description = "NixOS configuration of Ryan Yin";
2023-07-04 06:18:46 +02:00
# ...
2023-06-23 14:29:12 +02:00
inputs = {
2023-07-04 06:18:46 +02:00
# ...
2023-06-23 14:29:12 +02:00
2023-12-05 03:39:10 +01:00
# Helix editor, version - 23.10
helix.url = "github:helix-editor/helix/23.10";
2023-06-23 14:29:12 +02:00
};
outputs = inputs@{ self, nixpkgs, ... }: {
nixosConfigurations = {
nixos-test = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
2023-07-04 06:18:46 +02:00
# Set all input parameters as specialArgs of all sub-modules
2023-10-09 18:46:31 +02:00
# so that we can use the `helix` (an attribute in inputs) in
# sub-modules directly.
2023-06-23 14:29:12 +02:00
specialArgs = inputs;
modules = [
./configuration.nix
];
};
};
};
}
```
2023-07-04 06:18:46 +02:00
Next, update `configuration.nix` to install `helix` from the `helix` input:
2023-06-23 14:29:12 +02:00
2023-07-08 07:32:05 +02:00
```nix{3,14-15}
2023-06-23 14:29:12 +02:00
# Nix will automatically inject `helix` from specialArgs
# into the third parameter of this function through name matching
{ config, pkgs, helix, ... }:
{
2023-07-04 06:18:46 +02:00
# Omit other configurations...
2023-06-23 14:29:12 +02:00
environment.systemPackages = with pkgs; [
git
vim
wget
curl
2023-07-04 06:18:46 +02:00
# Install Helix from the `helix` input
2023-06-23 14:29:12 +02:00
helix.packages."${pkgs.system}".helix
];
2023-07-04 06:18:46 +02:00
# Omit other configurations...
2023-06-23 14:29:12 +02:00
}
```
2023-07-04 06:18:46 +02:00
To deploy the changes, run `sudo nixos-rebuild switch` . After that, you can start the Helix editor by running the `hx` command.
2023-06-23 14:29:12 +02:00
2023-10-07 09:41:22 +02:00
> If your system's hostname is not `nixos-test`, you need to modify the name of `nixosConfigurations` in `flake.nix`, or use `--flake /etc/nixos#nixos-test` to specify the configuration name.