diff --git a/1systems/tv/cd.nix b/1systems/tv/cd.nix
index c0c41e96c..4b8c40f35 100644
--- a/1systems/tv/cd.nix
+++ b/1systems/tv/cd.nix
@@ -7,6 +7,8 @@ let
 in
 
 {
+  krebs.build.host = config.krebs.hosts.cd;
+
   imports = [
     ../../2configs/tv/CAC-Developer-2.nix
     ../../2configs/tv/CAC-CentOS-7-64bit.nix
@@ -32,10 +34,6 @@ in
       tv.iptables.input-internet-accept-new-tcp =
         singleton config.krebs.github-hosts-sync.port;
     }
-    {
-      imports = [ ../../2configs/tv/identity.nix ];
-      tv.identity.self = config.krebs.hosts.cd;
-    }
     {
       tv.iptables = {
         enable = true;
diff --git a/1systems/tv/mkdir.nix b/1systems/tv/mkdir.nix
index 113fc9596..938f50118 100644
--- a/1systems/tv/mkdir.nix
+++ b/1systems/tv/mkdir.nix
@@ -3,6 +3,8 @@
 with lib;
 
 {
+  krebs.build.host = config.krebs.hosts.mkdir;
+
   imports = [
     ../../2configs/tv/CAC-Developer-1.nix
     ../../2configs/tv/CAC-CentOS-7-64bit.nix
@@ -10,10 +12,6 @@ with lib;
     ../../2configs/tv/consul-server.nix
     ../../2configs/tv/exim-smarthost.nix
     ../../2configs/tv/git.nix
-    {
-      imports = [ ../../2configs/tv/identity.nix ];
-      tv.identity.self = config.krebs.hosts.mkdir;
-    }
     {
       tv.iptables = {
         enable = true;
diff --git a/1systems/tv/nomic.nix b/1systems/tv/nomic.nix
index fc58c1698..1f7f6b188 100644
--- a/1systems/tv/nomic.nix
+++ b/1systems/tv/nomic.nix
@@ -3,16 +3,14 @@
 with lib;
 
 {
+  krebs.build.host = config.krebs.hosts.nomic;
+
   imports = [
     ../../2configs/tv/AO753.nix
     ../../2configs/tv/base.nix
     ../../2configs/tv/consul-server.nix
     ../../2configs/tv/exim-retiolum.nix
     ../../2configs/tv/git.nix
-    {
-      imports = [ ../../2configs/tv/identity.nix ];
-      tv.identity.self = config.krebs.hosts.nomic;
-    }
     {
       tv.iptables = {
         enable = true;
diff --git a/1systems/tv/rmdir.nix b/1systems/tv/rmdir.nix
index 15d624d1c..45e9997e4 100644
--- a/1systems/tv/rmdir.nix
+++ b/1systems/tv/rmdir.nix
@@ -3,6 +3,8 @@
 with lib;
 
 {
+  krebs.build.host = config.krebs.hosts.rmdir;
+
   imports = [
     ../../2configs/tv/CAC-Developer-1.nix
     ../../2configs/tv/CAC-CentOS-7-64bit.nix
@@ -10,10 +12,6 @@ with lib;
     ../../2configs/tv/consul-server.nix
     ../../2configs/tv/exim-smarthost.nix
     ../../2configs/tv/git.nix
-    {
-      imports = [ ../../2configs/tv/identity.nix ];
-      tv.identity.self = config.krebs.hosts.rmdir;
-    }
     {
       tv.iptables = {
         enable = true;
diff --git a/1systems/tv/wu.nix b/1systems/tv/wu.nix
index 5ca64ce9e..0b2dab9df 100644
--- a/1systems/tv/wu.nix
+++ b/1systems/tv/wu.nix
@@ -7,6 +7,8 @@ let
 in
 
 {
+  krebs.build.host = config.krebs.hosts.wu;
+
   imports = [
     ../../2configs/tv/w110er.nix
     ../../2configs/tv/base.nix
@@ -16,10 +18,6 @@ in
     ../../2configs/tv/mail-client.nix
     ../../2configs/tv/xserver.nix
     ../../2configs/tv/synaptics.nix # TODO w110er if xserver is enabled
-    {
-      imports = [ ../../2configs/tv/identity.nix ];
-      tv.identity.self = config.krebs.hosts.wu;
-    }
     {
       environment.systemPackages = with pkgs; [
 
diff --git a/2configs/tv/charybdis.nix b/2configs/tv/charybdis.nix
index a45c7aebe..265f85132 100644
--- a/2configs/tv/charybdis.nix
+++ b/2configs/tv/charybdis.nix
@@ -123,7 +123,7 @@ let
     #loadmodule "extensions/ip_cloaking.so";
     
     serverinfo {
-      name = ${toJSON (head config.tv.identity.self.nets.retiolum.aliases)};
+      name = ${toJSON (head config.krebs.build.host.nets.retiolum.aliases)};
       sid = "4z3";
       description = "miep!";
       network_name = "irc.retiolum";
@@ -133,9 +133,9 @@ let
       /* On multi-homed hosts you may need the following. These define
        * the addresses we connect from to other servers. */
       /* for IPv4 */
-      vhost = ${concatMapStringsSep ", " toJSON config.tv.identity.self.nets.retiolum.addrs4};
+      vhost = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs4};
       /* for IPv6 */
-      vhost6 = ${concatMapStringsSep ", " toJSON config.tv.identity.self.nets.retiolum.addrs6};
+      vhost6 = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs6};
       
       /* ssl_private_key: our ssl private key */
       ssl_private_key = "/tmp/ssl.key";
@@ -240,7 +240,7 @@ let
        */
       # XXX This is stupid because only one host is allowed[?]
       #host = ''${concatMapStringsSep ", " toJSON (
-      #  config.tv.identity.self.nets.retiolum.addrs
+      #  config.krebs.build.host.nets.retiolum.addrs
       #)};
       port = 6667;
       sslport = 6697;
diff --git a/2configs/tv/consul-server.nix b/2configs/tv/consul-server.nix
index 63dabdc2a..d10f9ea75 100644
--- a/2configs/tv/consul-server.nix
+++ b/2configs/tv/consul-server.nix
@@ -4,7 +4,7 @@
   tv.consul = rec {
     enable = true;
 
-    inherit (config.tv.identity) self;
+    self = config.krebs.build.host;
     inherit (self) dc;
 
     server = true;
diff --git a/2configs/tv/git.nix b/2configs/tv/git.nix
index b7f9983a1..f884ea464 100644
--- a/2configs/tv/git.nix
+++ b/2configs/tv/git.nix
@@ -6,7 +6,7 @@ let
   out = {
     krebs.git = {
       enable = true;
-      root-title = "public repositories at ${config.tv.identity.self.name}";
+      root-title = "public repositories at ${config.krebs.build.host.name}";
       root-desc = "keep calm and engage";
       inherit repos rules;
     };
@@ -14,7 +14,7 @@ let
 
   repos = mapAttrs (_: s: removeAttrs s ["collaborators"]) (
     public-repos //
-    optionalAttrs config.tv.identity.self.secure restricted-repos
+    optionalAttrs config.krebs.build.host.secure restricted-repos
   );
 
   rules = concatMap make-rules (attrValues repos);
@@ -55,8 +55,8 @@ let
     public = true;
     hooks = {
       post-receive = git.irc-announce {
-        # TODO make nick = config.tv.identity.self.name the default
-        nick = config.tv.identity.self.name;
+        # TODO make nick = config.krebs.build.host.name the default
+        nick = config.krebs.build.host.name;
         channel = "#retiolum";
         server = "cd.retiolum";
       };
diff --git a/2configs/tv/identity.nix b/2configs/tv/identity.nix
deleted file mode 100644
index 481ac72a6..000000000
--- a/2configs/tv/identity.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{ config, ... }:
-
-{
-  tv.identity = {
-    enable = true;
-    search = "retiolum";
-  };
-}
diff --git a/3modules/krebs/default.nix b/3modules/krebs/default.nix
index 999e68da2..601ecf017 100644
--- a/3modules/krebs/default.nix
+++ b/3modules/krebs/default.nix
@@ -19,6 +19,21 @@ let
   api = {
     enable = mkEnableOption "krebs";
 
+    build = mkOption {
+      type = types.submodule {
+        options = {
+          host = mkOption {
+            type = types.host;
+          };
+          user = mkOption {
+            type = types.user;
+          };
+        };
+      };
+      # Define defaul value, so unset values of the submodule get reported.
+      default = {};
+    };
+
     hosts = mkOption {
       type = with types; attrsOf host;
     };
@@ -26,12 +41,69 @@ let
     users = mkOption {
       type = with types; attrsOf user;
     };
+
+    # XXX is there a better place to define search-domain?
+    # TODO search-domains :: listOf hostname
+    search-domain = mkOption {
+      type = types.hostname;
+      default = "";
+      example = "retiolum";
+    };
   };
 
   imp = mkMerge [
     { krebs = lass-imp; }
     { krebs = makefu-imp; }
     { krebs = tv-imp; }
+    {
+      # XXX This overlaps with krebs.retiolum
+      networking.extraHosts =
+        let
+          # TODO move domain name providers to a dedicated module
+          # providers : tree label providername
+          providers = {
+            internet = "hosts";
+            retiolum = "hosts";
+            de.viljetic = "regfish";
+            de.krebsco = "ovh";
+          };
+
+          # splitByProvider : [alias] -> set providername [alias]
+          splitByProvider = foldl (acc: alias: insert (providerOf alias) alias acc) {};
+
+          # providerOf : alias -> providername
+          providerOf = alias:
+            tree-get (splitString "." alias) providers;
+
+          # insert : k -> v -> set k [v] -> set k [v]
+          insert = name: value: set:
+            set // { ${name} = set.${name} or [] ++ [value]; };
+
+          # tree k v = set k (either v (tree k v))
+
+          # tree-get : [k] -> tree k v -> v
+          tree-get = path: x:
+            let
+              y = x.${last path};
+            in
+            if typeOf y != "set"
+              then y
+              else tree-get (init path) y;
+        in
+        concatStringsSep "\n" (flatten (
+          # TODO deepMap ["hosts" "nets"] (hostname: host: netname: net:
+          mapAttrsToList (hostname: host:
+            mapAttrsToList (netname: net:
+              let
+                aliases = toString (unique (longs ++ shorts));
+                longs = (splitByProvider net.aliases).hosts;
+                shorts = map (removeSuffix ".${cfg.search-domain}") longs;
+              in
+              map (addr: "${addr} ${aliases}") net.addrs
+            ) host.nets
+          ) config.krebs.hosts
+        ));
+    }
   ];
 
   lass-imp = {
diff --git a/3modules/tv/default.nix b/3modules/tv/default.nix
index e267d0b9f..bb10d8261 100644
--- a/3modules/tv/default.nix
+++ b/3modules/tv/default.nix
@@ -4,7 +4,6 @@ _:
   imports = [
     ./consul.nix
     ./ejabberd.nix
-    ./identity.nix
     ./iptables.nix
   ];
 }
diff --git a/3modules/tv/identity.nix b/3modules/tv/identity.nix
deleted file mode 100644
index 9de432203..000000000
--- a/3modules/tv/identity.nix
+++ /dev/null
@@ -1,77 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with import ../../4lib/tv { inherit lib pkgs; };
-let
-  cfg = config.tv.identity;
-
-  out = {
-    options.tv.identity = api;
-    config = mkIf cfg.enable imp;
-  };
-
-  api = {
-    enable = mkEnableOption "tv.identity";
-
-    self = mkOption {
-      type = types.host;
-    };
-
-    #others = mkOption {
-    #  type = types.host;
-    #  default = filterAttrs (name: _host: name != cfg.self.name) cfg.hosts;
-    #};
-
-    search = mkOption {
-      type = types.hostname;
-    };
-  };
-
-  imp = {
-    networking.extraHosts =
-      concatStringsSep "\n" (flatten (
-        # TODO deepMap ["hosts" "nets"] (hostname: host: netname: net:
-        mapAttrsToList (hostname: host:
-          mapAttrsToList (netname: net:
-            let
-              aliases = toString (unique (longs ++ shorts));
-              longs = (splitByProvider net.aliases).hosts;
-              shorts = map (removeSuffix ".${cfg.search}") longs;
-            in
-            map (addr: "${addr} ${aliases}") net.addrs
-          ) host.nets
-        ) config.krebs.hosts
-      ));
-  };
-
-  # TODO move domain name providers to a dedicated module
-  # providers : tree label providername
-  providers = {
-    internet = "hosts";
-    retiolum = "hosts";
-    de.viljetic = "regfish";
-    de.krebsco = "ovh";
-  };
-
-  # splitByProvider : [alias] -> set providername [alias]
-  splitByProvider = foldl (acc: alias: insert (providerOf alias) alias acc) {};
-
-  # providerOf : alias -> providername
-  providerOf = alias:
-    tree-get (splitString "." alias) providers;
-
-  # insert : k -> v -> set k [v] -> set k [v]
-  insert = name: value: set:
-    set // { ${name} = set.${name} or [] ++ [value]; };
-
-  # tree k v = set k (either v (tree k v))
-
-  # tree-get : [k] -> tree k v -> v
-  tree-get = path: x:
-    let
-      y = x.${last path};
-    in
-    if typeOf y != "set"
-      then y
-      else tree-get (init path) y;
-in
-out