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-07-04 06:18:46 +02:00
# Flakes use Git to pull dependencies from data sources, so Git must be installed first
2023-06-23 14:29:12 +02:00
git
vim
wget
curl
];
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.
# Official NixOS package source, using nixos-unstable branch here
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# home-manager, used for managing user configuration
home-manager = {
2023-07-08 05:44:49 +02:00
url = "github:nix-community/home-manager/release-23.05";
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
# function, this function can only have the following parameters:
#
# lib: the nixpkgs function library, which provides many
# useful functions for operating Nix expressions:
# https://nixos.org/manual/nixpkgs/stable/#id-1.4
2023-07-19 04:58:23 +02:00
# config: all config options of the current flake, every 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
#
# Only these parameters can be passed by default.
2023-07-08 12:07:25 +02:00
# If you need to pass other parameters,
# you must use `specialArgs` by uncomment the following line:
#
# 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-07-14 16:45:05 +02:00
To apply the configuration to a system with hostname `nixos-test` , run `sudo nixos-rebuild switch` . 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-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-07-04 06:18:46 +02:00
# Helix editor, using version 23.05
2023-06-23 14:29:12 +02:00
helix.url = "github:helix-editor/helix/23.05";
};
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
# so that we can use the `helix` input in sub-modules
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-07-04 06:18:46 +02:00
## Adding Custom Cache Mirrors
2023-06-23 14:29:12 +02:00
2023-06-28 10:53:32 +02:00
> If you don't need to customize the cache mirror, you can safely skip this section.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
To accelerate package building, Nix provides < https: / / cache . nixos . org > to cache build results and avoid rebuilding packages locally.
2023-06-23 14:29:12 +02:00
2023-07-08 06:52:49 +02:00
With the classic configuration method in NixOS, additional cache sources can be added using `nix-channel` . However, Nix Flakes strives to avoid using any system-level configurations or environment variables as much as possible, ensuring that its build results are not affected by the environment. Therefore, after switching to Flakes, the `nix-channel` command becomes ineffective.
2023-06-23 14:29:12 +02:00
2023-07-04 06:18:46 +02:00
To customize the cache source, we must add the related configuration in `flake.nix` using the `nixConfig` parameter. Here's an example:
2023-06-23 14:29:12 +02:00
2023-07-08 07:32:05 +02:00
```nix{4-19}
2023-06-23 14:29:12 +02:00
{
description = "NixOS configuration of Ryan Yin";
nixConfig = {
experimental-features = [ "nix-command" "flakes" ];
substituters = [
2023-07-04 06:18:46 +02:00
# Replace the official cache with a mirror located in China
2023-07-16 07:35:45 +02:00
"https://mirrors.ustc.edu.cn/nix-channels/store"
2023-06-23 14:29:12 +02:00
"https://cache.nixos.org/"
];
2023-07-06 05:04:52 +02:00
extra-substituters = [
2023-07-04 06:18:46 +02:00
# Nix community's cache server
2023-06-23 14:29:12 +02:00
"https://nix-community.cachix.org"
];
extra-trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
};
inputs = {
2023-07-04 06:18:46 +02:00
# Omit some configurations...
2023-06-23 14:29:12 +02:00
};
outputs = {
2023-07-04 06:18:46 +02:00
# Omit some configurations...
2023-06-23 14:29:12 +02:00
};
}
```
2023-07-08 06:42:00 +02:00
After making the modifications, run `sudo nixos-rebuild switch` to apply the updates.