Operating systems (OS) is an extensive topic. For decades, one approach has dominated here: Unix. Indeed, most modern systems, including most GNU / Linux distributions, * BSD and macOS, adhere to the Unix architecture. (Windows is not, but there is almost nothing interesting on this topic).
In 2000, Rob Pike made a presentation on why
system software research is not relevant . Due to pessimism or neglect of the community, he seems to have completely ignored the complaints collected by many Unix-users in
The Unix-Haters Handbook (1994). The book is intentionally sarcastic, but it points to some critical problems of Unix systems — and they have not been solved yet.
In 2006, Elko Dositra published his thesis
“A fully functional model of software deployment,” which describes the functional package manager Nix. In 2008, the author published
NixOS: a fully functional distribution of Linux . While NixOS reuses a lot of free software for Unix systems, it is so far away from the design and philosophy of Unix that it can hardly be called a "Unix system."
Nix - a giant step forward in system development. This OS not only solved many Unix problems (including criticism from the aforementioned collection), but also opened the way for many other functions and research that can play a very important role in our time, when reliability and security have become the main theme of many scientific, public and political debates.
Pike was wrong. And this proves another more general point: it is probably wiser to refrain from declaring the irrelevance of any research if you cannot prove the impossibility of further development. And the mentioned report can hardly be considered a mathematical proof. He only reinforced the idea that Unix is “good enough” and that one should come to terms with its features and problems.
Fortunately, this unnecessary pessimism was short-sighted and did not survive for long: just a couple of years later, the Nix system proved him wrong.
Guix appearance
Guix is the package manager on Nix, and GuixSD is the operating system, the equivalent of NixOS, which aims to be a “fully programmable OS.” Indeed, almost everything here is written and configured in
Guile Scheme : from Guix package management to the
GNU shepherd initialization system.
Guix is significantly different from Unix operating systems. You can view the documentation and assess the degree of change:
Guix Benefits
The advantages of Guix are revolutionary to such an extent that the rest of the operating systems look outdated compared to it.
My personal favorite features:
- System Invulnerability: Guix keeps a history of all changes at both the system and user levels. If the update breaks something, you can always roll back. This makes the system virtually invulnerable .
- Integrity: since the configuration is declarative, it gives the user or system administrator complete control. On other versions, Unix is much more difficult to tell when a random configuration file changes.
- Fully programmable OS: program system configurations and use version control system. Many system services can be configured in Guile Scheme: from udev rules to Xorg, PAM, etc. Thanks to Guile, the configuration can be driven by hardware or even by the host name!
- Direct replacement to other (not so good) package managers: why manage Emacs, Python or TeXlive packages separately, if there is a single interface for everyone (see below )! It's easier to write and maintain declarations for user profiles.
- Package definitions with Guile: It’s much more efficient to develop package definitions in bulk . It favorably replaces concepts such as the Portage USE flags (see below ).
- Several ways of issuing packages: A Guix package may have several “ways of issuing”, which serve to separate various components (libraries, additional tools, documentation, etc.). On other operating systems (usually Debian), it is more difficult to guess which packages are suitable for each other.
- Non-propagated inputs: In Guix terminology, “inputs” are package dependencies. The user profile and environment contain only explicitly installed user packages and not necessarily their dependencies. For example, see inxi - a system information reporting tool: if I’m only interested in inxi system / hardware reports, it’s not necessary to add two or three dozen additional command line tools to the
PATH
. Guix allows you to display only what you really need in your user profile.
- Guix Environments: When you run
guix environment SOME-PACKAGES
Guix sets up a temporary environment where all the requirements for SOME-PACKAGES
. This can be used to easily set up the build environment for a project, as well as for other purposes (see below). One remarkable quality - they allow you to run programs without setting them in the user profile.
- Partial updates: 100% supported. This is probably the main reason for breakdowns in floating releases like Arch Linux and Gentoo: since there are only a few versions supported at the same time (usually only one), the whole system should be updated as a whole. This means more traffic with each update. With Guix, any package is updated separately.
- Continuous integration or why Guix can work without package maintainers: thanks to reproducible builds and support for partial updates, if a package works in Guix, it will work “always” and will not break with the next update of some dependency (more precisely, if the dependency breaks the package, then it is trivially corrected to use the correct version of the library). Thus, work with packages can be transferred to “assembly farms” (one to Hydra from the Nix project, the other to Cuirass ). Compare this with most other GNU / Linux communities, which require dozens of maintainers to update thousands of packages. This approach does not scale: as a result, these distributions stagnate on a couple of thousand packages. In Guix, the number of packages can easily grow without fear of collapse. At the same time, contributors can be used more efficiently.
Guix is just as easy to build from source. In fact, this is not so important for the end user: Guix can easily go back to building from source if the complete package is not available.
guix import
and guix refresh
: automatic and recursive creation or updating of package definitions. Hundreds of definitions are processed simultaneously. Such functions emphasize the advantages of a real programming language in the OS. What is a difficult task in most operating systems is relatively easy to implement in Guix.
- Guix channels: one of my favorite features! In Arch Linux or Gentoo, you need to create a local repository. Since they do not support partial updates, the user must do some maintenance from time to time (i.e., make sure that dependency updates do not break packages). Guix feeds take advantage of AUR from Arch Linux and Gentoo overlays, allowing anyone to distribute their package definitions, for example, from Git repositories. Again, this guarantees full transparency (kickbacks, history, etc.).
- Emacs-Guix : as far as I know, Guix is the only distribution that comes with the most powerful Emacs user interface!
- Guix packs : a real alternative to containers like Docker. Most container systems suffer from critical issues: they are not reproducible and in reality are opaque binaries, which is totally unacceptable for users who care about trust, security and privacy. In contrast, Guix packs are absolutely clear, reproducible and transparent.
guix system vm
and guix system disk-image
: Guix makes it trivial to play the entire current system as a live USB, inside a VM or on a remote machine.
Guix compared to competitors
Debian, Arch Linux, and most other GNU / Linux distributions
GNU / Linux distributions usually lack the above-mentioned Guix benefits. The most critical shortcomings:
- Lack of support for multiple package versions or “dependency hell”. Let's say the last mpv requires a new ffmpeg, but updating ffmpeg breaks most other programs. We are stuck in a dilemma: either we break some packages, or we keep old versions. Worse, it may not be the right package at all or there is no OS support. This problem is inherent in most distributions that cannot guarantee the performance of their main task: a package for any program.
- Critical dependence on maintainers. Non-functional package management means that all packages need to be constantly tested for compatibility. This is a lot of hard work for those who have shouldered this task. In practice, this means that the quality of package management is highly dependent on people. A distribution without sufficient number of maintainers will inevitably suffer and possibly die. This labor requirement does not normally scale and as the number of packages increases, it leads to an increase in complexity (both in the code base and in management).
Gentoo, * BSD
Gentoo and other distributions with
Portage's package manager have a famous feature:
USE flags to activate features throughout the system (for example, mute, enable GUI support, etc.).
USE flags make it trivial to enable and disable features from the package author (and the advantage is that they are tested). Portage, on the other hand, does not allow functions that are not thought out in advance. For example, if the package has an additional sound, but the author has not set the corresponding flag, the user will not be able to do anything about it (except for creating a new package definition).
By comparison, Guix allows full customization of everything, albeit with a little more Scheme code. In pseudocode, it looks like this:
(loop-over (TARGET-PACKAGES) (package (inherit TARGET) (changes-here... including patches, build options, etc.))
This code batch sets the definitions for
TARGET-PACKAGES
with your changes. None of the changes need to be made to the package definition. At any time, the user retains full control over the changes that can be made to the packages.
I loved Gentoo, but after switching to Guix, the limitations of Portage became apparent.
- The USE flags system does not allow customizing unplanned arbitrary functions.
- The use of flags adds a whole class of complexity (see the rather complex semantics of atom ) to describe and manage the relationship of functions between packages. Guix completely removes this level of complexity using Guile Scheme to program relationships.
In addition, Portage suffers from the same problem with the lack of proper support for multiple versions, and the flags significantly increase the scale of the problem (a frequent complaint about Portage): when incompatible USE flags are applied to some dependencies, the user has to manually search for a solution. Sometimes this means that the required function is not applicable (at least without substantial work on package definitions).
In practice, Guix provides precompiled packages - a huge time saving compared to Gentoo (although Portage supports the distribution of binary packages).
* BSD systems (for example, FreeBSD) suffer from similar problems in
make config
.
Nix
Nix was a historic breakthrough in operating system research, and Guix borrowed almost all of its ideas from there. Today, Nix is still one of the best active OSes. Probably, Guix would not exist if it were not for one drawback.
In my opinion, Guix solves the basic problem of Nix: instead of its own
domain-specific language (DSL), the full-fledged Lisp
-based programming language is used here.
“Implementing your own programming language” is a very common misconception in software development. This hit hard on many projects where the configuration or programming language suffered from the following flaws:
- limited expressiveness and possibilities;
- another language to learn (but not something very useful and universal) that requires some effort from the user and thus creates an entry barrier;
- less readable code (at least at first);
- often poor performance.
There are a huge number of projects in homegrown or too limited languages:
- XML, HTML (even better: S-XML )
- Make, Autoconf, Automake, Cmake, etc.
- Bash, Zsh, Fish (even better: Eshell or scsh )
- JSON, TOML, YAML
- Ebuilds from Portage to Nix and many other syntax rules for defining OS packages
- Firefox when using XUL (since Mozilla refused it) and most other homegrown languages for extensions
- SQL
- Octave, R, PARI / GP, most scientific programs (for example, Common Lisp, Racket, and other Scheme)
- Regular expressions ( rx in Emacs , PEG in Racket , etc.)
- sed, awk and others
- Most configurations for init, including systemd (even better: GNU Shepherd )
- cron (even better: mcron )
- conky (not fully programmable, although it should be the most expected feature of a similar program)
- TeX, LaTeX (and all derivatives), Asymptote (even better: scribble , skribilo - still in development; as of January 2019, TeX / LaTeX is still used as an intermediate step in preparing the PDF)
- Most programs with configurations that do not use a general-purpose programming language.
Reinventing a wheel is usually not a good idea. When it comes to such important tools as programming languages, this has very dramatic consequences. Requires unnecessary extra effort, errors occur. The community is dissipating. More consolidated communities are more efficient and use their time better if they improve existing, well-developed programming languages.
Not just for the desktop
Guix supports several architectures (i686, x86_64, ARMv7, and AArch64 as of January 2019), and plans to support more kernels outside the Linux ecosystem (say, * BSD,
GNU Hurd, or maybe your own system!).
This makes Guix a great tool for deploying (reproducible) servers and other specialized systems. I think that in embedded systems Guix can compete very well with
OpenWRT (although it will take some work on porting to embedded systems).
Self-reproducible live USB
Above, I mentioned the
guix system disk-image
: for example, it allows you to recreate the current system on a USB flash drive.
Thus, a clone of the current system is easy to connect anywhere and replicate the exact current environment (minus the hardware). There you can include user data: PGP keys, email. Everything is available immediately after the download.
Obviously, the cloning works further with the machine on which the clone is installed: instead of the “naked” Guix, a full-fledged OS is deployed, ready for work.
Replacing other package managers
Emacs, Python, Ruby ... and the power of the guix environment
Guix can replace any package manager, including programming language package managers. It has several advantages:
- Ubiquitous reproducibility.
- Ubiquitous kickbacks.
- No need to learn another package manager.
At this point, you should mention the
guix environment
. This command only sets up a temporary environment with a specific set of packages, like
virtualenv
. Killer feature is that it is universal for all languages and their combinations.
Texlive
(Disclaimer: as of January 2019, the TeXlive assembly system for Guix is being modified).
TeXlive received a special mention, because it is especially awful :), which once again confirms the saving role of Guix!
Most Unix-based operating systems typically distribute TeXlive as part of a set of packages. For example, in Arch Linux there are a dozen of these. If you need some TeX packages from different sets, then Arch Linux leaves no choice but to install thousands (possibly unnecessary) packages, and TeXlive takes up a
lot of space: hundreds of megabytes.
Alternatively, you can install TeXlive manually, but let's face it:
tlmgr
is just a bad batch manager, and it requires tedious additional work.
Using Guix, TeXlive packages are installed separately, like everything else that helps you keep your own set of TeXlive packages or even create virtual environment specifications for compiling specific documents.
Core
Many operating systems offer only limited support for non-standard kernels. If users want to move away from the default kernel, the non-standard kernel has to be manually maintained.
Gentoo is known to "require" a custom kernel as a recommended (required?) Installation step. However, this is hardly a mandatory requirement, and users themselves must support the configuration of the kernel.
In Guix, the kernel is a fully customizable regular package, just like any other. You can customize everything and transfer the kernel configuration file to the package definition.
For example, the following are the definitions of a non-free Linux kernel with the
iwlwifi
driver (warning: I strongly advise against using proprietary drivers, as they pose a serious threat to your privacy and freedom):
(define-module (ambrevar linux-custom) #:use-module (guix gexp) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix git-download) #:use-module (guix build-system trivial) #:use-module ((guix licenses) #:prefix license:) #:use-module (gnu packages linux) #:use-module (srfi srfi-1)) (define-public linux-nonfree (package (inherit linux-libre) (name "linux-nonfree") (version (package-version linux-libre)) (source (origin (method url-fetch) (uri (string-append "https://www.kernel.org/pub/linux/kernel/v4.x/" "linux-" version ".tar.xz")) (sha256 (base32 "1lm2s9yhzyqra1f16jrjwd66m3jl43n5k7av2r9hns8hdr1smmw4")))) (native-inputs `(("kconfig" ,(local-file "./linux-custom.conf")) ,@(alist-delete "kconfig" (package-native-inputs linux-libre)))))) (define (linux-firmware-version) "9d40a17beaf271e6ad47a5e714a296100eef4692") (define (linux-firmware-source version) (origin (method git-fetch) (uri (git-reference (url (string-append "https://git.kernel.org/pub/scm/linux/kernel" "/git/firmware/linux-firmware.git")) (commit version))) (file-name (string-append "linux-firmware-" version "-checkout")) (sha256 (base32 "099kll2n1zvps5qawnbm6c75khgn81j8ns0widiw0lnwm8s9q6ch")))) (define-public linux-firmware-iwlwifi (package (name "linux-firmware-iwlwifi") (version (linux-firmware-version)) (source (linux-firmware-source version)) (build-system trivial-build-system) (arguments `(#:modules ((guix build utils)) #:builder (begin (use-modules (guix build utils)) (let ((source (assoc-ref %build-inputs "source")) (fw-dir (string-append %output "/lib/firmware/"))) (mkdir-p fw-dir) (for-each (lambda (file) (copy-file file (string-append fw-dir (basename file)))) (find-files source "iwlwifi-.*\\.ucode$|LICENSE\\.iwlwifi_firmware$")) #t)))) (home-page "https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi") (synopsis "Non-free firmware for Intel wifi chips") (description "Non-free iwlwifi firmware") (license (license:non-copyleft "https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/tree/LICENCE.iwlwifi_firmware?id=HEAD"))))
Custom kernel and firmware can be conditionally included in the current system configuration (some file
config.scm
):
(define *lspci* (let* ((port (open-pipe* OPEN_READ "lspci")) (str (get-string-all port))) (close-pipe port) str)) (operating-system (host-name "...")
Then follow these steps to install the new system configuration:
sudo -E guix system reconfigure config.scm
Without even installing a new kernel, you can directly create an image ready for booting from a USB drive.
Games
Since Guix packages use advanced technologies (for example, the latest versions of Mesa) and allow full kernel tuning, this is an ideal platform for games and, in particular, for
packaging games!
Unfortunately, the game industry is still far from the free software philosophy, and very few games are packaged as part of the official Guix project.
Although Guix stands for free software and doesn’t accept any proprietary rights in its repository, ironically, many advanced features make Guix an ideal package manager for non-free software.
Some of the benefits are:
guix environment
allows you to run any application in an isolated container that restricts network access, hides the file system (there is no risk that a proprietary program will steal any of your files, say, a bitcoin wallet or PGP keys) and even system-level information such as as username. This is necessary to run any unreliable closed source program.
- Functional package management: closed source programs usually do not stand the test of time and break down when a library dependency changes its API. Because Guix detects packages on top of any version of any dependency (without conflicts with the current system), Guix allows you to create packages for closed-source games that work forever.
- Reproducible environment: closed source programs are usually poorly tolerated and can behave differently in systems with slightly different dependencies. The reproducibility feature of Guix implies that if we make the Guix package work once, it will always work (except for hardware breakdown or a change in hardware configuration).
For these reasons, Guix is the perfect tool for packaging and distributing closed source games.
However, this is a large separate topic, which is best left for another article.
Tips and Tips
Emacs-guix
One of the amazing benefits of Guix is the
Emacs-Guix interface , which allows you to install and remove packages, selectively update, search, go to package definition, manage generations, print "differences" between them, and much more.
It has design modes for assembly and programming, as well as a special interactive environment Scheme
REPL . This is a unique user interface for the operating system.
There is also the
Helm System Packages interface, which partially overlaps with Emacs-Guix, but it seems to me more pleasant for quick package searching and quick operations.
Data storage
Since Guix saves several generations of system configurations (including the entire package history), it requires more disk space than other operating systems.
In my experience, in 2018, section 25 GB had to be cleaned about once a month (taking into account that I have large requests for the number of packages), and the section 50 GB can not be touched for a whole year.It is convenient to use the command to clear the storage guix gc
, but it can remove “too many packages”, that is, packages that will be needed immediately upon the next update.Emacs-Guix has a command mx guix-store-dead-item
that sorts dead packets by size and allows you to delete them individually.If you need to analyze dependencies, look at guix gc --references
and guix gc --requisites
. This can be combined with the output result guix build ...
to see the different elements of the dependency graph.For example, to view the code for one of the build scripts, open the file returned by the following command: $ guix gc --references $(guix build -d coreutils) | grep builder /gnu/store/v02xky6f5rvjywd7ficzi5pyibbmk6cq-coreutils-8.29-guile-builder
Manifest generation
It is often useful to generate a manifest of all packages installed in a profile.This can be done using the following Guile script: (use-modules (guix profiles) (ice-9 match) (ice-9 pretty-print)) (match (command-line) ((_ where) (pretty-print `(specifications->manifest ',(map manifest-entry-name (manifest-entries (profile-manifest where)))))) (_ (error "Please provide the path to a Guix profile.")))
For example, run it on the profile ~/.guix-profile
: $ guile -s manifest-to-manifest.scm ~/.guix-profile
My dotfiles track the history of installed packages. Since I also save the Guix version, I can return to the exact state of my system at any time in the past.Links
Some web interfaces:Documents:
Informal packages: