feat: polish by chatgpt

This commit is contained in:
Ryan Yin 2023-07-04 12:18:46 +08:00
parent 7825a8210b
commit b766b4c91e
26 changed files with 604 additions and 530 deletions

View File

@ -14,13 +14,13 @@ The flakes experimental feature is a major development for Nix, it introduces a
Flakes is one of the most significant changes the nix project has ever seen.[^2]
## Warning about Flakes
## A Word of Caution about Flakes
The benefits of Flakes are obvious, and the entire NixOS community likes it very much. Currently, more than half of the users are using Flakes[^3], so we're pretty sure that Flakes will never be deprecated.
The benefits of Flakes are evident, and the entire NixOS community has embraced it wholeheartedly. Currently, more than half of the users utilize Flakes[^3], providing assurance that Flakes will not be deprecated.
:warning: But **Flakes is still an experimental feature**, there are still some problems with it, it is likely to introduce some breaking changes in the process of stablizing it, and its uncertain how greatly the breaking changes will be.
:warning: However, it's important to note that **Flakes is still an experimental feature**. Some issues persist, and there is a possibility of introducing breaking changes during the stabilization process. The extent of these breaking changes remains uncertain.
Overall, I still recommend everyone to use Flakes, this book is also written around NixOS and Flakes after all, but please be prepared for the problems that may be caused by the upcomming breaking changes.
Overall, I strongly recommend everyone to use Flakes, especially since this book revolves around NixOS and Flakes. However, it's crucial to be prepared for potential problems that may arise due to forthcoming breaking changes.
## Contribution

View File

@ -1,28 +1,30 @@
# Advanced Topics
Once you're familiar with NixOS, you can explore Nix's three manuals and other documentation to discover more ways to use it:
Once you have become familiar with NixOS, you can explore advanced topics and dive deeper into the Nix ecosystem. Here are some resources and community projects that can help you expand your knowledge:
- [Nix Reference Manual](https://nixos.org/manual/nix/stable/package-management/profiles.html): A guide to the Nix package manager, which covers the design of the package manager and instructions for using it from the command line.
- [nixpkgs Manual](https://nixos.org/manual/nixpkgs/unstable/): A manual that introduces parameters of Nixpkgs, how to use, modify, and package Nix packages.
- [NixOS Manual](https://nixos.org/manual/nixos/unstable/): A user manual for NixOS, which includes configuration instructions for system-level components such as Wayland/X11 and GPU.
- [nix-pills](https://nixos.org/guides/nix-pills): Nix Pills provides an in-depth explanation of how to use Nix to build software packages. It is written in a clear and understandable way and is worth reading, as it is also sufficiently in-depth.
## Documentation
Once you're familiar with Flakes, you may want to explore some advanced techniques. Here are some popular community projects to try out:
- [Nix Reference Manual](https://nixos.org/manual/nix/stable/package-management/profiles.html): A comprehensive guide to the Nix package manager, covering its design and usage from the command line.
- [nixpkgs Manual](https://nixos.org/manual/nixpkgs/unstable/): The manual for nixpkgs, which introduces its parameters, explains how to use, modify, and package Nix packages.
- [NixOS Manual](https://nixos.org/manual/nixos/unstable/): A user manual for NixOS, providing configuration instructions for system-level components such as Wayland/X11 and GPU.
- [nix-pills](https://nixos.org/guides/nix-pills): "Nix Pills" is a series of guides that provide an in-depth explanation of building software packages with Nix. It offers clear and understandable explanations.
- [flake-parts](https://github.com/hercules-ci/flake-parts): This project simplifies the writing and maintenance of configuration through the Module module system.
- [flake-utils-plus](https://github.com/gytis-ivaskevicius/flake-utils-plus): A third-party package that simplifies Flake configuration and is known to be more powerful.
- [digga][digga]: A comprehensive Flake template that combines the functionality of various useful Nix toolkits. However, it has a complex structure and requires some experience to navigate.
- etc.
## Advanced Techniques and Community Projects
There are many other useful community projects to explore. Here are a few examples:
Once you are comfortable with Flakes, you can explore more advanced techniques and community projects. Here are some popular ones to try out:
- [flake-parts](https://github.com/hercules-ci/flake-parts): Simplifies the writing and maintenance of configurations using the Module module system.
- [flake-utils-plus](https://github.com/gytis-ivaskevicius/flake-utils-plus): A third-party package that enhances Flake configuration and provides additional powerful features.
- [digga](https://github.com/divnix/digga): A comprehensive Flake template that combines functionality from various useful Nix toolkits. Note that it has a complex structure and may require some experience to navigate.
There are many other valuable community projects worth exploring. Here are a few examples:
- [nixpak](https://github.com/nixpak/nixpak)
- [nix-output-monitor](https://github.com/maralorn/nix-output-monitor)
- [agenix](https://github.com/ryantm/agenix): A tool for secrets management
- [colmena](https://github.com/zhaofengli/colmena): Tools for NixOS deployment
- [nixos-generator](https://github.com/nix-community/nixos-generators): A tool to generate iso/qcow2/... from NixOS configuration
- [lanzaboote](https://github.com/nix-community/lanzaboote): A tool to enable secure boot for NixOS
- [impermanence](https://github.com/nix-community/impermanence): A tool used to make NixOS stateless and improve the reproducibility of NixOS systems.
- ...
- [agenix](https://github.com/ryantm/agenix): A tool for secrets management.
- [colmena](https://github.com/zhaofengli/colmena): Tools for NixOS deployment.
- [nixos-generators](https://github.com/nix-community/nixos-generators): A tool to generate ISO/qcow2/... from NixOS configurations.
- [lanzaboote](https://github.com/nix-community/lanzaboote): Enables secure boot for NixOS.
- [impermanence](https://github.com/nix-community/impermanence): Helps make NixOS stateless and improves system reproducibility.
[digga]: https://github.com/divnix/digga
These projects offer additional functionality and tools that can enhance your NixOS experience.

View File

@ -1,10 +1,10 @@
# Debug with `nix repl`
# Debugging with `nix repl`
We've used `nix repl '<nixpkgs>'` many times to check the source code in this guide, it's a powerful tool to help us understand how things work in Nix.
We have frequently used nix repl `<nixpkgs>` throughout this guide to examine the source code. It is a powerful tool that helps us understand how things work in Nix.
Better take a look at the help message of `nix repl`:
Let's take a closer look at the help message of nix repl:
```
```shell
nix repl -f '<nixpkgs>'
Welcome to Nix 2.13.3. Type :? for help.
@ -33,9 +33,9 @@ The following commands are available:
:te [bool] Enable, disable or toggle showing traces for errors
```
Some expressions that I use frequently: `:lf <ref>`, `:e <expr>`.
There are a couple of expressions that I frequently use: `:lf <ref>` and `:e <expr>`.
`:e <expr>` is very intuitive, so I won't repeat it. let's take a look at `:lf <ref>`:
The `:e <expr>` command is very intuitive, so I won't go into detail about it. Instead, let's focus on `:lf <ref>`:
```nix
# cd into my nix-config repo(you should replace it with your own nix-config repo)
@ -140,4 +140,4 @@ outputs.nixosConfigurations.ai.config.home-manager.users.ryan.home.file..config/
#......
```
As we can see, we can check every attribute of my flake in the REPL after loading it, which is very convenient for debugging.
As you can see, after loading your Nix flake into the REPL, you can check every attribute of the flake. This capability is very convenient for debugging purposes.

View File

@ -1,7 +1,6 @@
# Best Practices
Nix is powerful and flexible, it provides a lot of ways to do things, making it difficult to find the most suitable way to do your job.
Here are some best practices that I've learned from the community, hope it can help you.
Nix is a powerful and flexible tool that offers various approaches to accomplish tasks, which can sometimes make it challenging to determine the most suitable method for a particular job. To assist you in navigating through this vast ecosystem, I have compiled some best practices that I've learned from the community. I hope these practices prove helpful to you.
## References

View File

@ -1,33 +1,29 @@
# Remote deployment
# Remote Deployment
Some tools like [NixOps](https://github.com/NixOS/nixops), [deploy-rs](https://github.com/serokell/deploy-rs), and [colmena](https://github.com/zhaofengli/colmena) can all be used to deploy NixOS configuration to remote hosts, but they are all too complicated for me.
Deploying NixOS configuration to remote hosts can be accomplished using tools like [NixOps](https://github.com/NixOS/nixops), [deploy-rs](https://github.com/serokell/deploy-rs), and [colmena](https://github.com/zhaofengli/colmena). However, if you prefer a simpler approach, you can use the built-in remote deployment capability of `nixos-rebuild` with SSH protocol.
`nixos-rebuild`, the tool we use to deploy NixOS configuration, also supports remote deployment through ssh protocol, which is very convenient and simple.
Before using `nixos-rebuild` for remote deployment, there are a few prerequisites:
But `nixos-rebuild` does not support deploying with password authentication, so to use it for remote deployment, we need to:
1. Configure SSH public key authentication for the remote hosts.
2. To prevent sudo password verification failures, either deploy as the `root` user or grant the user sudo permission without password verification.
- Related issue: <https://github.com/NixOS/nixpkgs/issues/118655>
1. Configure ssh public key authentication for the remote hosts.
2. To avoid sudo password verification failures, we need to use the `root` user to deploy, or grant the user sudo permission without password verification.
1. related issue: <https://github.com/NixOS/nixpkgs/issues/118655>
After the above configuration is completed, we can deploy the configuration to the server through the following command:
Once the above configurations are in place, you can deploy the configuration to the server using the following command:
```bash
# 1. add the ssh key to ssh-agent first
# 1. Add the SSH key to ssh-agent first
ssh-add ~/.ssh/ai-idols
# 2. deploy the configuration to the remote host, using the ssh key we added in step 1
# and the username defaults to `$USER`, it's `ryan` in my case.
# 2. Deploy the configuration to the remote host, using the SSH key added in step 1.
# The username defaults to `$USER`, in my case, it's `ryan`.
nixos-rebuild --flake .#aquamarine --target-host 192.168.4.1 --build-host 192.168.4.1 switch --use-remote-sudo --verbose
```
The commands above will build & deploy the configuration to `aquamarine`, the build process will be executed on `aquamarine` too,
and the `--use-remote-sudo` option indicates that we need to use sudo permission on the remote server to deploy the configuration.
The command above will build and deploy the configuration to the `aquamarine` server, and the build process will also execute on `aquamarine`. The `--use-remote-sudo` option indicates that sudo permission is required on the remote server for deploying the configuration.
If you want to build the configuration locally and deploy it to the remote server, just replace `--build-host aquamarinr` with `--build-host localhost`.
Instead of using IP address directly, we can also define some host aliases in `~/.ssh/config` or `/etc/ssh/ssh_config`, for example:
If you prefer to build the configuration locally and deploy it to the remote server, replace `--build-host aquamarine` with `--build-host localhost`. Additionally, instead of using the IP address directly, you can define host aliases in `~/.ssh/config` or `/etc/ssh/ssh_config`. For example:
> ssh's config can be generated completely through Nix configuration, and this task is left to you.
> The SSH config can be generated entirely through Nix configuration, and this task is left to you.
```bash
cat ~/.ssh/config
@ -51,8 +47,10 @@ Host kana
Port 22
```
Then we can use the host alias to deploy the configuration:
You can then use the host aliases to deploy the configuration:
```bash
nixos-rebuild --flake .#aquamarine --target-host aquamarine --build-host aquamarine switch --use-remote-sudo --verbose
```
This allows for more convenient deployment using the defined host aliases.

View File

@ -1,12 +1,10 @@
# Run downloaded binaries on NixOS
# Running Downloaded Binaries on NixOS
NixOS does not follow the FHS standard, so the binaries you download from the Internet will not likely work on NixOS. But there are some ways to make it work.
Since NixOS does not strictly adhere to the Filesystem Hierarchy Standard (FHS), binaries downloaded from the internet may not work directly on NixOS. However, there are various methods available to make them function properly.
Here is a detailed guide that provides 10 ways to run downloaded binaries on NixOS: [Different methods to run a non-nixos executable on Nixos](https://unix.stackexchange.com/questions/522822/different-methods-to-run-a-non-nixos-executable-on-nixos), I recommend you to read it.
For a comprehensive guide that presents ten different approaches to run downloaded binaries on NixOS, I recommend reading the article [Different methods to run a non-nixos executable on Nixos](https://unix.stackexchange.com/questions/522822/different-methods-to-run-a-non-nixos-executable-on-nixos).
Among these methods, I prefer creating an FHS environment to run the binary, which is very convenient and easy to use.
To create such an environment, add the following code to one of your Nix modules:
Among these methods, I personally prefer creating an FHS environment to run the binary, as it proves to be both convenient and easy to use. To set up such an environment, you can add the following code to one of your Nix modules:
```nix
{ config, pkgs, lib, ... }:
@ -17,20 +15,20 @@ To create such an environment, add the following code to one of your Nix modules
environment.systemPackages = with pkgs; [
# ......omit many packages
# create a fhs environment by command `fhs`, so we can run non-nixos packages in nixos!
# Create an FHS environment using the command `fhs`, enabling the execution of non-NixOS packages in NixOS!
(let base = pkgs.appimageTools.defaultFhsEnvArgs; in
pkgs.buildFHSUserEnv (base // {
name = "fhs";
targetPkgs = pkgs: (
# pkgs.buildFHSUserEnv provides only a minimal fhs environment,
# it lacks many basic packages needed by most softwares.
# so we need to add them manually.
# pkgs.buildFHSUserEnv provides only a minimal FHS environment,
# lacking many basic packages needed by most software.
# Therefore, we need to add them manually.
#
# pkgs.appimageTools provides basic packages needed by most softwares.
# pkgs.appimageTools provides basic packages required by most software.
(base.targetPkgs pkgs) ++ with pkgs; [
pkg-config
ncurses
# feel free to add more packages here, if you need
# Feel free to add more packages here if needed.
]
);
profile = "export FHS=1";
@ -43,19 +41,19 @@ To create such an environment, add the following code to one of your Nix modules
}
```
After applying the updated configuration, you can run `fhs` to enter the FHS environment, and then run the binary you downloaded, e.g.
After applying the updated configuration, you can use the `fhs` command to enter the FHS environment, and then execute the binary you downloaded, for example:
```shell
# Activating FHS drops me in a shell which looks like a "normal" Linux
# Activating FHS drops me into a shell that resembles a "normal" Linux environment.
$ fhs
# check what we have in /usr/bin
# Check what we have in /usr/bin.
(fhs) $ ls /usr/bin
# try to run a non-nixos binary downloaded from the Internet
# Try running a non-NixOS binary downloaded from the Internet.
(fhs) $ ./bin/code
```
## References
- [Tips&Tricks for NixOS Desktop - NixOS Discourse][Tips&Tricks for NixOS Desktop - NixOS Discourse]: Just as the title says, it is a collection of tips and tricks for NixOS desktop.
- [Tips&Tricks for NixOS Desktop - NixOS Discourse][Tips&Tricks for NixOS Desktop - NixOS Discourse]: This resource provides a collection of useful tips and tricks for NixOS desktop users.
[Tips&Tricks for NixOS Desktop - NixOS Discourse]: https://discourse.nixos.org/t/tips-tricks-for-nixos-desktop/28488
[Tips&Tricks for NixOS Desktop - NixOS Discourse]: https://discourse.nixos.org/t/tips-tricks-for-nixos-desktop/28488

View File

@ -1,14 +1,13 @@
# Simplify NixOS-related commands
# Simplifying NixOS-Related Commands
I use Makefile to simplify NixOS-related commands, which is very convenient.
You can also use other similar tools to do this job(such as [just](https://github.com/casey/just) and [cargo-make](https://github.com/sagiegurari/cargo-make)), here I will only introduce my usage as a reference.
To simplify NixOS-related commands, I utilize a Makefile, which proves to be very convenient. Alternatively, you can also use similar tools like [just](https://github.com/casey/just) and [cargo-make](https://github.com/sagiegurari/cargo-make) for this purpose. Here, I will provide my approach as a reference.
My Makefile looks like this:
Below is an example of how my Makefile looks:
```makefile
#
# NOTE: Makefile's target name should not be the same as one of the file or directory in the current directory,
# otherwise the target will not be executed!
# NOTE: The target names in the Makefile should not conflict with any file or directory names in the current directory.
# Otherwise, the targets will not execute.
#
@ -39,7 +38,7 @@ gc:
############################################################################
#
# Idols, Commands related to my remote distributed building cluster
# Idols: Commands related to my remote distributed building cluster
#
############################################################################
@ -69,4 +68,6 @@ idols: aqua ruby kana
idols-debug: aqua-debug ruby-debug kana-debug
```
Save the above Makefile to the root directory of the flake, and then we can use `make deploy` to deploy the configuration to the local machine, and use `make idols` to deploy the configuration to all my remote servers.
Save the above Makefile to the root directory of your Nix flake. Then, you can use `make deploy` to deploy the configuration to your local machine and `make aqua` to deploy the configuration to all your remote servers.
This approach simplifies the execution of NixOS commands by abstracting them behind target names in the Makefile, providing a more user-friendly and convenient experience.

View File

@ -1,17 +1,15 @@
# Distributed Building
Distributed building can speed up the build process by utilizing multiple machines.
Distributed building can significantly speed up the build process by utilizing multiple machines. However, for ordinary NixOS users, distributed building may not be very useful since `cache.nixos.org` provides a vast majority of caches for the `x86_64` architecture.
For ordinary NixOS users, distributed building is generally not very useful because NixOS's official `cache.nixos.org` provides the vast majority of caches for the `x86_64` architecture.
Distributed building is particularly valuable in scenarios where no cache is available, such as:
Distributed building is of great value in scenarios where there is no cache available, such as:
1. Users of `RISC-V` or `ARM64` architectures, especially `RISC-V`, as there are very few caches for these architectures in the official cache repository. Local compilation is often required.
2. Users who heavily customize their systems. The packages in the official cache repository are built with default configurations. If you modify the build parameters, the official cache is not applicable, and local compilation is necessary. For example, in embedded scenarios, customization of the underlying kernel, drivers, etc., is often required, leading to the need for local compilation.
1. Users of `RISC-V` or `ARM64` architectures (especially `RISC-V`), because there are very few caches for these two architectures in the official cache repository, which often requires a lot of local compilation.
2. Users who customize the system a lot, because the packages in the official cache repository are all default configurations. If you change the build parameters, then the official cache is not applicable, and you need to compile locally. For instance, in the embedded scenario, there is often a need for customization of the underlying kernel, drivers, etc., which leads to the need for local compilation.
## Configuring Distributed Building
## Configure Distributed Building
Currently, there is no official documentation for distributed building. However, I have listed some recommended reference documents at the end of this chapter, along with my distributed build configuration (a NixOS Module).
Currently, there is no official documentation for distributed building. However, I have provided a sample distributed build configuration (a NixOS module) below, along with some recommended reference documents at the end of this section.
```nix
{ ... }: {
@ -22,24 +20,24 @@ Currently, there is no official documentation for distributed building. However,
#
####################################################################
# set local's max-job to 0 to force remote building(disable local building)
# Set local's max-jobs to 0 to force remote building (disable local building).
# nix.settings.max-jobs = 0;
nix.distributedBuilds = true;
nix.buildMachines =
let
sshUser = "ryan";
# ssh key's path on local machine
# Path to the SSH key on the local machine.
sshKey = "/home/ryan/.ssh/ai-idols";
systems = [
# native arch
# Native architecture.
"x86_64-linux"
# emulated arch using binfmt_misc and qemu-user
# Emulated architecture using binfmt_misc and qemu-user.
"aarch64-linux"
"riscv64-linux"
];
# all available system features are poorly documentd here:
# https://github.com/NixOS/nix/blob/e503ead/src/libstore/globals.hh#L673-L687
# All available system features are poorly documented here:
# https://github.com/NixOS/nix/blob/e503ead/src/libstore/globals.hh#L673-L687
supportedFeatures = [
"benchmark"
"big-parallel"
@ -47,22 +45,22 @@ Currently, there is no official documentation for distributed building. However,
];
in
[
# Nix seems always give priority to trying to build remotely
# to make use of the local machine's high-performance CPU, do not set remote builder's maxJobs too high.
# Nix seems to always prioritize remote building.
# To make use of the local machine's high-performance CPU, do not set the remote builder's maxJobs too high.
{
# some of my remote builders are running NixOS
# and has the same sshUser, sshKey, systems, etc.
# Some of my remote builders are running NixOS
# and have the same sshUser, sshKey, systems, etc.
inherit sshUser sshKey systems supportedFeatures;
# the hostName should be:
# 1. a hostname that can be resolved by DNS
# 2. the ip address of the remote builder
# 3. a host alias defined globally in /etc/ssh/ssh_config
# The hostName should be:
# 1. A hostname that can be resolved by DNS.
# 2. The IP address of the remote builder.
# 3. A host alias defined globally in /etc/ssh/ssh_config.
hostName = "aquamarine";
# remote builder's max-job
# Remote builder's max-jobs.
maxJobs = 3;
# speedFactor's a signed integer
# but it seems that it's not used by Nix, takes no effect
# SpeedFactor is a signed integer,
# but it seems that it's not used by Nix and has no effect.
speedFactor = 1;
}
{
@ -78,13 +76,15 @@ Currently, there is no official documentation for distributed building. However,
speedFactor = 1;
}
];
# optional, useful when the builder has a faster internet connection than yours
# Optional: Useful when the builder has a faster internet connection than yours.
nix.extraOptions = ''
builders-use-substitutes = true
builders-use-sub
stitutes = true
'';
# define the host alias for remote builders
# this config will be written to /etc/ssh/ssh_config
# Define the host aliases for remote builders.
# This configuration will be written to /etc/ssh/ssh_config.
programs.ssh.extraConfig = ''
Host ai
HostName 192.168.5.100
@ -103,8 +103,8 @@ Currently, there is no official documentation for distributed building. However,
Port 22
'';
# define the host key for remote builders so that nix can verify all the remote builders
# this config will be written to /etc/ssh/ssh_known_hosts
# Define the host keys for remote builders so that Nix can verify all the remote builders.
# This configuration will be written to /etc/ssh/ssh_known_hosts.
programs.ssh.knownHosts = {
# 星野 愛久愛海, Hoshino Aquamarine
aquamarine = {
@ -127,19 +127,18 @@ Currently, there is no official documentation for distributed building. However,
}
```
## Defects
## Limitations
The problems I have observed so far are:
Here are some observed issues and limitations:
1. You cannot specify which hosts to use at build time, you can only specify a list of hosts in the configuration file, and nix automatically selects available hosts.
two。
2. When choosing a host, I found that Nix always preferred the remote host, while my local host had the best performance, which caused the local host's CPU to be underutilized.
3. The smallest unit of distributed building is Derivation, so when building some big packages, other machines may be idle for a long time, waiting for the big package to be built, which leads to a waste of resources.
1. You cannot specify which hosts to use at build time. You can only specify a list of hosts in the configuration file, and Nix automatically selects available hosts.
2. When choosing a host, Nix always prefers the remote host over the local host, even if the local host has better performance. This can result in underutilization of the local host's CPU.
3. The smallest unit of distributed building is a derivation. When building large packages, other machines may remain idle for a long time, waiting for the large package to be built. This can lead to resource wastage.
## References
- [Distributed build - NixOS Wiki](https://nixos.wiki/wiki/Distributed_build)
- [Document available system features - nix#7380](https://github.com/NixOS/nix/issues/7380)
- [Distributed builds seem to disable local builds nix#2589](https://github.com/NixOS/nix/issues/2589)
- [Distributed builds seem to disable local builds - nix#2589](https://github.com/NixOS/nix/issues/2589)
- [Offloading NixOS builds to a faster machine](https://sgt.hootr.club/molten-matter/nix-distributed-builds/)
- [tests/nixos/remote-builds.nix - Nix Source Code](https://github.com/NixOS/nix/blob/713836112/tests/nixos/remote-builds.nix#L46)
- [tests/nixos/remote-builds.nix - Nix Source Code](https://github.com/NixOS/nix/blob/713836112/tests/nixos/remote-builds.nix#L46)

View File

@ -1,6 +1,6 @@
# Development Environments on NixOS
NixOS's reproducibility makes it ideal for building development environments. However, if you're used to other distros, you may encounter problems because NixOS has its own logic. We'll explain this briefly below.
NixOS's reproducibility makes it ideal for building development environments. However, if you're used to other distros, you may encounter problems because NixOS has its own logic. We'll briefly explain this below.
On NixOS, it's recommended to only install common tools in the global environment, such as `git`, `vim`, `emacs`, `tmux`, `zsh`, etc. The development environment of each language should be an independent environment for each project.
@ -67,9 +67,9 @@ stdenv.mkDerivation ({
} // rest)
```
`pkgs.mkShell { ... }` is a special Derivation (Nix package). Its `name` `buildInputs` and other parameters are customizable, and `shellHook` is a special parameter that will be executed when `nix develop` enters the environment.
`pkgs.mkShell { ... }` is a special derivation (Nix package). Its `name`, `buildInputs`, and other parameters are customizable, and `shellHook` is a special parameter that will be executed when `nix develop` enters the environment.
Here is a `flake.nix` that defined a development environment with nodejs 18 installed:
Here is a `flake.nix` that defines a development environment with Node.js 18 installed:
```nix
{

View File

@ -2,26 +2,25 @@
## Advantages
- **Declarative configuration, Environment as Code, can be managed with Git**
- Nix Flakes lock dependencies' version through a lock file named `flake.lock`, to ensure that the system is reproducible. This idea actually borrows from some package managers such as npm, cargo, etc.
- Compared with Docker, Nix Flakes provides a much stronger guarantee for the reproducibility of build results, because Dockerfile is actually an imperative configuration and there is no such thing as `flake.lock` in Docker, Docker's reproducibility relies on sharing the build result (which is MUCH LARGER than the Dockerfile itself) through an image registry (e.g. Docker Hub).
- **Highly convenient system customization capability**
- By changing a few lines of configuration, various components of NixOS can be easily customized. This is because Nix encapsulates all the underlying complex operations in Nix packages and only exports concise and necessary declarative parameters.
- Moreover, this modification is very safe. For example, switching between different desktop environments on NixOS is very simple and clean, you just need to change several lines of the configuration.
- **Rollback**: The system can be restored to any historical state at any time(except the state that is NOT managed by NixOS, such as docker containers, postgresql data, etc...), and NixOS even adds all old versions to the boot options by default to ensure that the system can be rolled back at any time even though it crashes. Therefore, NixOS is also considered one of the most stable Linux Systems.
- **No dependency conflicts**: Each software package in Nix has a unique hash, its installation path also includes this hash value, so multiple versions can coexist.
- **Active community and third-party projects**. The official package repository, nixpkgs, has many contributors, and many people share their Nix configuration on Github/Gitlab. After browsing through it, the entire ecosystem gives me a sense of excitement in discovering a new continent.
- **Declarative Configuration and Git Integration**:
- Nix Flakes uses a lock file named `flake.lock` to lock dependencies' versions, ensuring system reproducibility. This concept is borrowed from package managers like npm and cargo.
- Compared to Docker, Nix Flakes provides stronger guarantees for reproducibility of build results. Dockerfile is an imperative configuration without an equivalent of `flake.lock`. Docker's reproducibility relies on sharing the large build result through an image registry like Docker Hub.
- **Highly Convenient System Customization**:
- NixOS allows easy customization of various components by modifying a few lines of configuration. Nix encapsulates complex operations in Nix packages and exposes concise and necessary declarative parameters.
- Customization is also safe. For instance, switching between different desktop environments on NixOS is simple and clean, requiring only a few configuration changes.
- **Rollback Capability**: The system can be restored to any previous state at any time (excluding content not managed by NixOS, such as Docker containers and PostgreSQL data). NixOS even adds all old versions to the boot options by default, ensuring the ability to roll back even in case of system crashes. NixOS is considered one of the most stable Linux systems.
- **No Dependency Conflicts**: Each software package in Nix has a unique hash, and its installation path includes this hash value, enabling coexistence of multiple versions.
- **Active Community and Third-Party Projects**: The official package repository, nixpkgs, has numerous contributors, and many individuals share their Nix configurations on GitHub/GitLab. Exploring this ecosystem is like discovering a new continent, filled with excitement.
## Disadvantages
- **High learning curve:**: To use NixOS effectively and avoid pitfalls caused by improper use, you need to learn about the entire design of Nix and manage the system in a declarative manner. You should not blindly use `nix-env -i` (which is similar to `apt-get install`).
- **Chaotic documentation**: Flakes is still an experimental feature, and there are currently few documents introducing it, Most of the Nix community's documentation only introduces the old cli such as `nix-env`/`nix-channel`. If you want to start learning Nix directly from Flakes, you need to refer to a large number of old documents and extract what you need from them. In addition, some of Nix's current core functions are not well-documented (such as `imports` and Nix Module System), to figure out what it does, it is best to look at the source code...
- **Relatively high disk space usage**: To ensure that the system can be rolled back at any time, Nix preserves all historical environments by default, which can take up a lot of disk space. This can be a problem, especially on some resource-constrained Virtual Machines.
- **Obscure error messages**: Sometimes you may come across some strange error messages and not understand what's going on.
`--show-trace` may throw you a stack of errors that are of little help.
- **Steep Learning Curve**: To effectively use NixOS and avoid pitfalls, understanding the entire design of Nix and managing the system declaratively is necessary. Blindly using `nix-env -i` (similar to `apt-get install`) should be avoided.
- **Chaotic Documentation**: Flakes is still an experimental feature, and there is limited documentation available. Most of the Nix community's documentation focuses on the old CLI tools like `nix-env` and `nix-channel`. If starting directly with Flakes, you'll need to refer to a large number of old documents and extract the relevant information. Additionally, some core functions of Nix are poorly documented (e.g., `imports` and Nix Module System), requiring reading the source code for clarity.
- **Relatively High Disk Space Usage**: By default, Nix preserves all historical environments to facilitate rollback, resulting in significant disk space usage. This can be a concern, particularly on resource-constrained virtual machines.
- **Obscure Error Messages**: At times, encountering cryptic error messages can be confusing, leaving you unsure of what went wrong. Using `--show-trace` may provide a stack of errors that offer limited help.
## Summary
Generally speaking, I think NixOS is suitable for developers who have some experience in using Linux and programming and want to have more control over their systems.
In general, I believe NixOS is suitable for developers with experience in using Linux and programming, who desire greater control over their systems.
I don't recommend you get started with NixOS if you are new to Linux, it can be a very painful journey.
If you are new to Linux, I do not recommend starting with NixOS, as it can be a challenging journey.

View File

@ -1,32 +1,29 @@
# Introduction to Nix & NixOS
Nix is a declarative package manager, that allows users to declare the expected system state in some configuration files, and Nix is responsible for achieving that goal.
Nix is a declarative package manager that enables users to specify the desired system state in configuration files. It takes responsibility for achieving that goal.
> In simple terms, "declarative configuration" means that users only need to declare the result they want. For example, you declare that you want to replace the i3 window manager with sway, then Nix will help you achieve the goal. You don't need to worry about the underlying details (such as which packages sway needs to install, which i3-related packages need to be uninstalled, which system configuration or environment variables need to be adjusted for sway, what adjustments need to be made to the Sway parameters if an Nvidia graphics card is used, etc.), Nix will automatically handle these details for the user(prerequisite: if the nix packages related to sway & i3 are designed properly.).
> In simple terms, "declarative configuration" means that users only need to declare the desired outcome. For instance, if you declare that you want to replace the i3 window manager with sway, Nix will assist you in achieving that goal. You don't have to worry about the underlying details, such as which packages sway requires for installation, which i3-related packages need to be uninstalled, or the necessary adjustments to system configuration and environment variables for sway. Nix automatically handles these details for the user (provided that the Nix packages related to sway and i3 are properly designed).
NixOS, the Linux distribution built on top of the Nix package manager, can be simply described as "OS as Code", which describes the entire operating system's state using declarative Nix configuration files.
NixOS, a Linux distribution built on top of the Nix package manager, can be described as "OS as Code." It employs declarative Nix configuration files to describe the entire state of the operating system.
An operating system has a variety of software packages, configuration files, text/binary data, which are all the current state of the system, and declarative configuration can manage only the static part of it.
Those dynamic data (such as PostgreSQL/MySQL/MongoDB data) are obviously not manageable through a declarative configuration (you can't just delete all new postgresql data that is not declared in the configuration at every deployment).
Therefore, **NixOS actually only supports to manage part of the state of the system in a declarative way**, and all the dynamic data mentioned above, as well as all the contents in the user's home directory, are not controlled by it (so when you rollback your NixOS to the last generation, NixOS will do nothing on these content).
An operating system consists of various software packages, configuration files, and text/binary data, all of which represent the current state of the system. Declarative configuration can manage only the static portion of this state. Dynamic data, such as PostgreSQL, MySQL, or MongoDB data, cannot be effectively managed through declarative configuration. It is not feasible to delete all new PostgreSQL data that is not declared in the configuration during each deployment. Therefore, **NixOS primarily focuses on managing a portion of the system state in a declarative manner**. Dynamic data mentioned above, along with the contents in the user's home directory, remain unaffected by NixOS when rolling back to a previous generation.
Although we cannot make the entire system reproducible, the `/home` directory, as an important user directory, does have many necessary configuration files.
Another important community project, [home-manager](https://github.com/nix-community/home-manager), filled this gap.
home-manager is designed to manage user-level packages & configuration files in user's home directory.
Although we cannot achieve complete system reproducibility, the `/home` directory, being an important user directory, contains many necessary configuration files. To bridge this gap, a significant community project called [home-manager](https://github.com/nix-community/home-manager) was initiated. home-manager is designed to manage user-level packages and configuration files within the user's home directory.
Due to Nix's features such as declarative and reproducible, Nix is not only used to manage desktop environments but also widely used to manage development environments, compilation environments, cloud virtual machines, container image construction, etc. [NixOps](https://github.com/NixOS/nixops) from the Nix official and [deploy-rs](https://github.com/serokell/deploy-rs) from the community are both operations tools based on Nix.
Due to Nix's features, such as being declarative and reproducible, Nix is not limited to managing desktop environments but is also extensively used for managing development environments, compilation environments, cloud virtual machines, and container image construction. [NixOps](https://github.com/NixOS/nixops) from the official Nix project and [deploy-rs](https://github.com/serokell/deploy-rs) from the community are both operational tools based on Nix.
## Why NixOS?
I heard about the Nix package manager several years ago. It uses the Nix language to describe system configuration, and the Linux distribution built on top of it can roll back the system to any historical state at any time(In fact, only the state declared by nix configuration files can be rollback). Although it sounds impressive, it requires learning a new language and writing code to install packages, I thought it was too troublesome and didn't study it at the time.
I first learned about the Nix package manager several years ago. It utilizes the Nix language to describe system configuration, and the Linux distribution built on top of it allows for rolling back the system to any previous state (though only the state declared in Nix configuration files can be rolled back). While it sounded impressive, I found it troublesome to learn a new language and write code to install packages, so I didn't pursue it at the time.
But I recently encountered a lot of environmental problems in the process of using EndeavourOS, and I spent a lot of energy solving them, which made me exhausted. After thinking about it carefully, I realized that the root cause was that EndeavourOS do not have any version control and rollback mechanism, which caused the system to be unable to be restored when problems occurred.
However, I recently encountered numerous environmental issues while using EndeavourOS, and resolving them consumed a significant amount of my energy, leaving me exhausted. Upon careful consideration, I realized that the lack of version control and rollback mechanisms in EndeavourOS prevented me from restoring the system when problems arose.
So I switched to NixOS.
That's when I decided to switch to NixOS.
I am quite satisfied with NixOS, even more than expected.
The most amazing thing is, now I can restore the entire i3 environment and my commonly used packages on a fresh NixOS host with just one command, that's really fantastic!
To my delight, NixOS has exceeded my expectations. The most astonishing aspect is that I can now restore my entire i3 environment and all my commonly used packages on a fresh NixOS host with just one command. It's truly fantastic!
The rollback capability of NixOS gave me a lot of confidence - I no longer fear breaking the system anymore. I even tried a lot of new things on NixOS, such as hyprland compositor. (I wouldn't have dared to play with such new compositors on EndeavourOS - it would have been a big hassle if something went wrong with the system and I need to fix it manually through various tricks.)
The rollback capability of NixOS has instilled a great deal of confidence in me—I no longer fear breaking the system. I've even ventured into experimenting with new things on
That's why I chose NixOS.
NixOS, such as the hyprland compositor. Previously, on EndeavourOS, I wouldn't have dared to tinker with such novel compositors, as any system mishaps would have entailed significant manual troubleshooting using various workarounds.
This is why I chose NixOS.

View File

@ -1,10 +1,10 @@
# Installation
Nix can be installed in multiple ways:
Nix can be installed in various ways:
1. As a package manager on macOS/Linux/WSL.
2. Manage the entire system environment on NixOS, it's a Linux distribution that uses Nix to manage the system.
1. As a package manager on macOS, Linux, or WSL.
2. As the system environment manager on NixOS, a Linux distribution that utilizes Nix for system management.
This book focuses on introducing the usage of NixOS & Flakes, so we will skip the content related only to Nix.
This book primarily focuses on the usage of NixOS and Flakes. Therefore, we will skip content that pertains solely to Nix.
The installation process of NixOS is simple, and we won't go into details here. Please visit the official download site for more information: <https://nixos.org/download.html>.
The installation process of NixOS is straightforward, but we won't delve into the specifics here. For more information, please visit the official download site at <https://nixos.org/download.html>.

View File

@ -1,42 +1,36 @@
# Downgrading or Upgrading Packages
After using Flakes, most people are currently using the `nixos-unstable` branch of nixpkgs. However, sometimes you may encounter bugs, such as the [chrome/vscode crash problem](https://github.com/swaywm/sway/issues/7562).
When working with Flakes, you may encounter situations where you need to downgrade or upgrade certain packages to address bugs or compatibility issues. In Flakes, package versions and hash values are directly tied to the git commit of their flake input. To modify the package version, you need to lock the git commit of the flake input.
To resolve these issues, you may need to downgrade or upgrade some packages. In Flakes, all package versions and hash values correspond one-to-one to the git commit of their flake input. Therefore, to downgrade or upgrade a package, you need to lock the git commit of its flake input.
For example, you can add multiple nixpkgs, each using a different git commit or branch:
Here's an example of how you can add multiple nixpkgs inputs, each using a different git commit or branch:
```nix
{
description = "NixOS configuration of Ryan Yin"
description = "NixOS configuration of Ryan Yin";
inputs = {
# default to nixos-unstable branch
# Default to the nixos-unstable branch
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
# the latest stable branch of nixpkgs, used to rollback the version of some packages
# the current latest version is 22.11
# Latest stable branch of nixpkgs, used for version rollback
# The current latest version is 22.11
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-22.11";
# we can also use git commit hash to lock the version
# You can also use a specific git commit hash to lock the version
nixpkgs-fd40cef8d.url = "github:nixos/nixpkgs/fd40cef8d797670e203a27a91e4b8e6decf0b90c";
outputs = inputs@{
self,
nixpkgs,
nixpkgs-stable,
nixpkgs-fd40cef8d,
...
}: {
};
outputs = inputs@{ self, nixpkgs, nixpkgs-stable, nixpkgs-fd40cef8d, ... }: {
nixosConfigurations = {
nixos-test = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
# The core parameter, which passes the non-default nixpkgs instances to other nix modules
# The `specialArgs` parameter passes the non-default nixpkgs instances to other nix modules
specialArgs = {
# To use packages from nixpkgs-stable, we need to configure some parameters for it first
# To use packages from nixpkgs-stable, we configure some parameters for it first
pkgs-stable = import nixpkgs-stable {
system = system; # refer the `system` parameter form outer scope recursively
# To use chrome, we need to allow the installation of non-free software
system = system; # Refer to the `system` parameter from the outer scope recursively
# To use Chrome, we need to allow the installation of non-free software
config.allowUnfree = true;
};
pkgs-fd40cef8d = import nixpkgs-fd40cef8d {
@ -44,10 +38,11 @@ For example, you can add multiple nixpkgs, each using a different git commit or
config.allowUnfree = true;
};
};
modules = [
./hosts/nixos-test
# omit other configuration...
# Omit other configurations...
];
};
};
@ -55,35 +50,40 @@ For example, you can add multiple nixpkgs, each using a different git commit or
}
```
And then refer to the packages from `pkgs-stable` or `pkgs-fd40cef8d` in your sub module, a home manager's sub module as an example:
In the above example, we have defined multiple nixpkgs inputs: `nixpkgs`, `nixpkgs-stable`, and `nixpkgs-fd40cef8d`. Each input corresponds to a different git commit or branch.
Next, you can refer to the packages from `pkgs-stable` or `pkgs-fd40cef8d` within your submodule. Here's an example of a Home Manager submodule:
```nix
{
pkgs,
config,
# nix will search and jnject this parameter from specialArgs in flake.nix
# Nix will search for and inject this parameter from `specialArgs` in `flake.nix`
pkgs-stable,
# pkgs-fd40cef8d,
...
}:
{
# refer packages from pkgs-stable instead of pkgs
# Use packages from `pkgs-stable` instead of `pkgs`
home.packages = with pkgs-stable; [
firefox-wayland
# chrome wayland support was broken on nixos-unstable branch, so fallback to stable branch for now
# https://github.com/swaywm/sway/issues/7562
# Chrome Wayland support was broken on the nixos-unstable branch, so we fallback to the stable branch for now
# Reference: https://github.com/swaywm/sway/issues/7562
google-chrome
];
programs.vscode = {
enable = true;
package = pkgs-stable.vscode; # refer vscode from pkgs-stable instead of pkgs
enable
= true;
package = pkgs-stable.vscode; # Refer to vscode from `pkgs-stable` instead of `pkgs`
};
}
```
After adjusting the configuration, deploy it with `sudo nixos-rebuild switch`. This will downgrade your Firefox/Chrome/VSCode to the version corresponding to `nixpkgs-stable` or `nixpkgs-fd40cef8d`.
By adjusting the configuration as shown above, you can deploy it using `sudo nixos-rebuild switch`. This will downgrade your Firefox/Chrome/VSCode versions to the ones corresponding to `nixpkgs-stable` or `nixpkgs-fd40cef8d`.
>According to [1000 instances of nixpkgs](https://discourse.nixos.org/t/1000-instances-of-nixpkgs/17347), it's not a good practice to use `import` in submodules to customize `nixpkgs`. Each `import` creates a new instance of nixpkgs, which increases build time and memory usage as the configuration grows. To avoid this problem, we create all nixpkgs instances in `flake.nix`.

View File

@ -1,18 +1,18 @@
# Get Started with NixOS
After learning the basics of the Nix language, we can start using it to configure our NixOS. The default configuration for NixOS is located at `/etc/nixos/configuration.nix`, which contains all the declarative configuration for the system, such as time zone, language, keyboard layout, network, users, file system, boot options, etc.
Now that we have learned the basics of the Nix language, we can start using it to configure our NixOS system. The default configuration file for NixOS is located at `/etc/nixos/configuration.nix`. This file contains all the declarative configuration for the system, including settings for the time zone, language, keyboard layout, network, users, file system, and boot options.
To modify the system state in a reproducible way (**which is the most recommended way**), we need to manually edit `/etc/nixos/configuration.nix`, and then execute `sudo nixos-rebuild switch` to apply the modified configuration. This generates a new system environment based on the modified configuration file, sets the new environment as the default one, and preserves the previous environment in the boot options of grub/systemd-boot. This ensures that we can always roll back to the old environment (even if the new environment fails to start).
To modify the system state in a reproducible manner (which is highly recommended), we need to manually edit the `/etc/nixos/configuration.nix` file and then execute `sudo nixos-rebuild switch` to apply the modified configuration. This command generates a new system environment based on the modified configuration file, sets the new environment as the default one, and preserves the previous environment in the boot options of grub/systemd-boot. This ensures that we can always roll back to the old environment if the new one fails to start.
`/etc/nixos/configuration.nix` is the classic method to configure NixOS, which relies on data sources configured by `nix-channel` and has no version-locking mechanism, making it difficult to ensure the reproducibility of the system. **A better approach is to use Flakes**, which ensures the reproducibility of the system and makes it easy to manage the configuration.
While `/etc/nixos/configuration.nix` is the classic method for configuring NixOS, it relies on data sources configured by `nix-channel` and lacks a version-locking mechanism, making it challenging to ensure the reproducibility of the system. A better approach is to use Flakes, which provides reproducibility and facilitates configuration management.
Now, let's learn how to manage NixOS through the classic method, `/etc/nixos/configuration.nix`, and then migrate to the more advanced Flakes.
In this section, we will first learn how to manage NixOS using the classic method (`/etc/nixos/configuration.nix`), and then we will explore the more advanced Flakes.
## Configuring the system using `/etc/nixos/configuration.nix`
## Configuring the System using `/etc/nixos/configuration.nix`
This is the classic method to configure NixOS, and also the default method currently used by NixOS. It relies on data sources configured by `nix-channel` and has no version-locking mechanism, making it difficult to ensure the reproducibility of the system.
The `/etc/nixos/configuration.nix` file is the default and classic method for configuring NixOS. While it lacks some of the advanced features of Flakes, it is still widely used and provides flexibility in system configuration.
For example, to enable ssh and add a user `ryan`, simply add the following content into `/etc/nixos/configuration.nix`:
To illustrate how to use `/etc/nixos/configuration.nix`, let's consider an example where we enable SSH and add a user named `ryan` to the system. We can achieve this by adding the following content to `/etc/nixos/configuration.nix`:
```nix
{ config, pkgs, ... }:
@ -23,15 +23,15 @@ For example, to enable ssh and add a user `ryan`, simply add the following conte
./hardware-configuration.nix
];
# Omit the previous configuration.......
# Omit previous configuration settings...
# add user ryan
# Add user 'ryan'
users.users.ryan = {
isNormalUser = true;
description = "ryan";
extraGroups = [ "networkmanager" "wheel" ];
openssh.authorizedKeys.keys = [
# replace with your own public key
# Replace with your own public key
"ssh-ed25519 <some-public-key> ryan@ryan-pc"
];
packages = with pkgs; [
@ -40,32 +40,32 @@ For example, to enable ssh and add a user `ryan`, simply add the following conte
];
};
# enable openssh-server
# Enable openssh-server
services.openssh = {
enable = true;
permitRootLogin = "no"; # disable root login
passwordAuthentication = false; # disable password login
permitRootLogin = "no"; # Disable root login
passwordAuthentication = false; # Disable password login
openFirewall = true;
forwardX11 = true; # enable X11 forwarding
forwardX11 = true; # Enable X11 forwarding
};
# omit the rest of the configuration.......
# Omit the rest of the configuration...
}
```
In this configuration, we declared that we want to enable the openssh service, add an ssh public key for the user ryan, and disable password login.
In this configuration, we declare our intention to enable the openssh service, add an SSH public key for the user 'ryan', and disable password login.
Now, run `sudo nixos-rebuild switch` to deploy the modified configuration. After that, you can log in to the system using ssh with the ssh keys you configured.
To deploy the modified configuration, run `sudo nixos-rebuild switch`. This command will apply the changes, generate a new system environment, and set it as the default. You can now log in to the system using SSH with the configured SSH keys.
Any reproducible changes to the system can be made by modifying `/etc/nixos/configuration.nix` and deploying the changes by running `sudo nixos-rebuild switch`.
Remember that any reproducible changes to the system can be made by modifying the `/etc/nixos/configuration.nix` file and deploying the changes with `sudo nixos-rebuild switch`.
All configuration options in `/etc/nixos/configuration.nix` can be found in the following places:
To find configuration options and documentation:
- By searching on Google, such as `Chrome NixOS`, which will provide NixOS information related to Chrome. Generally, the NixOS Wiki and the source code of Nixpkgs will be among the top results.
- By searching for keywords in [NixOS Options Search](https://search.nixos.org/options).
- For system-level configuration, relevant documentation can be found in [Configuration - NixOS Manual](https://nixos.org/manual/nixos/unstable/index.html#ch-configuration).
- By searching for keywords directly in the source code of [nixpkgs](https://github.com/NixOS/nixpkgs) on GitHub.
- Use search engines like Google, e.g., search for `Chrome NixOS` to find NixOS-related information about Chrome. The NixOS Wiki and the source code of Nixpkgs are usually among the top results.
- Utilize the [NixOS Options Search](https://search.nixos.org/options) to search for keywords.
- Refer to the [Configuration section](https://nixos.org/manual/nixos/unstable/index.html#ch-configuration) in the NixOS Manual for system-level configuration documentation.
- Search for keywords directly in the source code of [nixpkgs](https://github.com/NixOS/nixpkgs) on GitHub.
## References
- [Overview of the NixOS Linux distribution](https://nixos.wiki/wiki/Overview_of_the_NixOS_Linux_distribution)
- [Overview of the NixOS Linux distribution](https://nixos.wiki/wiki/Overview_of_the_NixOS_Linux_distribution)

View File

@ -4,44 +4,40 @@ The flakes experimental feature is a major development for Nix, it introduces a
Flakes is one of the most significant changes the nix project has ever seen.[^2]
## Warning about Flakes
## A Word of Caution about Flakes
The benefits of Flakes are obvious, and the entire NixOS community likes it very much. Currently, more than half of the users are using Flakes[^3], so we're pretty sure that Flakes will never be deprecated.
The benefits of Flakes are evident, and the entire NixOS community has embraced it wholeheartedly. Currently, more than half of the users utilize Flakes[^3], providing assurance that Flakes will not be deprecated.
:warning: But **Flakes is still an experimental feature**, there are still some problems with it, it is likely to introduce some breaking changes in the process of stablizing it, and its uncertain how greatly the breaking changes will be.
:warning: However, it's important to note that **Flakes is still an experimental feature**. Some issues persist, and there is a possibility of introducing breaking changes during the stabilization process. The extent of these breaking changes remains uncertain.
Overall, I still recommend everyone to use Flakes, this book is also written around NixOS and Flakes after all, but please be prepared for the problems that may be caused by the upcomming breaking changes.
Overall, I strongly recommend everyone to use Flakes, especially since this book revolves around NixOS and Flakes. However, it's crucial to be prepared for potential problems that may arise due to forthcoming breaking changes.
## Nix Flakes and Classic Nix
As `nix-command` and `flakes` are still experimental features, the official documentation does not cover them in detail, and the community's documentation about them is also scattered. However, from the perspective of reproducibility and ease of management and maintenance, the classic Nix package structure and CLI are no longer recommended for use. Therefore, I will not introduce the usage of the classic Nix. It's recommended that beginners start with `nix-command` and `flakes` and ignore all the contents about the classic Nix.
Since the `nix-command` and `flakes` features are still experimental, the official documentation lacks detailed coverage, and the community's documentation on them is also scattered. From the perspective of reproducibility, ease of management, and maintenance, the classic Nix package structure and CLI are no longer recommended. Therefore, I will not delve into the usage of classic Nix. Beginners are advised to start with `nix-command` and `flakes` while disregarding any content related to classic Nix.
Here are the classic Nix commands and related concepts that are no longer needed after enabling `nix-command` and `flakes`. When searching for information, you can safely ignore them:
The following are classic Nix commands and associated concepts that are no longer necessary after enabling `nix-command` and `flakes`. When searching for information, you can safely ignore them:
1. `nix-channel`: `nix-channel` manages software package versions through stable/unstable/test channels, similar to other package management tools such as apt/yum/pacman.
1. In Flakes, the functionality of `nix-channel` is completely replaced by `inputs` in `flake.nix`.
1. In Flakes, the functionality of `nix-channel` is entirely replaced by the `inputs` section in `flake.nix`.
2. `nix-env`: `nix-env` is a core command-line tool for classic Nix used to manage software packages in the user environment.
1. It installs packages from the data sources added by `nix-channel`, so the installed package's version is influenced by the channel. Packages installed with `nix-env` are not automatically recorded in Nix's declarative configuration and are entirely outside of its control, making them difficult to reproduce on other machines. Therefore, it is not recommended to use this tool.
1. It installs packages from the data sources added by `nix-channel`, causing the installed package's version to be influenced by the channel. Packages installed with `nix-env` are not automatically recorded in Nix's declarative configuration and are completely independent of its control, making them challenging to reproduce on other machines. Therefore, it is not recommended to use this tool.
2. The corresponding command in Flakes is `nix profile`, which is also not recommended for use.
3. `nix-shell`: `nix-shell` creates a temporary shell environment, which is useful for development and testing.
1. In Flakes, this tool is split into three sub-commands: `nix develop`, `nix shell`, and `nix run`. We will introduce these three commands in detail in the "Development" chapter.
1. In Flakes, this tool is divided into three sub-commands: `nix develop`, `nix shell`, and `nix run`. We will discuss these three commands in detail in the "Development" chapter.
4. `nix-build`: `nix-build` builds Nix packages and places the build results in `/nix/store`, but it does not record them in Nix's declarative configuration.
1. In Flakes, `nix-build` is replaced by `nix build`.
5. ...
> NOTE: `nix-env -qa` may still be useful sometimes, as it returns all packages installed in the system.
> NOTE: `nix-env -qa` may still be useful in some cases, as it returns all packages installed in the system.
## When will flakes stablized {#when-will-flakes-stablized}
## When Will Flakes Be Stabilized?
I dived into some details about flakes:
I delved into some details regarding Flakes:
- [[RFC 0136] A plan to stabilize Flakes and the new CLI incrementally](https://github.com/NixOS/rfcs/pull/136): A plan to stabilize Flakes and the new CLI incrementally, still WIP.
- [Why are flakes still experimental? - NixOS Discourse](https://discourse.nixos.org/t/why-are-flakes-still-experimental/29317): A post, Why are flakes still experimental?
- [Flakes are such an obviously good thing - Graham Christensen](https://grahamc.com/blog/flakes-are-an-obviously-good-thing/): Flakes are such an obviously good thing... but the design and development process should be better.
- [Draft: 1 year roadmap - NixOS Foundation](https://nixos-foundation.notion.site/1-year-roadmap-0dc5c2ec265a477ea65c549cd5e568a9): A roadmap of nixos fundation, which includes plan about the stabilization of flakes.
- [[RFC 0136] A Plan to Stabilize Flakes and the New CLI Incrementally](https://github.com/NixOS/rfcs/pull/136): A plan to incrementally stabilize Flakes and the new CLI, still a work in progress.
- [Why Are Flakes Still Experimental? - NixOS Discourse](https://discourse.nixos.org/t/why-are-flakes-still-experimental/29317): A post discussing why Flakes are still considered experimental.
- [Flakes Are Such an Obviously Good Thing - Graham Christensen](https://grahamc.com/blog/flakes-are-an-obviously-good-thing/): An article emphasizing the advantages of Flakes while suggesting areas for improvement in its design and development process.
- [Draft: 1-year Roadmap - NixOS Foundation](https://nixos-foundation.notion.site/1-year-roadmap-0dc5c2ec265a477ea65c549cd5e568a9): A roadmap provided by the NixOS Foundation, which includes plans regarding the stabilization of Flakes.
After reading all of these, I feel like that flakes will eventually be stabilized in one or two years, maybe with some breaking changes.
[^1]: [Flakes - NixOS Wiki](https://nixos.wiki/index.php?title=Flakes)
[^2]: [Flakes are such an obviously good thing](https://grahamc.com/blog/flakes-are-an-obviously-good-thing/)
[^3]: [Draft: 1 year roadmap - NixOS Foundation](https://nixos-foundation.notion.site/1-year-roadmap-0dc5c2ec265a477ea65c549cd5e568a9)
After reviewing these resources, it seems likely that Flakes will be stabilized within one or two years, possibly accompanied by some breaking changes[^1][^2][^3].

View File

@ -1,6 +1,6 @@
# Modularize Your NixOS Configuration
At this point, the skeleton of the entire system is configured. The current configuration structure in `/etc/nixos` should be:
At this point, the skeleton of the entire system is configured. The current configuration structure in `/etc/nixos` should be as follows:
```
$ tree
@ -14,24 +14,21 @@ $ tree
The functions of these four files are:
- `flake.lock`: An automatically generated version-lock file that records all input sources, hash values, and version numbers of the entire flake to ensure reproducibility.
- `flake.nix`: The entry file that will be recognized and deployed when executing `sudo nixos-rebuild switch`.
- See [Flakes - NixOS Wiki](https://nixos.wiki/wiki/Flakes) for all options of flake.nix.
- `configuration.nix`: Imported as a Nix module in flake.nix, all system-level configuration is currently written here.
- See [Configuration - NixOS Manual](https://nixos.org/manual/nixos/unstable/index.html#ch-configuration) for all options of configuration.nix.
- `home.nix`: Imported by Home-Manager as the configuration of the user `ryan` in flake.nix, containing all of `ryan`'s configuration and managing `ryan`'s home folder.
- See [Appendix A. Configuration Options - Home-Manager](https://nix-community.github.io/home-manager/options.html) for all options of home.nix.
- `flake.nix`: The entry file that will be recognized and deployed when executing `sudo nixos-rebuild switch`. See [Flakes - NixOS Wiki](https://nixos.wiki/wiki/Flakes) for all options of flake.nix.
- `configuration.nix`: Imported as a Nix module in flake.nix, all system-level configuration is currently written here. See [Configuration - NixOS Manual](https://nixos.org/manual/nixos/unstable/index.html#ch-configuration) for all options of configuration.nix.
- `home.nix`: Imported by Home-Manager as the configuration of the user `ryan` in flake.nix, containing all of `ryan`'s configuration and managing `ryan`'s home folder. See [Appendix A. Configuration Options - Home-Manager](https://nix-community.github.io/home-manager/options.html) for all options of home.nix.
By modifying these files, you can declaratively change the system and home directory status.
As the configuration increases, it becomes difficult to maintain the configuration by relying solely on `configuration.nix` and `home.nix`. Therefore, a better solution is to use the Nix module system to split the configuration into multiple modules and write them in a classified manner.
The Nix module system provides a parameter, `imports`, which accepts a list of `.nix` files and merges all the configuration defined in these files into the current Nix module. Note that `imports` will not simply overwrite duplicate configuration, but handle it more reasonably. For example, if `program.packages = [...]` is defined in multiple modules, then `imports` will merge all `program.packages` defined in all Nix modules into one list. Attribute sets can also be merged correctly. The specific behavior can be explored by yourself.
The Nix module system provides a parameter, `imports`, which accepts a list of `.nix` files and merges all the configuration defined in these files into the current Nix module. Note that `imports` will not simply overwrite duplicate configuration but handle it more reasonably. For example, if `program.packages = [...]` is defined in multiple modules, then `imports` will merge all `program.packages` defined in all Nix modules into one list. Attribute sets can also be merged correctly. The specific behavior can be explored by yourself.
> I only found a description of `imports` in [Nixpkgs-Unstable Official Manual - evalModules Parameters](https://nixos.org/manual/nixpkgs/unstable/#module-system-lib-evalModules-parameters): `A list of modules. These are merged together to form the final configuration.`, it's a bit ambiguous...
> I only found a description of `imports` in [Nixpkgs-Unstable Official Manual - evalModules Parameters](https://nixos.org/manual/nixpkgs/unstable/#module-system-lib-evalModules-parameters): `A list of modules. These are merged together to form the final configuration.` It's a bit ambiguous...
With the help of `imports`, we can split `home.nix` and `configuration.nix` into multiple Nix modules defined in different `.nix` files.
For example, [ryan4yin/nix-config/v0.0.2](https://github.com/ryan4yin/nix-config/tree/v0.0.2) is the configuration of my previous NixOS system with i3 window manager. Its structure is:
For example, [ryan4yin/nix-config/v0.0.2](https://github.com/ryan4yin/nix-config/tree/v0.0.2) is the configuration of my previous NixOS system with the i3 window manager. Its structure is as follows:
```shell
├── flake.lock
@ -176,12 +173,104 @@ To take a look at the source code of `lib.mkBefore`, run `nix repl -f '<nixpkgs>
# ......
```
So `lib.mkBefore` is a shortcut for `lib.mkOrder 500`, and `lib.mkAfter` is a shortcut for `lib.mkOrder 1500`.
For more details, you can refer to the [ryan4yin/nix-config/v0.0.2](https://github.com/ryan4yin/nix-config/tree/v0.0.2) repository.
## `lib.mkOverride`, `lib.mkDefault`, and `lib.mkForce`
In Nix, some people use `lib.mkDefault` and `lib.mkForce` to define values. These functions are designed to set default values or force values of options.
You can explore the source code of `lib.mkDefault` and `lib.mkForce` by running `nix repl -f '<nixpkgs>'` and then entering `:e lib.mkDefault`. To learn more about `nix repl`, type `:?` for the help information.
Here's the source code:
```nix
# ......
mkOverride = priority: content:
{ _type = "override";
inherit priority content;
};
mkOptionDefault = mkOverride 1500; # priority of option defaults
mkDefault = mkOverride 1000; # used in config sections of non-user modules to set a default
mkImageMediaOverride = mkOverride 60; # image media profiles can be derived by inclusion into host config, hence needing to override host config, but do allow user to mkForce
mkForce = mkOverride 50;
mkVMOverride = mkOverride 10; # used by nixos-rebuild build-vm
# ......
```
In summary, `lib.mkDefault` is used to set default values of options with a priority of 1000 internally, and `lib.mkForce` is used to force values of options with a priority of 50 internally. If you set a value of an option directly, it will be set with a default priority of 1000, the same as `lib.mkDefault`.
The lower the `priority` value, the higher the actual priority. As a result, `lib.mkForce` has a higher priority than `lib.mkDefault`. If you define multiple values with the same priority, Nix will throw an error.
Using these functions can be very helpful for modularizing the configuration. You can set default values in a low-level module (base module) and force values in a high-level module.
For example, in my configuration at [ryan4yin/nix-config/blob/main/modules/nixos/core-server.nix#L30](https://github.com/ryan4yin/nix-config/blob/main/modules/nixos/core-server.nix#L30), I define default values like this:
```nix
{ lib, pkgs, ... }:
{
# ......
nixpkgs.config.allowUnfree = lib.mkDefault false;
# ......
}
```
Then, for my desktop machine, I override the value in [ryan4yin/nix-config/blob/main/modules/nixos/core-desktop.nix#L15](https://github.com/ryan4yin/nix-config/blob/main/modules/nixos/core-desktop.nix#L15) like this:
```nix
{ lib, pkgs, ... }:
{
# import the base module
imports = [
./core-server.nix
];
# override the default value defined in the base module
nixpkgs.config.allowUnfree = lib.mkForce true;
# ......
}
```
## `lib.mkOrder`, `lib.mkBefore`, and `lib.mkAfter`
In addition to `lib.mkDefault` and `lib.mkForce`, there are also `lib.mkBefore` and `lib.mkAfter`, which are used to set the merge order of **list
-type options**. These functions further contribute to the modularization of the configuration.
As mentioned earlier, when you define multiple values with the same **override priority**, Nix will throw an error. However, by using `lib.mkOrder`, `lib.mkBefore`, or `lib.mkAfter`, you can define multiple values with the same override priority, and they will be merged in the order you specify.
To examine the source code of `lib.mkBefore`, you can run `nix repl -f '<nixpkgs>'` and then enter `:e lib.mkBefore`. To learn more about `nix repl`, type `:?` for the help information:
```nix
# ......
mkOrder = priority: content:
{ _type = "order";
inherit priority content;
};
mkBefore = mkOrder 500;
mkAfter = mkOrder 1500;
# The default priority for things that don't have a priority specified.
defaultPriority = 100;
# ......
```
Therefore, `lib.mkBefore` is a shorthand for `lib.mkOrder 500`, and `lib.mkAfter` is a shorthand for `lib.mkOrder 1500`.
To test the usage of `lib.mkBefore` and `lib.mkAfter`, let's create a simple Flake project:
```shell
# create flake.nix with the following content
# Create flake.nix with the following content
cat <<EOF | sudo tee flake.nix
{
description = "Ryan's NixOS Flake";
@ -196,17 +285,17 @@ To test the usage of `lib.mkBefore` and `lib.mkAfter`, let's create a simple Fla
system = "x86_64-linux";
modules = [
# demo module 1, insert git at the head of list
# Demo module 1: insert 'git' at the head of the list
({lib, pkgs, ...}: {
environment.systemPackages = lib.mkBefore [pkgs.git];
})
# demo module 2, insert vim at the tail of list
# Demo module 2: insert 'vim' at the tail of the list
({lib, pkgs, ...}: {
environment.systemPackages = lib.mkAfter [pkgs.vim];
})
# demo module 3, just add curl to the list normally
# Demo module 3: simply add 'curl' to the list
({lib, pkgs, ...}: {
environment.systemPackages = with pkgs; [curl];
})
@ -217,32 +306,34 @@ To test the usage of `lib.mkBefore` and `lib.mkAfter`, let's create a simple Fla
}
EOF
# create flake.lock
# Create flake.lock
nix flake update
# enter nix repl environment
# Enter the nix repl environment
nix repl
Welcome to Nix 2.13.3. Type :? for help.
# load the flake we just created
# Load the flake we just created
nix-repl> :lf .
Added 9 variables.
# check the order of systemPackages
# Check the order of systemPackages
nix-repl> outputs.nixosConfigurations.nixos-test.config.environment.systemPackages
[ «derivation /nix/store/0xvn7ssrwa0ax646gl4hwn8cpi05zl9j-git-2.40.1.drv»
«derivation /nix/store/7x8qmbvfai68sf73zq9szs5q78mc0kny-curl-8.1.1.drv»
«derivation /nix/store/bly81l03kh0dfly9ix2ysps6kyn1hrjl-nixos-container.drv»
......
......
«derivation /nix/store/qpmpvq5azka70lvamsca4g4sf55j8994-vim-9.0.1441.drv» ]
«derivation /nix/store/qpmpv
q5azka70lvamsca4g4sf55j8994-vim-9.0.1441.drv» ]
```
As we can see, the order of `systemPackages` is `git -> curl -> default packages -> vim`, which is the same as the order we defined in `flake.nix`.
As you can see, the order of `systemPackages` is `git -> curl -> default packages -> vim`, which matches the order we defined in `flake.nix`.
> Though it's useless to adjust the order of `systemPackages`, it may be helpful at some other places...
> Although adjusting the order of `systemPackages` may not be useful in practice, it can be helpful in other scenarios.
## References
- [Nix modules: Improving Nix's discoverability and usability ](https://cfp.nixcon.org/nixcon2020/talk/K89WJY/)
- [Module System - Nixpkgs](https://github.com/NixOS/nixpkgs/blob/nixos-unstable/doc/module-system/module-system.chapter.md)
- [Nix modules: Improving Nix's discoverability and usability](https://cfp.nixcon.org/nixcon2020/talk/K89WJY/)
- [Module System - Nixpkgs](https://github.com/NixOS/nixpkgs/blob/nixos-unstable/doc/module-system/module-system.chapter.md)

View File

@ -1,14 +1,14 @@
# NixOS with Flakes Enabled
# Enabling NixOS with Flakes
## Enabling Flakes Support
Flakes provide better reproducibility and a clearer package structure that is easier to maintain compared to the default configuration approach of NixOS. Therefore, it's recommended to manage NixOS with Flakes.
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.
However, as Flakes is still an experimental feature, it's not enabled by default. To enable it, modify `/etc/nixos/configuration.nix` as follows:
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:
```nix
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running 'nixos-help').
{ config, pkgs, ... }:
@ -18,46 +18,50 @@ However, as Flakes is still an experimental feature, it's not enabled by default
./hardware-configuration.nix
];
# omit the previous configuration.......
# Omit the previous configuration...
# enable Flakes and the new command line tool
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Enable Flakes and the new command-line tool
nix = {
package = pkgs.nixFlakes;
extraOptions = ''
experimental-features = nix-command flakes
'';
};
environment.systemPackages = with pkgs; [
# Flakes uses git to pull dependencies from data sources, so git must be installed first
# Flakes use Git to pull dependencies from data sources, so Git must be installed first
git
vim
wget
curl
];
# omit the rest of the configuration.......
# Omit the rest of the configuration...
}
```
To apply the changes, run `sudo nixos-rebuild switch`. After that, you can write the configuration for NixOS with Flakes.
To apply the changes, run `sudo nixos-rebuild switch`. After that, you can start writing the configuration for NixOS using Flakes.
## Switching System Configuration to `flake.nix`
## Switching to `flake.nix` for System Configuration
After enabling `flakes`, `sudo nixos-rebuild switch` will first try to read `/etc/nixos/flake.nix` every time you run it. If not found, it will fallback to `/etc/nixos/configuration.nix`.
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`.
To learn how to write a flake, take a look at the official flake templates provided by Nix. To check which templates are available, run:
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:
```bash
nix flake show templates
```
The templates `templates#full` contain all possible use cases, let's take a look at them:
The `templates#full` template contains examples covering various use cases. Let's take a look at them:
```bash
nix flake init -t templates#full
cat flake.nix
```
After reading the example, create a file `/etc/nixos/flake.nix` and copy the content of the example into it. From now on, all system modifications will be taken over by Flakes with `/etc/nixos/flake.nix`.
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`.
Note that the template we copied cannot be used directly. We need to modify it to make it work. Here's an example of `/etc/nixos/flake.nix`:
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`:
```nix
{
@ -135,24 +139,24 @@ We defined a NixOS system called `nixos-test` with a configuration file at `./co
To apply the configuration, 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.
## Manage System Software through Flakes
## Managing System Packages with Flakes
After the switch, we can manage the system through Flakes. The most common requirement for managing a system is to install packages. We have seen how to install packages through `environment.systemPackages` before, and these packages are all from the official nixpkgs repository.
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.
Now let's learn how to install packages from other sources through Flakes. This is much more flexible than installing from nixpkgs directly, and the most obvious benefit is that you can easily set the version of the software.
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.
Let's use [Helix](https://github.com/helix-editor/helix) editor as an example. First, we need to add Helix as an input to `flake.nix`:
First, we need to add Helix as an input in `flake.nix`:
```nix
{
description = "NixOS configuration of Ryan Yin";
# ......
# ...
inputs = {
# ......
# ...
# helix editor, use the tag 23.05
# Helix editor, using version 23.05
helix.url = "github:helix-editor/helix/23.05";
};
@ -161,8 +165,8 @@ Let's use [Helix](https://github.com/helix-editor/helix) editor as an example. F
nixos-test = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
# set all inputs parameters as specialArgs of all sub module
# so that we can use `helix` input in sub modules
# Set all input parameters as specialArgs of all sub-modules
# so that we can use the `helix` input in sub-modules
specialArgs = inputs;
modules = [
./configuration.nix
@ -173,7 +177,7 @@ Let's use [Helix](https://github.com/helix-editor/helix) editor as an example. F
}
```
Then update `configuration.nix` to install `helix` from the input `helix`:
Next, update `configuration.nix` to install `helix` from the `helix` input:
```nix
# Nix will automatically inject `helix` from specialArgs
@ -181,7 +185,7 @@ Then update `configuration.nix` to install `helix` from the input `helix`:
{ config, pkgs, helix, ... }:
{
# omit other configuration......
# Omit other configurations...
environment.systemPackages = with pkgs; [
git
@ -189,44 +193,44 @@ Then update `configuration.nix` to install `helix` from the input `helix`:
wget
curl
# install helix from the input `helix`
# Install Helix from the `helix` input
helix.packages."${pkgs.system}".helix
];
# omit other configuration......
# Omit other configurations...
}
```
To deploy the changes, run `sudo nixos-rebuild switch`. Then start the Helix editor by running the `hx` command.
To deploy the changes, run `sudo nixos-rebuild switch`. After that, you can start the Helix editor by running the `hx` command.
## Add Custom Cache Mirror
## Adding Custom Cache Mirrors
> If you don't need to customize the cache mirror, you can safely skip this section.
To speed up package building, Nix provides <https://cache.nixos.org> to cache build results and avoid building every package locally.
To accelerate package building, Nix provides <https://cache.nixos.org> to cache build results and avoid rebuilding packages locally.
With the classic configuration method in NixOS, other cache sources can be added using `nix-channel`. However, Flakes avoids using any system-level configuration and environment variables to ensure that its build results are not affected by the environment, making the build results reproducible.
With the classic configuration method in NixOS, additional cache sources can be added using `nix-channel`. However, Flakes avoids relying on system-level configuration and environment variables to ensure reproducibility of its build results.
Therefore, to customize the cache source, we must add the related configuration in `flake.nix` using the `nixConfig` parameter. Here's an example:
To customize the cache source, we must add the related configuration in `flake.nix` using the `nixConfig` parameter. Here's an example:
```nix
{
description = "NixOS configuration of Ryan Yin";
# 1. To ensure purity, Flakes does not rely on the system's `/etc/nix/nix.conf`, so we have to set related configuration here.
# 2. To ensure security, flake allows only a few nixConfig parameters to be set directly by default.
# you need to add `--accept-flake-config` when executing the nix command,
# otherwise all other parameters will be ignored, and an warning will printed by nix.
# ...
nixConfig = {
experimental-features = [ "nix-command" "flakes" ];
substituters = [
# replace official cache with a mirror located in China
# Replace the official cache with a mirror located in China
"https://mirrors.bfsu.edu.cn/nix-channels/store"
"https://cache.nixos.org/"
];
extra-substituters = [
# nix community's cache server
extra-sub
stituters = [
# Nix community's cache server
"https://nix-community.cachix.org"
];
extra-trusted-public-keys = [
@ -235,14 +239,13 @@ Therefore, to customize the cache source, we must add the related configuration
};
inputs = {
# omit some configuration...
# Omit some configurations...
};
outputs = {
# omit some configuration...
# Omit some configurations...
};
}
```
After the modification, run `sudo nixos-rebuild switch` to apply the updates.
After making the modifications, run `sudo nixos-rebuild switch` to apply the updates.

View File

@ -1,95 +1,99 @@
# Other useful Tips
# Other Useful Tips
## Manage the configuration with Git
## Managing the Configuration with Git
NixOS configuration is just a set of text files, it is very suitable to be managed with Git, and thus we can easily rollback to a previous version when we encounter some problems.
NixOS configuration, being a set of text files, is well-suited for version control with Git. This allows easy rollback to a previous version in case of issues.
However, NixOS places the configuration in `/etc/nixos` by default, which requires root permissions to modify, which is not convenient for daily use.
Luckily, Flakes can solve this problem, you can place your flake anywhere you like.
However, by default, NixOS places the configuration in `/etc/nixos`, which requires root permissions for modification, making it inconvenient for daily use. Thankfully, Flakes can help solve this problem by allowing you to place your flake anywhere you prefer.
For example, my usage is to place my flake in `~/nixos-config`, and then create a soft link in `/etc/nixos`:
For example, you can place your flake in `~/nixos-config` and create a symbolic link in `/etc/nixos` as follows:
```shell
sudo mv /etc/nixos /etc/nixos.bak # backup the original configuration
sudo mv /etc/nixos /etc/nixos.bak # Backup the original configuration
sudo ln -s ~/nixos-config/ /etc/nixos
# deploy the flake.nix located at the default location(/etc/nixos)
# Deploy the flake.nix located at the default location (/etc/nixos)
sudo nixos-rebuild switch
```
And then you can use Git to manage the configuration in `~/nixos-config`. The configuration can be used with ordinary user-level permissions, and it is not required to be owned by root.
This way, you can use Git to manage the configuration in `~/nixos-config`. The configuration can be modified with regular user-level permissions and does not require root ownership.
Another method is just to delete `/etc/nixos` directly, and specify the configuration file path each time you deploy it:
Another approach is to delete `/etc/nixos` directly and specify the configuration file path each time you deploy it:
```shell
sudo mv /etc/nixos /etc/nixos.bak
cd ~/nixos-config
# `--flake .#nixos-test` means deploy the flake.nix located in the current directory, and the nixosConfiguration's name is `nixos-test`
# `--flake .#nixos-test` deploys the flake.nix located in the current directory, and the nixosConfiguration's name is `nixos-test`
sudo nixos-rebuild switch --flake .#nixos-test
```
Choose whichever you like. After that, system rollback will become very simple, just switch to the previous commit and then deploy it:
Choose the method that suits you best. Afterward, system rollback becomes simple. Just switch to the previous commit and deploy it:
```shell
cd ~/nixos-config
# switch to the previous commit
# Switch to the previous commit
git checkout HEAD^1
# deploy the flake.nix located in the current directory, and the nixosConfiguration's name is `nixos-test`
# Deploy the flake.nix located in the current directory, with the nixosConfiguration's name `nixos-test`
sudo nixos-rebuild switch --flake .#nixos-test
```
More operations on Git are not described here. Generally speaking, rollback can be done directly through Git. Only when the system crashes completely, you will need to restart into bootloader and boot the system from the previous historical version.
More advanced Git operations are not covered here, but in general, rollback can be performed directly using Git. Only in cases of complete system crashes would you need to restart into the bootloader and boot the system from a previous historical version.
## View and delete history data {#view-and-delete-history}
## Viewing and Deleting Historical Data
As we mentioned before, each deployment of NixOS will generate a new version, and all versions will be added to the system boot options. In addition to restarting the computer, we can also query all available historical versions through the following command:
As mentioned earlier, each NixOS deployment creates a new version, and all versions are added to the system's boot options. In addition to restarting the computer, you can query all available historical versions using the following command:
```shell
nix profile history --profile /nix/var/nix/profiles/system
```
The command to clean up historical versions to release storage space:
To clean up historical versions and free up storage space, use the following command:
```shell
# delete all historical versions older than 7 days
sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 7d
# Delete all historical versions older than 7 days
sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 7d
# we need to collect garbages after wipe-history
# Run garbage collection after wiping history
sudo nix store gc --debug
```
Another command returns all packages installed in the system:
Another command that returns all packages installed in the system is:
```shell
nix-env -qa
```
## Reduce Disk Usage
## Reducing Disk Usage
The following configuration can be used to reduce disk usage, feel free to add it into your NixOS Configuration.
The following configuration can be added to your NixOS configuration to help reduce disk usage:
```nix
{ lib, pkgs, ... }:
{
# ......
# ...
# do not need to keep too much generations
# Limit the number of generations to keep
boot.loader.systemd-boot.configurationLimit = 10;
# boot.loader.grub.configurationLimit = 10;
# do garbage collection weekly to keep disk usage low
# Perform garbage collection weekly to maintain low disk usage
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 1w";
};
# Optimise storage
# you can alse optimise the store manually via:
};
# Optimize storage
# You can also manually optimize the store via:
# nix-store --optimise
# Refer to the following link for more details:
# https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-auto-optimise-store
nix.settings.auto-optimise-store = true;
}
```
By incorporating this configuration, you can better manage and optimize the disk usage of your NixOS system.

View File

@ -1,13 +1,13 @@
# Updating the System
With Flakes, updating the system is simple. Just run the following commands in `/etc/nixos`(
or any other place where you keep the configuration.):
With Flakes, updating the system is straightforward. Simply execute the following commands in `/etc/nixos` or any other location where you keep the configuration:
```shell
# Update flake.lock
nix flake update
# Apply the updates
sudo nixos-rebuild switch --flake .
```
Sometimes, you may encounter a sha256 mismatch error when running `nixos-rebuild switch`. This can be resolved by updating `flake.lock` through `nix flake update`.
Occasionally, you may encounter a "sha256 mismatch" error when running `nixos-rebuild switch`. This error can be resolved by updating `flake.lock` using `nix flake update`.

View File

@ -1,21 +1,24 @@
# pkgs.callPackage
# `pkgs.callPackage`
In the previous section, we used `import xxx.nix` to import Nix files multiple times. This syntax simply returns the execution result of the file without any further processing.
In the previous section, we used the `import xxx.nix` syntax to import Nix files. This syntax simply returns the execution result of the file without any further processing.
`pkgs.callPackage` is also used to import Nix files. Its syntax is `pkgs.callPackage xxx.nix { ... }`. However, unlike `import`, the Nix file imported by it must be a Derivation or a function that returns a Derivation. Its result is also a Derivation (a software package).
Another method to import Nix files is `pkgs.callPackage`. Its syntax is `pkgs.callPackage xxx.nix { ... }`. However, unlike `import`, the Nix file imported by `pkgs.callPackage` must be a Derivation or a function that returns a Derivation. The result of `pkgs.callPackage` is also a Derivation, which represents a software package.
So, what does the Nix file that can be used as a parameter of `pkgs.callPackge` look like? You can take a look at the `hello.nix`, `fcitx5-rime.nix`, `vscode/with-extensions.nix`, and `firefox/common.nix` files we mentioned earlier. They can all be imported by `pkgs.callPackage`.
So, what does a Nix file that can be used as a parameter for `pkgs.callPackage` look like? You can refer to the `hello.nix`, `fcitx5-rime.nix`, `vscode/with-extensions.nix`, and `firefox/common.nix` files mentioned earlier. All of these files can be imported using `pkgs.callPackage`.
When the `xxx.nix` used in `pkgs.callPackge xxx.nix {...}` is a function (most Nix packages are like this), the execution flow is as follows:
When the `xxx.nix` file used in `pkgs.callPackage xxx.nix {...}` is a function (most Nix packages follow this pattern), the execution flow is as follows:
1. `pkgs.callPackge xxx.nix {...}` first imports `xxx.nix` to get the function defined in it. The parameters of this function usually have `lib`, `stdenv`, `fetchurl`, and other parameters, as well as some custom parameters that usually have default values.
2. Then, `pkgs.callPackge` looks up the value matching the name from the current environment as the parameter to be passed to the function. Parameters like `lib`, `stdenv`, and `fetchurl` are defined in nixpkgs and will be found in this step.
3. Next, `pkgs.callPackge` merges its second parameter `{...}` with the attribute set obtained in the previous step and passes it to the function imported from `xxx.nix` to execute it.
4. Finally, we get a Derivation as the result of the function execution.
1. `pkgs.callPackage xxx.nix {...}` first imports `xxx.nix` to obtain the function defined within it. This function usually has parameters like `lib`, `stdenv`, `fetchurl`, and sometimes additional custom parameters with default values.
The common usage of `pkgs.callPackage` is to import customized Nix packages and use them in Nix Modules.
2. Then, `pkgs.callPackage` searches for a value matching the parameter names from the current environment. Parameters like `lib`, `stdenv`, and `fetchurl` are defined in nixpkgs and will be found in this step.
For example, suppose we have customized a NixOS kernel configuration `kernel.nix`, which uses the SBC's name and kernel source as its variable parameters:
3. Next, `pkgs.callPackage` merges its second parameter, `{...}`, with the attribute set obtained in the previous step. It then passes this merged set as the parameter to the function imported from `xxx.nix` for execution.
4. Finally, the result of the function execution is a Derivation.
The common use case for `pkgs.callPackage` is to import customized Nix packages and use them in Nix Modules.
For example, let's say we have a customized NixOS kernel configuration file named `kernel.nix`, which uses the SBC's name and kernel source as its variable parameters:
```nix
{
@ -33,16 +36,16 @@ For example, suppose we have customized a NixOS kernel configuration `kernel.nix
inherit src lib stdenv;
# file path to the generated kernel config file(the `.config` generated by make menuconfig)
# File path to the generated kernel config file (`.config` generated by make menuconfig)
#
# here is a special usage to generate a file path from a string
# Here, we use a special usage to generate a file path from a string.
configfile = ./. + "${boardName}_config";
allowImportFromDerivation = true;
})
```
Then we can use `pkgs.callPackage ./kernel.nix {}` in any Nix Module to import and replace any of its parameters:
We can use `pkgs.callPackage ./kernel.nix {}` in any Nix Module to import and replace any of its parameters:
```nix
{ lib, pkgs, pkgsKernel, kernel-src, ... }:
@ -53,16 +56,16 @@ Then we can use `pkgs.callPackage ./kernel.nix {}` in any Nix Module to import a
boot = {
# ......
kernelPackages = pkgs.linuxPackagesFor (pkgs.callPackage ./pkgs/kernel {
src = kernel-src; # kernel source is passed as a `specialArgs` and injected into this module.
boardName = "licheepi4a"; # the board name, used to generate the kernel config file path.
src = kernel-src; # The kernel source is passed as a `specialArgs` and injected into this module.
boardName = "licheepi4a"; # The board name, used to generate the kernel config file path.
});
# ......
}
```
Similarly to the example above, we can use `pkgs.callPackage` to pass different `src` and `boardName` parameters to the function defined in `kernel.nix`. This allows us to generate different kernel packages. By changing the parameters passed to it, `kernel.nix` can be used to adapt to different kernel sources and development boards.
In the example above, we use `pkgs.callPackage` to pass different `src` and `boardName` parameters to the function defined in `kernel.nix`. This allows us to generate different kernel packages. By changing the parameters passed to `pkgs.callPackage`, `kernel.nix` can adapt to different kernel sources and development boards.
## References
- [Chapter 13. Callpackage Design Pattern - Nix Pills](https://nixos.org/guides/nix-pills/callpackage-design-pattern.html)
- [Chapter 13. Callpackage Design Pattern - Nix Pills](https://nixos.org/guides/nix-pills/callpackage-design-pattern.html)

View File

@ -1,164 +1,163 @@
# Overlays
The `override` we introduced earlier generates a new Derivation that does not affect the original Derivation in `pkgs`. It's only suitable for use as a local parameter. If you need to override a Derivation that is also dependent on other Nix packages, then other Nix packages will still use the original Derivation.
In the previous section, we learned about overriding derivations using the `override` keyword. However, this approach only affects the local derivation and doesn't modify the original derivation in `pkgs`. To globally modify derivations in `pkgs`, Nix provides a feature called "overlays".
To solve this problem, Nix provides the ability to use `overlays`. Simply put, `overlays` can globally modify the Derivations in `pkgs`.
In traditional Nix environments, overlays can be configured globally using the `~/.config/nixpkgs/overlays.nix` or `~/.config/nixpkgs/overlays/*.nix` files. However, in Flakes, to ensure system reproducibility, overlays cannot rely on configurations outside of the Git repository.
In the classic Nix environment, Nix automatically applies all `overlays` configurations under the paths `~/.config/nixpkgs/overlays.nix` and `~/.config/nixpkgs/overlays/*.nix`. However, in Flakes, to ensure the reproducibility of the system, it cannot depend on any configuration outside the Git repository. Therefore, this classic method cannot be used now.
When using Flakes to configure NixOS, both Home Manager and NixOS provide the `nixpkgs.overlays` option to define overlays. You can refer to the following documentation for more details:
When using Flakes to write configuration for NixOS, both home Manager and NixOS provide the `nixpkgs.overlays` option to define `overlays`. For more information, refer to the following documentation:
- [Home Manager docs - `nixpkgs.overlays`](https://nix-community.github.io/home-manager/options.html#opt-nixpkgs.overlays)
- [Nixpkgs source code - `nixpkgs.overlays`](https://github.com/NixOS/nixpkgs/blob/30d7dd7e7f2cba9c105a6906ae2c9ed419e02f17/nixos/modules/misc/nixpkgs.nix#L169)
- [home-manager docs - `nixpkgs.overlays`](https://nix-community.github.io/home-manager/options.html#opt-nixpkgs.overlays)
- [nixpkgs source code - `nixpkgs.overlays`](https://github.com/NixOS/nixpkgs/blob/30d7dd7e7f2cba9c105a6906ae2c9ed419e02f17/nixos/modules/misc/nixpkgs.nix#L169)
For example, the following content is a Module that loads overlays, which can be used as either a home Manager Module or a NixOS Module because the two definitions are exactly the same:
> Home Manager is an external component, and most people use the unstable branch of Home Manager and nixpkgs, which sometimes causes problems with Home Manager Module. Therefore, it's recommended to import `overlays` in a NixOS Module.
Let's take a look at an example module that loads overlays. This module can be used as a Home Manager module or a NixOS module, as the definitions are the same:
```nix
{ config, pkgs, lib, ... }:
{
nixpkgs.overlays = [
# overlayer1 - use self and super to express the inheritance relationship
# Overlay 1: Use `self` and `super` to express the inheritance relationship
(self: super: {
google-chrome = super.google-chrome.override {
commandLineArgs =
"--proxy-server='https=127.0.0.1:3128;http=127.0.0.1:3128'";
};
google-chrome = super.google-chrome.override {
commandLineArgs =
"--proxy-server='https=127.0.0.1:3128;http=127.0.0.1:3128'";
};
})
# overlayer2 - you can also use `extend` to inherit other overlays
# use `final` and `prev` to express the relationship between the new and the old
# Overlay 2: Use `final` and `prev` to express the relationship between the new and the old
(final: prev: {
steam = prev.steam.override {
extraPkgs = pkgs:
with pkgs; [
keyutils
libkrb5
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
];
extraPkgs = pkgs: with pkgs; [
keyutils
libkrb5
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
];
extraProfile = "export GDK_SCALE=2";
};
})
# overlay3 - define overlays in other files
# here the content of overlay3.nix is the same as above:
# `final: prev: { xxx = prev.xxx.override { ... }; }`
# Overlay 3: Define overlays in other files
# The content of overlay3.nix is the same as above:
# `(final: prev: { xxx = prev.xxx.override { ... }; })`
(import ./overlays/overlay3.nix)
];
}
```
refer to this example to write your own overlays, import the configuration as a NixOS Module or a home Manager Module, and then deploy it to see the effect.
In the above example, we define three overlays. Overlay 1 modifies the `google-chrome` derivation by adding a command-line argument for a proxy server. Overlay 2 modifies the `steam` derivation by adding extra packages and an environment variable. Overlay 3 is defined in a separate file `overlay3.nix`.
You can write your own overlays following this example. Import the configuration as a NixOS module or a Home Manager module, and then deploy it to see the effect.
## Modular overlays
The previous example shows how to write overlays, but all overlays are written in a single nix file, which is a bit difficult to maintain.
In the previous example, all overlays were written in a single Nix file, which can become difficult to maintain over time. To address this, we can manage overlays in a modular way.
To resolve this problem, here is a best practice of how to manage overlays in a modular way.
Start by creating an `overlays` folder in your
First, create an `overlays` folder in the Git repository to store all overlays configurations, and then create `overlays/default.nix`, whose content is as follows:
Git repository to store all overlay configurations. Inside this folder, create a `default.nix` file with the following content:
```nix
# import all nix files in the current folder, and execute them with args as parameters
# The return value is a list of all execution results, which is the list of overlays
args:
# import all nix files in the current folder, and execute them with args as parameters
# The return value is a list of all execution results, which is the list of overlays
builtins.map
(f: (import (./. + "/${f}") args)) # the first parameter of map, a function that import and execute a nix file
(builtins.filter # the second parameter of map, a list of all nix files in the current folder except default.nix
# execute and import all overlay files in the current directory with the given args
builtins.map
(f: (import (./. + "/${f}") args)) # execute and import the overlay file
(builtins.filter # find all overlay files in the current directory
(f: f != "default.nix")
(builtins.attrNames (builtins.readDir ./.)))
```
Then you can write all overlays configurations in the `overlays` folder, an example configuration `overlays/fcitx5/default.nix` is as follows:
The `default.nix` file imports and executes all Nix files in the current folder (excluding `default.nix`) with the provided arguments. It returns a list of all overlay results.
Next, write your overlay configurations in the `overlays` folder. For example, you can create `overlays/fcitx5/default.nix` with the following content:
```nix
# to add my custom input method, I override the default rime-data here
# refer to https://github.com/NixOS/nixpkgs/blob/e4246ae1e7f78b7087dce9c9da10d28d3725025f/pkgs/tools/inputmethods/fcitx5/fcitx5-rime.nix
{pkgs, config, lib, ...}:
{ pkgs, config, lib, ... }:
(self: super: {
# my custom input method's rime-data, downloaded from https://flypy.com
rime-data = ./rime-data-flypy;
rime-data = ./rime-data-flypy; # Customized rime-data package
fcitx5-rime = super.fcitx5-rime.override { rimeDataPkgs = [ ./rime-data-flypy ]; };
})
```
We customized the `rime-data` package through the overlay shown above.
In the above example, we override the `rime-data` package with a custom version and modify the `fcitx5-rime` derivation to use the custom `rime-data` package.
At last, you need to load all overlays returned by `overlays/default.nix` through the `nixpkgs.overlays` option, add the following parameter to any NixOS Module to achieve this:
To load all overlays returned by `overlays/default.nix`, add the following parameter to any NixOS module:
```nix
{ config, pkgs, lib, ... } @ args:
{
# ......
# ...
# add this parameter
nixpkgs.overlays = import /path/to/overlays/dir;
# ......
# ...
}
```
For example, you can just add it directly in `flake.nix`:
For instance, you can add it directly in `flake.nix`:
```nix
{
description = "NixOS configuration of Ryan Yin";
# ......
# ...
inputs = {
# ......
# ...
};
outputs = inputs@{ self, nixpkgs, ... }: {
nixosConfigurations = {
nixos-test = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = inputs;
modules = [
./hosts/nixos-test
outputs = inputs@{ self, nixpkgs, ... }:
{
nixosConfigurations = {
nixos-test = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = inputs;
modules = [
./hosts/nixos-test
# add the following inline module definition
# here, all parameters of modules are passed to overlays
(args: { nixpkgs.overlays = import ./overlays args; })
# add the following inline module definition
# here, all parameters of modules are passed to overlays
(args: { nixpkgs.overlays = import ./overlays args; })
# ......
];
# ...
];
};
};
};
};
}
```
By using this modular approach, it is very convenient to modularize all your overlays. Taking my configuration as an example, the structure of the `overlays` folder is rough as follows:
By using this modular approach, you can conveniently organize and manage your overlays. In this example, the structure of the `overlays` folder would look like this:
```nix
```txt
.
├── flake.lock
├── flake.nix
├── home
├── hosts
├── modules
├── ......
├── ...
├── overlays
│ ├── default.nix # it returns a list of all overlays.
│ └── fcitx5 # fcitx5 overlay
│ ├── default.nix # return a list of all overlays.
│ └── fcitx5 # fcitx5 overlay
│ ├── default.nix
│ ├── README.md
│ └── rime-data-flypy # my custom rime-data
│ └── rime-data-flypy # my custom rime-data
│ └── share
│ └── rime-data
│ ├── ...... # rime-data files
│ ├── ...
└── README.md
```
This modular approach simplifies the management of overlays and allows you to easily add, modify, or remove overlays as needed.

View File

@ -1,46 +1,21 @@
# Overriding
Simply put, all Nix packages in nixpkgs can be customized with `<pkg>.override {}` to define some build parameters, which returns a new Derivation that uses custom parameters. For example:
In Nix, you can customize Nix packages in `pkgs` by using the `override` function, which allows you to define custom build parameters and returns a new derivation with the overridden values. Let's take a look at an example:
```nix
pkgs.fcitx5-rime.override {rimeDataPkgs = [
./rime-data-flypy
];}
pkgs.fcitx5-rime.override { rimeDataPkgs = [ ./rime-data-flypy ]; }
```
The result of this Nix expression is a new Derivation, where `rimeDataPkgs` is overridden as `[./rime-data-flypy]`, while other parameters remain at their original values.
In the above example, we override the `rimeDataPkgs` parameter of the `fcitx5-rime` derivation to use a custom package called `rime-data-flypy`. This creates a new derivation where `rimeDataPkgs` is overridden, while other parameters remain unchanged.
How to know which parameters of `fcitx5-rime` can be overridden? There are several ways:
To find out which parameters of a specific package can be overridden, there are a couple of approaches you can follow:
1. Try to find the source code of the package in the nixpkgs repository on GitHub, such as [fcitx5-rime.nix](https://github.com/NixOS/nixpkgs/blob/e4246ae1e7f78b7087dce9c9da10d28d3725025f/pkgs/tools/inputmethods/fcitx5/fcitx5-rime.nix)
1. Note: Be sure to select the correct branch, for example, if you are using the nixos-unstable branch, you need to find it in the nixos-unstable branch.
2. Check by using `nix repl '<nixpkgs>'`, then enter `:e pkgs.fcitx5-rime`, which will open the source code of this package through the default editor, and then you can see all the parameters of this package.
1. Note: To learn the basic usage of `nix repl`, just type `:?` to see the help information
1. Check the source code of the package in the Nixpkgs repository on GitHub, such as [`fcitx5-rime.nix`](https://github.com/NixOS/nixpkgs/blob/e4246ae1e7f78b7087dce9c9da10d28d3725025f/pkgs/tools/inputmethods/fcitx5/fcitx5-rime.nix). Make sure to select the appropriate branch, such as `nixos-unstable`, if you are using that branch.
2. Use the `nix repl '<nixpkgs>'` command to open a Nix REPL and then enter `:e pkgs.fcitx5-rime`. This opens the source code of the package in your default editor, where you can see all the parameters of the package. To learn the basic usage of `nix repl`, you can type `:?` to see the help information.
Through these two methods, you can see that the `fcitx5-rime` package has the following input parameters, which can all be modified by `override`:
By using these methods, you can discover the input parameters of a package and determine which ones can be modified using `override`.
```nix
{ lib, stdenv
, fetchFromGitHub
, pkg-config
, cmake
, extra-cmake-modules
, gettext
, fcitx5
, librime
, rime-data
, symlinkJoin
, rimeDataPkgs ? [ rime-data ]
}:
stdenv.mkDerivation rec {
...
}
```
Instead of overriding the function's parameters, we can also override the attributes of the Derivation created by `stdenv.mkDerivation`.
Take `pkgs.hello` as an example, first check the source code of this package through the method we mentioned earlier:
For example, let's take a look at the source code of `pkgs.hello`:
```nix
# https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/applications/misc/hello/default.nix
@ -64,11 +39,11 @@ stdenv.mkDerivation (finalAttrs: {
doCheck = true;
# ......
# ...
})
```
The attributes showed above, such as `pname` `version` `src` `doCheck`, can all be overridden by `overrideAttrs`, for example:
In this example, the attributes `pname`, `version`, `src`, and `doCheck` can all be overridden using `overrideAttrs`. For instance:
```nix
helloWithDebug = pkgs.hello.overrideAttrs (finalAttrs: previousAttrs: {
@ -76,9 +51,9 @@ helloWithDebug = pkgs.hello.overrideAttrs (finalAttrs: previousAttrs: {
});
```
Here we use `overrideAttrs` to override `doCheck`, while other attributes remain their original values.
In the above code, we use `overrideAttrs` to override the `doCheck` attribute, while leaving other attributes unchanged.
Some default attributes defined in `stdenv.mkDerivation` can also be overridden by `overrideAttrs`, for example:
You can also override some default attributes defined in `stdenv.mkDerivation` using `overrideAttrs`. For example:
```nix
helloWithDebug = pkgs.hello.overrideAttrs (finalAttrs: previousAttrs: {
@ -86,5 +61,8 @@ helloWithDebug = pkgs.hello.overrideAttrs (finalAttrs: previousAttrs: {
});
```
The attribute we override here, `separateDebugInfo`, is defined in `stdenv.mkDerivation`, not in the source code of `hello`.
We can check the source code of `stdenv.mkDerivation` to see all the attributes defined in it by using `nix repl '<nixpkgs>'` and then enter `:e stdenv.mkDerivation`(To learn the basic usage of `nix repl`, just type `:?` to see the help information).
In this case, we override the `separateDebugInfo` attribute, which is defined in `stdenv.mkDerivation`, rather than in the source code of `hello`.
To see all the attributes defined in `stdenv.mkDerivation`, you can check its source code by using `nix repl '<nixpkgs>'` and entering `:e stdenv.mkDerivation`.
This will open the source code in your default editor. If you're new to using `nix repl`, you can type `:?` to see the help information.

View File

@ -1,3 +1,3 @@
# Other Usage of Flakes
Up to now, we have written a lot of configurations with Flakes to manage NixOS. Here is a brief introduction to the more detailed content of the Flakes, as well as the new command lines commonly used with flakes.
So far, we have extensively used Flakes to manage NixOS configurations. In this section, I will provide a brief introduction to additional features and command-line options commonly used with Flakes.

View File

@ -1,64 +1,67 @@
# Flake outputs
# Flake Outputs
the `outputs` in `flake.nix` are what a flake produces as part of its build. Each flake can have many different outputs simultaneously, including but not limited to:
In `flake.nix`, the `outputs` section defines the different outputs that a flake can produce during its build process. A flake can have multiple outputs simultaneously, which can include but are not limited to the following:
- Nix packages: named `apps.<system>.<name>`, `packages.<system>.<name>`, or `legacyPackages.<system>.<name>`
- we can build a package by command `nix build .#<name>`
- Nix Helper Functions: named `lib`., which means a library for other flakes.
- Nix development environments: named `devShells`
- `devShells` can be used by command `nix develop`, will be introduced later.
- NixOS configuration: named `nixosConfiguration`
- `nixosConfiguration` will be used by command `nixos-rebuild switch --flake .#<name>`
- Nix templates: named `templates`
- templates can be used by command `nix flake init --template <reference>`
- Other user defined outputs, may be parsed by other nix-related tools.
- Nix packages: These are named `apps.<system>.<name>`, `packages.<system>.<name>`, or `legacyPackages.<system>.<name>`. You can build a specific package using the command `nix build .#<name>`.
- Nix helper functions: These are named `lib.<name>` and serve as libraries for other flakes to use.
- Nix development environments: These are named `devShells` and provide isolated development environments. They can be accessed using the command `nix develop`.
- NixOS configurations: These are named `nixosConfiguration` and represent specific NixOS system configurations. You can activate a configuration using the command `nixos-rebuild switch --flake .#<name>`.
- Nix templates: These are named `templates` and can be used as a starting point for creating new projects. You can generate a project using the command `nix flake init --template <reference>`.
- Other user-defined outputs: These outputs can be defined by the user and may be used by other Nix-related tools.
An example copy from NixOS Wiki:
Here's an example excerpt from the NixOS Wiki that demonstrates the structure of the `outputs` section:
```nix
{ self, ... }@inputs:
{
# Executed by `nix flake check`
checks."<system>"."<name>" = derivation;
# Executed by `nix build .#<name>`
packages."<system>"."<name>" = derivation;
# Executed by `nix build .`
packages."<system>".default = derivation;
# Executed by `nix run .#<name>`
apps."<system>"."<name>" = {
type = "app";
program = "<store-path>";
inputs = {
# ......
};
# Executed by `nix run . -- <args?>`
apps."<system>".default = { type = "app"; program = "..."; };
# Formatter (alejandra, nixfmt or nixpkgs-fmt)
formatter."<system>" = derivation;
# Used for nixpkgs packages, also accessible via `nix build .#<name>`
legacyPackages."<system>"."<name>" = derivation;
# Overlay, consumed by other flakes
overlays."<name>" = final: prev: { };
# Default overlay
overlays.default = {};
# Nixos module, consumed by other flakes
nixosModules."<name>" = { config }: { options = {}; config = {}; };
# Default module
nixosModules.default = {};
# Used with `nixos-rebuild --flake .#<hostname>`
# nixosConfigurations."<hostname>".config.system.build.toplevel must be a derivation
nixosConfigurations."<hostname>" = {};
# Used by `nix develop .#<name>`
devShells."<system>"."<name>" = derivation;
# Used by `nix develop`
devShells."<system>".default = derivation;
# Hydra build jobs
hydraJobs."<attr>"."<system>" = derivation;
# Used by `nix flake init -t <flake>#<name>`
templates."<name>" = {
path = "<store-path>";
description = "template description goes here?";
outputs = { self, ... }@inputs: {
# Executed by `nix flake check`
checks."<system>"."<name>" = derivation;
# Executed by `nix build .#<name>`
packages."<system>"."<name>" = derivation;
# Executed by `nix build .`
packages."<system>".default = derivation;
# Executed by `nix run .#<name>`
apps."<system>"."<name>" = {
type = "app";
program = "<store-path>";
};
# Executed by `nix run . -- <args?>`
apps."<system>".default = { type = "app"; program = "..."; };
# Formatter (alejandra, nixfmt or nixpkgs-fmt)
formatter."<system>" = derivation;
# Used for nixpkgs packages, also accessible via `nix build .#<name>`
legacyPackages."<system>"."<name>" = derivation;
# Overlay, consumed by other flakes
overlays."<name>" = final: prev: { };
# Default overlay
overlays.default = {};
# Nixos module, consumed by other flakes
nixosModules."<name>" = { config }: { options = {}; config = {}; };
# Default module
nixosModules.default = {};
# Used with `nixos-rebuild --flake .#<hostname>`
# nixosConfigurations."<hostname>".config.system.build.toplevel must be a derivation
nixosConfigurations."<hostname>" = {};
# Used by `nix develop .#<name>`
devShells."<system>"."<name>" = derivation;
# Used by `nix develop`
devShells."<system>".default = derivation;
# Hydra build jobs
hydraJobs."<attr>"."<system>" = derivation;
# Used by `nix flake init -t <flake>#<name>`
templates."<name>" = {
path = "<store-path>";
description = "template description goes here?";
};
# Used by `nix flake init -t <flake>`
templates.default = { path = "<store-path>"; description = ""; };
};
# Used by `nix flake init -t <flake>`
templates.default = { path = "<store-path>"; description = ""; };
}
```

View File

@ -1,13 +1,12 @@
# Usage of The New CLI
# Usage of the New CLI
after enabling `nix-command` & `flake`, you can use `nix help` to get all the info of [New Nix Commands][New Nix Commands], some useful examples are listed below:
Once you have enabled `nix-command` and `flake`, you can use the `nix help` command to obtain information about the [New Nix Commands][New Nix Commands]. Here are some useful examples:
```bash
# `nixpkgs#ponysay` means `ponysay` from `nixpkgs` flake.
# [nixpkgs](https://github.com/NixOS/nixpkgs) contains `flake.nix` file, so it's a flake.
# `nixpkgs` is a falkeregistry id for `github:NixOS/nixpkgs/nixos-unstable`.
# you can find all the falkeregistry ids at <https://github.com/NixOS/flake-registry/blob/master/flake-registry.json>
# so this command means install and run package `ponysay` in `nixpkgs` flake.
# The following command installs and runs the `ponysay` package from the `nixpkgs` flake.
# The `nixpkgs` flake refers to the `nixpkgs` repository on GitHub, which contains a `flake.nix` file.
# `nixpkgs` is a flake registry ID for `github:NixOS/nixpkgs/nixos-unstable`.
# You can find all the flake registry IDs at <https://github.com/NixOS/flake-registry/blob/master/flake-registry.json>.
echo "Hello Nix" | nix run "nixpkgs#ponysay"
# this command is the same as above, but use a full flake URI instead of falkeregistry id.

View File

@ -1,7 +1,12 @@
# Basics of The Nix language
# Basics of the Nix Language
The Nix language is used to declare the configuration to be built by Nix, if you want to play with NixOS and Flakes and enjoy the benefits they bring, you must learn the basics of this language first.
The Nix language is essential for declaring configurations to be built by Nix. To fully enjoy the benefits of NixOS and Flakes, it is necessary to grasp the fundamentals of this language.
The Nix language is a simple functional language, if you already have some experience in programming, it should take less than 2 hours to go through its basics.
The Nix language is a straightforward functional language. If you have some programming experience, it should take you less than 2 hours to grasp its basics.
Please read [**Nix language basics - nix.dev**](https://nix.dev/tutorials/first-steps/nix-language) and [Chapter 4. The Basics of the Language - Nix Pills](https://nixos.org/guides/nix-pills/basics-of-language.html) to get a basic understanding of the Nix language now, they are all good introductory materials.
To get started, I recommend reading the following resources for a solid introduction to the Nix language:
1. [**Nix Language Basics - nix.dev**](https://nix.dev/tutorials/first-steps/nix-language): This tutorial provides a comprehensive overview of the basics of the Nix language.
2. [Chapter 4. The Basics of the Language - Nix Pills](https://nixos.org/guides/nix-pills/basics-of-language.html): This chapter in the Nix Pills guide offers detailed explanations and examples to help you understand the core concepts of the Nix language.
By going through these materials, you will develop a solid foundation in the Nix language, allowing you to effectively utilize NixOS and Flakes.