Workstation Environments

with Nix and home-manager

dustin.lacewell@workiva.com

  • Worked at Docker Inc
  • Helped establish and grow DockerHub CI/CD
  • Moved from San Francisco, from Chicagoland
  • Obsessed with Developer UX/QoL

Workstation Environments?

  • Software used for work (editors, tools, utilities, etc)
  • Associated configuration

Ideal Properties

  • Declarative
  • Version controlled
  • Reproducable
  • Extensible

Nix

...a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible.

 

It provides atomic upgrades and rollbacks, side-by-side installation of multiple versions of a package, multi-user package management and easy setup of build environments.

"The Purely Functional Package Manager"

 Nixlang

 Nix

 NixOS

 NixOps

 Disnix

 Hydra

Purity

Atomicity

Laziness

Reproducibility

HM

Nix is a package manager

  • Manages packages...!  😮 
  • Everything is isolated under /nix
  • Every package lives in /nix/store

Nixpkgs

Around 6500 packages for Linux and OSX

 

"On GNU/Linux, the packages in Nixpkgs are ‘pure’, meaning that they have no dependencies on packages outside of the Nix store. This means that they should work on pretty much any GNU/Linux distribution."

Bread and Butter

#> nix-channel --add https://nixos.org/channels/nixpkgs-unstable
#> nix-env -qa 'firefox.*'
#> nix-channel --update
#> nix-env -i firefox
#> nix-env -e firefox



stdenv.mkDerivation rec {
  name = "hello-2.10";

  src = fetchurl {
    url    = "https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz";
    sha256 = "1im1gglfm4k10bh4mdaqzmx3lm3kivnsmxrvl6vyvmfqqzljq75l";
  };

  meta = {
    description = "A program that produces a familiar, friendly greeting";
    platforms = stdenv.lib.platforms.all;
  };
}

Package Purity

Nixlang's purity -> Nix's reproducibility

/nix/store/r8vvq9kq18pz08v249h8my6r9vs7s0n3-firefox-8.0.1
/nix/store/y15i77ghwd0w0xcw8hl2cl1gs4fi9dj5-firefox-8.0.1

Text

SYMLINKS

SYMLINKS EVERYWHERE

  • Dependencies are symlinks
  • Profiles contain symlinks
  • Profiles are symlinks

Atomic upgrades and rollback

#> nix-env --upgrade firefox

​​#> nix-env --rollback

 

Nix is a language

  • Functional
  • (Mostly) Pure
  • Lazy / Non-strict evaluation
  • A "modeling" language

It has basic data types

  • Integers (no floats): 5 + 5
  • Strings: "hello world"
  • Lists: [ "blah" name 5 ]
  • Attrsets: { foo = "bar"; biz.baz = "boz"; }

Every file is an expression

# example.nix
{
  foo = "bar";
  biz = [ 1 "two" 3 ];
}

let expressions are nice

# let <names> in <expr>
let
  filename = "config.conf";
  prefix = "/etc/foo";
  path = "${prefix}/${filename}"
{
  file = touchFile path;
}

Functions

# { <args> }: <expr>
let
  func = { prefix, filename ? "foo.conf" }: {
    fullPath = "${prefix}/${filename}";
    ready = false;
  };
in func { prefix = "/etc/foo"; }

Files can be imported

# prefix.nix
{ filename, prefix ? "/etc/foo" }: 
  "${prefix}/${filename}"
# foo.nix
let
  prefix = import ./prefix.nix;
in {
  fooFile = prefix { filename = "foo.conf"; };
}
# {fooFile="/etc/foo/foo.conf";}

Anatomy of a Package

  • Depend on other packages
  • Built from some source
  • Files are written to $out
  • Basically a special attrset
with import <nixpkgs> {};

stdenv.mkDerivation {
  name = "hello-2.1.1";

  src = fetchurl {
    url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz;
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
  };

  buildInputs = [ tar ];
  builder = builtins.toFile "builder.sh" "
    source $stdenv/setup
    tar xvfz $src
    cd hello-*
    ./configure --prefix=$out
    make
    make install
  ";
}
with import <nixpkgs> {};

stdenv.mkDerivation {
  name = "hello-2.1.1";
  src = fetchurl {
    url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz;
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
  };
}
stdenv.mkDerivation {
  name = "foo-5.4";
  buildPhases = [ "buildPhase" 
                  "installPhase" ];
  buildPhase = ''
    gcc foo.c -o foo
  '';
  installPhase = ''
    mkdir -p $out/bin
    cp foo $out/bin
  '';
}

Packaging Harbour-CLI

  • Golang CLI utility
  • Uses 'Glide' for dependencies
  • Produces a single binary

Use a profile?

#> nix-env --switch-profile /nix/var/nix/profiles/harbour-cli
#> nix-env -i go glide git emacs
#> emacs main.go
#> go build, etc
# default.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
  name = "harbour-cli";
  src = ./.;
  buildInputs = [ git go glide ];
}

nix-shell 

#> nix-shell
#> which go

/nix/store/2r298x93l2v48yrjp31381vcghyrnlz3-go-1.9.2/bin/go

#> emacs main.go
#> glide install && go build, etc
# default.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
  name = "harbour-cli";
  src = ./.;
  buildInputs = [ git go glide ];
  buildPhases = [ "unpackPhase" "buildPhase" ];
  builderPhase = ''
    glide install
    go test --cover
    go build -o $out/bin/harbour-cli
  '';
}

Installing the package

#> nix-env -i -f .
#> which harbour-cli

/Users/dustinlacewell/.nix-profile/bin/harbour-cli

#> nix-env -i \
https://github.com/Workiva/harbour-cli/archive/master.tar.gz

NixOS

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

nix-rebuild

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Configuration.nix

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Syntax Sugar

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Repetition Blues

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Set Extension

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Functions

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Higher-order Functions

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Modularity

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Functions

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Configuration Modules

  • Young, typical GNU/Linux distro
  • Built on top of Nix
  • Declarative system configuration

Workstation Environments with Nix

By dlacewell

Workstation Environments with Nix

Nix is the package manager of the future. Its incredibly expressive language gives us the tools to describe our workstation environments and reliably reproduce them.

  • 945