This page looks best with JavaScript enabled

Nixos

 ·  ☕ 6 min read  ·  ✍️ TinHead

Intro

First time I ever found out about Linux was in ‘97 on a CD from Chip magazine (yeah round shiny thingies just like DVD’s but smaller in capacity). It was a small linux distro you could start from windows, without installing to the harddrive.

I was hooked instatly, after a while I had my PC dualbooting, discovered the man pages, the howto’s … New world!

Since that first contact I’ve been running some Linux distro constantly, to name a few Slackware, RedHat, Ubuntu, Archlinux, Fedora, Gentoo, Funtoo, LFS (well only once 😄), Solus, etc. From time to time I did also wander to the *BSD world only to come back defeated by some thing that did not work … anyway I had my fun and I’m diverging.

Last year I had the itch to try something new again while fighting broken python dependencies, versions, virtualenvs.

Enter NixOS

Instead of trying to explain what this is all about, I’m better off quoting the NixOS homepage ( https://nixos.org ):

A Linux distribution with a unique approach to package and configuration management. Built on top of the Nix package manager, it is completely declarative, makes upgrading systems reliable, and has many other advantages.

Right and Nix package manager is:

A powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible. Share your development and build environments across different machines.

There you have it as per it’s creators 😄

OK leaving the in depth info to the site above I’ll just dive a bit on my experience so far with NixOS.

  1. The install process is not as easy as say Fedora or Ubuntu, if you are expecting a graphical installer it’s not there
  2. All the system setup is controlled by editing /etc/nixos/configuration.nix and/or /etc/nixos/hardware-configuration.nix. Each time you add a setting in there you need to rebuild your system’s setup by running nixos-rebuild switch. This does not mean it’s recompiling packages (well most of the time) but just the system configuration.
  3. Forget thinking in dynamic linked packages and deps as rpm or deb packages work. There is no such thing in nix/nixos. Each package comes with every dependency linked and separated from the rest. Yes you can have python3.7, python2.7, python 3.8 all installed at the same time with no issues.
  4. Forget about the file system standard you are used to there is just the nix store in /nix and symlinks.
  5. If you update and the system brakes you can always go back to the last working generation.
  6. You can and you probably will learn to use nix-shell to setup throw-away environments for instance to install the latest unstable you name it without having to care it will mess with the rest of the system.
  7. Did I mention nix-shell? Yes very powerful 😄

It is great isn’t it? Of course nothing is perfect so here are some drawbacks:

  1. Are you used to modify things in /etc/ by hand and be done with it? Forget it. You have to go the long way around and figure a way to make it happen in configuration.nix
  2. Are you used to mount /usr on a different partition? Useless because the bulk of things are now in /nix so make sure you either make your / partition big enough or (huh not sure if this works…) mount /nix in another partition.
  3. Are you used to rpm/dnf/apt/pacman/emerge <replace with install param\> <package>? Forget it you add it to configuration.nix and rebuild. Or you use nix-env -iA nixos.<package> … buut this is not really encouraged by NixOS’s approach.
  4. Learning curve? I would not say the nix language is hard to grasp but the documentation, while thorough, oh well you just don’t find the thing you want to do right away. They are working on it though and the forum is very active.
  5. Not all hardware in the world will work out of the box, usually the Linux case but not so much lately in mainstream distros, YMMW

All that being said I’m happy with it, although sometimes I feel you have to work a lot just to have a setting changed the way I want it.

The nix-shell

Now to the stuff you can do with Nix.

You can have Nix installed regardless if you use NixOS or not. It can be installed on most if not all Linux based distros, MacOS (with some hacks to let you have /nix on another partition) and even Windows WSL2.

Here is an example of my setup for a python environment I use for some older scripts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
with import <nixpkgs> {};
mkShell {
  name = "pip2-env";
  buildInputs = with python2.pkgs; [
    pip
    setuptools
    click
    boto3
    boto
    awscli
    pyyaml
    pipenv
  ];
shellHook = ''
    export LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH
    alias pip="PIP_PREFIX='$(pwd)/_build/pip_packages' \pip"
    export PYTHONPATH="$(pwd)/_build/pip_packages/lib/python2.7/site-packages:$PYTHONPATH"
    unset SOURCE_DATE_EPOCH
  '';
}

You save this in a file called shell.nix and run nix-shell in the same folder… Magic ! You get python2 and the deps mentioned and pip available while being in the shell. You exit it? Nothing left to bother you until the next time you need it.

Here is another example with a Rust env for embedded STM32 platforms:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  nixpkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
  ruststable = (nixpkgs.latest.rustChannels.stable.rust.override { extensions = [ "rust-src" "rls-preview" "rust-analysis" "rustfmt-preview" ];});
in
  with nixpkgs;
  stdenv.mkDerivation {
    name = "rust";
    buildInputs = [ openssl pkg-config nasm rustup ruststable cmake zlib gdb ];
  }

and a similar for AVR platforms:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  nixpkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
  ruststable = (nixpkgs.latest.rustChannels.stable.rust.override { extensions = [ "rust-src" "rls-preview" "rust-analysis" "rustfmt-preview" ];});
  crossSystem = {
    config = "avr";
  };
in
  with nixpkgs;
  stdenv.mkDerivation {
    name = "rust-avr";
    buildInputs = [ arduino openssl pkg-config nasm rustup ruststable cmake zlib gdb ];
  shellHook =
    ''
      export PATH=$PATH:${arduino}/share/arduino/hardware/tools/avr/bin/
    '';
  }

OK there are things in these nix expressions that seem complicated at a first look, and credit for them goes to the people who posted them for others on the web.

And there is much more! Nix can build container images, AWS ami’s, Azure VM images an so on and so forth.

I hope you find this useful,
Cheers!

Share on

TinHead
WRITTEN BY
TinHead
Linux guy, friendly hacker, 3d printer lover

What's on this Page