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
Made with Slides.com