Libre-rate your NixOS
September 25, 2017
NixOS isn't a libre distribution by any means, but it comes close, and maintains a clear distinction between free and non-free packages (and in fact, different license types). This makes it possible to configure the system to exclude non-free packages, and with the addition of a libre kernel, allows us to turn NixOS into a libre platform. Of course, this isn't the same as leveraging an FSF endorsed distribution, but for those who are happy to maintain and take responsibility for the software running on their systems, it's as good. In fact, it's a little strange that the process of deblobbing normal systems isn't better documented and more widely done, after all, this is exactly what a libre distribution typically is. If you want a libre system out of the box, with nix-y functionality, GuixSD is also worth a look, but I really like NixOS, and I thought it worth the effort to libre-up.
By default, most non-free packages can't be installed on nixos without explicitly allowing unfree packages. There are a couple of places however where non-free software can be installed. The first is in the standard linux kernel, so our first job is to rebase our system on top of a libre linux build. NixOS does allows packages with the license type unfreeRedistributableFirmware
, so the remainder of the work consists of blacklisting this license type.
Installing a libre kernel
The default linux kernel comes with all the binary blobs typically packaged with the linux kernel. NixoOS makes it easy to specify a custom kernel in /etc/nixos/configuration.nix
.
There are three stages to installing a custom kernel build:
- Generate/obtain a kernel build configuration file
- Write the build expression into
configuration.nix
- Testing
Nix will take care of building and installing the kernel for us. It also makes it trivial to reproduce once we've got the setup we want. Upgrades can be achieved just by updating the source package being pulled.
Building a kernel takes a little time, so if this is being done on a lot of machines (and once you've got it working as you like), you may want to set up a custom repository and binary cache for your built kernel, and use this in your configuration.nix
. This article should help with this, and provide other options for deployment.
Obtaining your current configuration
We can obtain the configuration file used to build the current kernel using `zcat /proc/config.gz`. Let's store this in a file alongside `configuration.nix` and use it to build our libre kernel.
$ zcat /proc/config.gz | sudo tee /etc/nixos/kernel.config
At a later point you could customize this file to adjust the kernel to your needs, or run the configuration tools bundled with the libre kernel to generate a configuration file completely customized to your needs. The above approach however will do to get started.
Specifying our new kernel
Nix will take care of building our kernel properly. We just need to provide enough details in configuration.nix
. The following addition to configuration.nix
provides all we need to build the 4.12.10 linux-libre kernel in NixOS.
boot.kernelPackages = pkgs.linuxPackages_custom
version = "4.12.10-gnu";
src = pkgs.fetchurl {
url = "http://www.linux-libre.fsfla.org/pub/linux-libre/releases/4.12.10-gnu/linux-libre-4.12.10-gnu.tar.xz";
sha256 = "122a457b0def2050378359641cce341c4d5f3f3dc70d9c55d58ac82ccfaf361b";
};
configfile = /etc/nixos/kernel.config;
};
Building and testing
Run nixos-rebuild switch
to instantiate your new configuration. You can try out your new kernel and test it works easily, and if there are problems boot into the old working kernel from the bootloader (another nix win). You can roll back to your old configuration with nixos-rebuild switch --rollback
.
Blacklisting unwanted licenses
nixpkgs
can be configured to blacklist certain license types. The license definition file lists all the licenses used in all the packages in nix. Anything with free = false;
is recognized as a non-free package by nix, and can't be installed unless non-free packages are explicitly enabled. However, there are non-free licenses without this label. unfreeRedistributableFirmware
is non-free yet doesn't have this label. To help avoid inadvertantly installing these kinds of packages, we need to blacklist this license (along with any others we want to avoid).
System level
The following snippet, added to configuration.nix
will do the job.
{ config, pkgs, lib, ... }:
{
.
.
.
# Block any unfree firmware (which isn't in the kernel)
nixpkgs.config = {
blacklistedLicenses = with lib.licenses; [
unfreeRedistributableFirmware
];
};
.
.
.
};
It's also possible to specify a license whitelist, with the option whitelistedLicenses
.
User level
nixpkgs
configuration at the system level isn't reflected for the users, so users will still by default be able to install non-free packages. User nixpkgs
need to be configured separately. At present, the best way to do this is to add
{
blacklistedLicenses = with stdenv.lib.licenses; [
unfreeRedistributableFirmware
];
}
to ~/.config/nixpkgs/config.nix
. The nixpkgs manual contains information here that's useful.
If you use a manifest to install packages, you can add these configuration options to your import of nixpkgs
. For example:
# Define pkgs as <nixpkgs> with some licenses
# blacklisted
pkgs = import <nixpkgs> {
config = {
blacklistedLicenses = with _licenses; [
unfreeRedistributableFirmware
];
};
};
Currently, there doesn't seem to be a way to add a system wide default for user nixpkgs configuration in the absence of an explicit configuration file, which is unfortunate. This works reasonably, in the meantime, and since firmware is the only non-free software available to users by default, is not as bad as it might seem.