diff --git a/krebs/4lib/default.nix b/krebs/4lib/default.nix
deleted file mode 100644
index c40b9a868..000000000
--- a/krebs/4lib/default.nix
+++ /dev/null
@@ -1,59 +0,0 @@
-_:
-
-let
-  lib = import <stockholm/lib>;
-in
-
-with lib;
-
-let out = lib // rec {
-
-  guard = spec@{ type, value, ... }:
-    assert isOptionType type;
-    if type.check value
-      then value
-      else throw (toString (filter isString [
-        "argument"
-        (if spec ? name then "‘${spec.name}’" else null)
-        "is not a ${type.name}"
-      ]));
-
-  types = import ./types.nix {
-    lib = lib // { inherit genid optionalTrace; };
-  };
-
-  genid = import ./genid.nix { lib = lib // out; };
-  genid_signed = x: ((genid x) + 16777216) / 2;
-  git = import ./git.nix { lib = lib // out; };
-  tree = import ./tree.nix { inherit lib; };
-
-  lpad = n: c: s:
-    if stringLength s < n
-      then lpad n c (c + s)
-      else s;
-
-  toC = x: let
-    type = typeOf x;
-    reject = throw "cannot convert ${type}";
-  in {
-    list = "{ ${concatStringsSep ", " (map toC x)} }";
-    null = "NULL";
-    set = if isDerivation x then toJSON x else reject;
-    string = toJSON x; # close enough
-  }.${type} or reject;
-
-  subdirsOf = path:
-    mapAttrs (name: _: path + "/${name}")
-             (filterAttrs (_: eq "directory") (readDir path));
-
-  genAttrs' = names: f: listToAttrs (map f names);
-
-  getAttrs = names: set:
-    listToAttrs (map (name: nameValuePair name set.${name})
-                     (filter (flip hasAttr set) names));
-
-  setAttr = name: value: set: set // { ${name} = value; };
-
-  optionalTrace = c: msg: x: if c then trace msg x else x;
-
-}; in out
diff --git a/krebs/4lib/tree.nix b/krebs/4lib/tree.nix
deleted file mode 100644
index 1cd83b3f6..000000000
--- a/krebs/4lib/tree.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-{ lib, ... }:
-
-with lib;
-
-rec {
-  # tree k v = set k (either v (tree k v))
-
-  # get : [k] -> tree k v -> v
-  get = path: tree:
-    if length path > 0
-      then get (tail path) tree.${head path} # TODO check if elem exists
-      else tree;
-}
diff --git a/lib/default.nix b/lib/default.nix
index 1f5010853..2b12fa4bf 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,10 +1,44 @@
 let
-  lib = import <nixpkgs/lib> // builtins // {
+  nixpkgs-lib = import <nixpkgs/lib>;
+  lib = with lib; nixpkgs-lib // builtins // {
+    git = import ./git.nix { inherit lib; };
     shell = import ./shell.nix { inherit lib; };
+    types = nixpkgs-lib.types // import ./types.nix { inherit lib; };
 
     eq = x: y: x == y;
     ne = x: y: x != y;
     mod = x: y: x - y * (x / y);
+
+    genid = import ./genid.nix { inherit lib; };
+    genid_signed = x: ((lib.genid x) + 16777216) / 2;
+
+    lpad = n: c: s:
+      if lib.stringLength s < n
+        then lib.lpad n c (c + s)
+        else s;
+
+    subdirsOf = path:
+      lib.mapAttrs (name: _: path + "/${name}")
+                   (filterAttrs (_: eq "directory") (readDir path));
+
+    genAttrs' = names: f: listToAttrs (map f names);
+
+    getAttrs = names: set:
+      listToAttrs (map (name: nameValuePair name set.${name})
+                       (filter (flip hasAttr set) names));
+
+    setAttr = name: value: set: set // { ${name} = value; };
+
+    toC = x: let
+      type = typeOf x;
+      reject = throw "cannot convert ${type}";
+    in {
+      list = "{ ${concatStringsSep ", " (map toC x)} }";
+      null = "NULL";
+      set = if isDerivation x then toJSON x else reject;
+      string = toJSON x; # close enough
+    }.${type} or reject;
+
   };
 in
 
diff --git a/krebs/4lib/genid.nix b/lib/genid.nix
similarity index 100%
rename from krebs/4lib/genid.nix
rename to lib/genid.nix
diff --git a/krebs/4lib/git.nix b/lib/git.nix
similarity index 100%
rename from krebs/4lib/git.nix
rename to lib/git.nix
diff --git a/krebs/4lib/types.nix b/lib/types.nix
similarity index 94%
rename from krebs/4lib/types.nix
rename to lib/types.nix
index 8d6ace2e5..edd48c35b 100644
--- a/krebs/4lib/types.nix
+++ b/lib/types.nix
@@ -1,10 +1,16 @@
 { lib, ... }:
 
-with builtins;
-with lib;
-with types;
+let
+  inherit (lib)
+    all any concatMapStringsSep concatStringsSep const filter flip genid
+    hasSuffix head isInt isString length match mergeOneOption mkOption
+    mkOptionType optional optionalAttrs optionals range splitString
+    stringLength tail typeOf;
+  inherit (lib.types)
+    attrsOf bool either enum int listOf nullOr path str string submodule;
+in
 
-types // rec {
+rec {
 
   host = submodule ({ config, ... }: {
     options = {
@@ -20,6 +26,11 @@ types // rec {
         default = {};
       };
 
+      binary-cache.pubkey = mkOption {
+        type = nullOr binary-cache-pubkey;
+        default = null;
+      };
+
       owner = mkOption {
         type = user;
       };
@@ -27,7 +38,7 @@ types // rec {
       extraZones = mkOption {
         default = {};
         # TODO: string is either MX, NS, A or AAAA
-        type = with types; attrsOf string;
+        type = attrsOf string;
       };
 
       secure = mkOption {
@@ -331,6 +342,8 @@ types // rec {
     merge = mergeOneOption;
   };
 
+  binary-cache-pubkey = str;
+
   pgp-pubkey = str;
 
   ssh-pubkey = str;
@@ -356,7 +369,7 @@ types // rec {
 
   tinc-pubkey = str;
 
-  krebs.file-location = types.submodule {
+  krebs.file-location = submodule {
     options = {
       # TODO user
       host = mkOption {
@@ -364,7 +377,7 @@ types // rec {
       };
       # TODO merge with ssl.privkey.path
       path = mkOption {
-        type = types.either types.path types.str;
+        type = either path str;
         apply = x: {
           path = toString x;
           string = x;