nixos-and-flakes-book/docs/faq/index.md

175 lines
8.3 KiB
Markdown

# Frequently Asked Questions
## What is the difference between NixOS rollback capability and btrfs/zfs system snapshot rollback?
The difference lies in the nature of the snapshots. System snapshots created with
btrfs/zfs does not contain the 'knowledge' of how to build this snapshot from scratch, it
is **uninterpretable**, and its content is strongly correlated with the current hardware
environment, making it difficult to reproduce on other machines.
On the other hand, NixOS configuration is a piece of "knowledge" that can build an
identical OS from scratch. It is **explainable** and can be automatically built with just
a few simple commands. The NixOS configuration serves as documentation of all the changes
made to your OS and is also used to automatically build the OS itself.
The NixOS configuration file is like the **source code** of a program. As long as the
source code is intact, it is easy to modify, review, or rebuild an identical program. In
contrast, system snapshots are like compiled binary programs derived from source code,
making it much more difficult to modify or review them. Moreover, snapshots are large in
size, making sharing or migrating them more costly compared to source code.
However, this doesn't mean that NixOS eliminates the need for system snapshots. As
mentioned in Chapter 1 of this book, NixOS can only guarantee reproducibility for
everything declared in the declarative configuration. Other aspects of the system that are
not covered by the declarative configuration, such as dynamic data in MySQL/PostgreSQL,
user-uploaded files, system logs, videos, music, and images in user home directories,
still require system snapshots or other means of backup.
## How does Nix compare to traditional system management tools like Ansible?
Nix is not only used for managing desktop environments but is also widely employed for
batch management of cloud servers. The official [NixOps](https://github.com/NixOS/nixops)
from the NixOS community and [colmena](https://github.com/zhaofengli/colmena) developed by
the community are tools specifically designed for this use case.
When compared to widely used traditional tools like Ansible, Nix has the following main
advantages:
1. One of the biggest problems with this Ansible is that each deployment is based on
incremental changes to the current state of the system. The current state of the
system, like the snapshots mentioned above, is not interpretable and is difficult to
reproduce. NixOS declares the target state of the system through its configuration
files, so that the deployment result is independent of the current state of the system,
and repeated deployments will not cause any problems.
2. Nix Flakes uses a version lock file `flake.lock` to lock the hash value, version
number, data source and other information of all dependencies, which greatly improves
the reproducibility of the system. Traditional tools like Ansible don't have this
feature, so they're not very reproducible.
1. This is why Docker is so popular - it provides, at a fraction of the cost, a
**reproducible system environment on a wide range of machines** that traditional Ops
tools like Ansible don't.
3. Nix provides a high degree of ease of system customization by shielding the underlying
implementation details with a layer of declarative abstraction so that users only need
to care about their core requirements. Tools like Ansible have much weaker
abstractions.
1. If you've ever used a declarative configuration tool like terraform/kubernetes, this
should be easy to understand. The more complex the requirements, the greater the
benefit of declarative configuration.
## What are the advantages of Nix compared to Docker container technology?
Nix and container technologies like Docker do have overlapping use cases, such as:
1. Many people use Nix to manage development and build environments, as discussed in this
book. On the other hand, technologies like
[Dev Containers](https://github.com/devcontainers/spec), which build development
environments based on containers, are also popular.
2. The DevOps/SRE field is currently dominated by container technologies based on
Dockerfiles. Commonly used distributions like Ubuntu/Debian are frequently used within
containers, and there are also mature options available for the host machine. In this
context, what significant advantages do switching to NixOS offer?
Regarding the first point of "managing the development and build environments," Nix
provides a development environment experience that closely resembles working directly on
the host machine. This offers several advantages over Dev Containers, as outlined below:
1. Nix does not use namespaces for filesystem and network isolation, allowing easy
interaction with the host machine's filesystem (including /dev for external devices)
and network environment within the Nix-created development environment. In contrast,
containers require various mappings to enable communication between the container and
the host machine's filesystem, which can sometimes lead to file permission issues.
2. Due to the absence of strong isolation, Nix development environments have no issues
supporting GUI applications. Running GUI programs within this environment is as
seamless as running them in the system environment.
In other words, Nix provides a development experience that is closest to the host machine,
with no strong isolation. Developers can use familiar development and debugging tools in
this environment, and their past development experience can be seamlessly migrated. On the
other hand, if Dev Containers are used, developers may encounter various issues related to
filesystem communication, network environment, user permissions, and the inability to use
GUI debugging tools due to strong isolation.
If we decide to use Nix to manage all development environments, then building Docker
containers based on Nix would provide the highest level of consistency. Additionally,
adopting a unified technological architecture for all environments significantly reduces
infrastructure maintenance costs. This answers the second point mentioned earlier: when
managing development environments with Nix as a prerequisite, using NixOS for container
base images and cloud servers offers distinct advantages.
## error: collision between `...` and `...`
This error occurs when you installed two packages that depend on the same library but with
different versions in the same profile(home module or nixos module).
For example, if you have the following configuration:
```nix
{
# as a nixos module
# environment.systemPackages = with pkgs; [
#
# or as a home manager module
home.packages = with pkgs; [
lldb
(python311.withPackages (ps:
with ps; [
ipython
pandas
requests
pyquery
pyyaml
]
))
];
}
```
this will cause the following error:
```bash
error: builder for '/nix/store/n3scj3s7v9jsb6y3v0fhndw35a9hdbs6-home-manager-path.drv' failed with exit code 25;
last 1 log lines:
> error: collision between `/nix/store/kvq0gvz6jwggarrcn9a8ramsfhyh1h9d-lldb-14.0.6/lib/python3.11/site-packages/six.py'
and `/nix/store/370s8inz4fc9k9lqk4qzj5vyr60q166w-python3-3.11.6-env/lib/python3.11/site-packages/six.py'
For full logs, run 'nix log /nix/store/n3scj3s7v9jsb6y3v0fhndw35a9hdbs6-home-manager-path.drv'.
```
Here are some solutions:
1. Split the two packages into two different **profiles**. For example, you can install
`lldb` via `environment.systemPackages` and `python311` via `home.packages`.
2. Different versions of Python3 are treated as different packages, so you can change your
custom Python3 version to `python310` to avoid the conflict.
3. Use `override` to override the version of the library used by the package to be
consistent with the version used by the other package.
```nix
{
# as a nixos module
# environment.systemPackages = with pkgs; [
#
# or as a home manager module
home.packages = let
custom-python3 = (pkgs.python311.withPackages (ps:
with ps; [
ipython
pandas
requests
pyquery
pyyaml
]
));
in
with pkgs; [
# override the version of python3
# NOTE: This will trigger a rebuild of lldb, it takes time
(lldb.override {
python3 = custom-python3;
})
custom-python3
];
}
```