summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormakefu <github@syntax-fehler.de>2017-07-23 21:11:11 +0200
committermakefu <github@syntax-fehler.de>2017-07-23 21:11:11 +0200
commit1e3931d983127bb2cf5fc93471bacfc9770e5b08 (patch)
tree9308da0abd27ad72547bc765e9a4100ccc71630b
parentfd7d1531acd5345136dad71bdcd1050176d88cd6 (diff)
parent1bf9e1e1eea95ea9efeb72a48e19a6df11881a7f (diff)
Merge remote-tracking branch 'lass/master'
-rw-r--r--Makefile8
-rw-r--r--krebs/1systems/hotdog/config.nix17
-rw-r--r--krebs/1systems/hotdog/source.nix3
-rw-r--r--krebs/1systems/puyak/config.nix5
-rw-r--r--krebs/2configs/hw/x220.nix29
-rw-r--r--krebs/3modules/krebs/default.nix24
-rw-r--r--krebs/5pkgs/writers.nix7
-rw-r--r--lass/1systems/iso.nix44
-rw-r--r--lib/eval-source.nix8
-rw-r--r--shell.nix122
-rw-r--r--tv/1systems/caxi/config.nix25
-rw-r--r--tv/1systems/caxi/source.nix3
-rw-r--r--tv/2configs/nginx/krebs-pages.nix13
-rw-r--r--tv/2configs/vim.nix1
-rw-r--r--tv/5pkgs/default.nix31
-rw-r--r--tv/5pkgs/simple/default.nix24
-rw-r--r--tv/5pkgs/simple/djbdns/default.nix (renamed from tv/5pkgs/djbdns/default.nix)0
-rw-r--r--tv/5pkgs/simple/q/default.nix (renamed from tv/5pkgs/q/default.nix)0
-rw-r--r--tv/5pkgs/simple/viljetic-pages/default.nix (renamed from tv/5pkgs/viljetic-pages/default.nix)0
-rw-r--r--tv/5pkgs/simple/viljetic-pages/index.html (renamed from tv/5pkgs/viljetic-pages/index.html)0
-rw-r--r--tv/5pkgs/simple/viljetic-pages/logo.xpm (renamed from tv/5pkgs/viljetic-pages/logo.xpm)0
-rw-r--r--tv/5pkgs/simple/xmonad-tv/default.nix (renamed from tv/5pkgs/xmonad-tv/default.nix)0
22 files changed, 248 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index f25830789..4258d9178 100644
--- a/Makefile
+++ b/Makefile
@@ -102,13 +102,7 @@ ifneq ($(ssh),)
populate: populate-flags += --ssh=$(ssh)
endif
populate:
- nix-instantiate \
- --eval \
- --json \
- --readonly-mode \
- --show-trace \
- --strict \
- $(LOGNAME)/1systems/$(system)/source.nix | \
+ nix-shell --run 'get-source $(LOGNAME)/1systems/$(system)/source.nix' \
populate $(populate-target) $(populate-flags)
# usage: make pkgs.populate
diff --git a/krebs/1systems/hotdog/config.nix b/krebs/1systems/hotdog/config.nix
new file mode 100644
index 000000000..18c8a86cd
--- /dev/null
+++ b/krebs/1systems/hotdog/config.nix
@@ -0,0 +1,17 @@
+# Edit this configuration file to define what should be installed on
+# your system. Help is available in the configuration.nix(5) man page
+# and in the NixOS manual (accessible by running ‘nixos-help’).
+
+{ config, lib, pkgs, ... }:
+
+{
+ imports = [
+ <stockholm/krebs>
+ <stockholm/krebs/2configs>
+ ];
+
+ krebs.build.host = config.krebs.hosts.hotdog;
+
+ boot.isContainer = true;
+ networking.useDHCP = false;
+}
diff --git a/krebs/1systems/hotdog/source.nix b/krebs/1systems/hotdog/source.nix
new file mode 100644
index 000000000..0fa61b20f
--- /dev/null
+++ b/krebs/1systems/hotdog/source.nix
@@ -0,0 +1,3 @@
+import <stockholm/krebs/source.nix> {
+ name = "hotdog";
+}
diff --git a/krebs/1systems/puyak/config.nix b/krebs/1systems/puyak/config.nix
index 835d717b8..19ee2343d 100644
--- a/krebs/1systems/puyak/config.nix
+++ b/krebs/1systems/puyak/config.nix
@@ -5,6 +5,7 @@
<stockholm/krebs>
<stockholm/krebs/2configs>
<stockholm/krebs/2configs/secret-passwords.nix>
+ <stockholm/krebs/2configs/hw/x220.nix>
<stockholm/krebs/2configs/repo-sync.nix>
<stockholm/krebs/2configs/shared-buildbot.nix>
@@ -48,10 +49,6 @@
};
};
- hardware.enableAllFirmware = true;
- networking.wireless.enable = true;
- nixpkgs.config.allowUnfree = true;
-
services.logind.extraConfig = ''
HandleLidSwitch=ignore
'';
diff --git a/krebs/2configs/hw/x220.nix b/krebs/2configs/hw/x220.nix
new file mode 100644
index 000000000..c85bac0d4
--- /dev/null
+++ b/krebs/2configs/hw/x220.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+with import <stockholm/lib>;
+{
+ networking.wireless.enable = lib.mkDefault true;
+
+ hardware.enableRedistributableFirmware = true;
+
+ hardware.cpu.intel.updateMicrocode = true;
+
+ services.tlp.enable = true;
+
+ boot = {
+ kernelModules = [ "kvm-intel" "acpi_call" "tpm-rng" ];
+ extraModulePackages = [ config.boot.kernelPackages.tp_smapi ];
+ kernelParams = [ "acpi_backlight=none" ];
+ };
+
+ hardware.opengl.extraPackages = [
+ pkgs.vaapiIntel
+ pkgs.vaapiVdpau
+ ];
+
+ security.rngd.enable = true;
+
+ services.xserver = {
+ videoDriver = "intel";
+ };
+}
diff --git a/krebs/3modules/krebs/default.nix b/krebs/3modules/krebs/default.nix
index f751b4f9f..07543489a 100644
--- a/krebs/3modules/krebs/default.nix
+++ b/krebs/3modules/krebs/default.nix
@@ -30,6 +30,30 @@ let
});
in {
hosts = {
+ hotdog = {
+ owner = config.krebs.users.krebs;
+ nets = {
+ retiolum = {
+ ip4.addr = "10.243.77.3";
+ ip6.addr = "42:0:0:0:0:0:77:3";
+ aliases = [
+ "hotdog.r"
+ ];
+ tinc.pubkey = ''
+ -----BEGIN RSA PUBLIC KEY-----
+ MIIBCgKCAQEAs9+Au3oj29C5ol/YnkG9GjfCH5z53wxjH2iy8UPike8C7GASZKqc
+ bZBrvxkIOyVs5oVtolPcaI0/nvtpIhSlmM6hg9qe1rZO6jXt53GVNvgdcUIfVHbX
+ mQmp4oVXOjPIeDqLn32Mc0O73Kp6i66zQGAXi8ejczuO0h6oSvAnjolT4wM9jugk
+ JBGCDlpl9mxAGDN5VOqbg2i0FxwtUk2UA9XghEaRcfBkVdsOrtW8sCwOg8YttQt9
+ fs7JjezUtw7JBxN754ynaahSRODcjyJhwjE18tKx6P7wsNbgbmULFQz+7IxZ01/P
+ h5ZUzfd1r1pTzQ0nYD5aRtlDd7zP7y5tUwIDAQAB
+ -----END RSA PUBLIC KEY-----
+ '';
+ };
+ };
+ ssh.privkey.path = <secrets/ssh.id_ed25519>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICxFkBln23wUxt4RhIHE3GvdKeBpJbjn++6maupHqUHp";
+ };
puyak = {
owner = config.krebs.users.krebs;
nets = {
diff --git a/krebs/5pkgs/writers.nix b/krebs/5pkgs/writers.nix
index c4fb8cd83..49ca3557e 100644
--- a/krebs/5pkgs/writers.nix
+++ b/krebs/5pkgs/writers.nix
@@ -262,7 +262,12 @@ with import <stockholm/lib>;
};
};
- writeJSON = name: value: pkgs.writeText name (toJSON value);
+ writeJSON = name: value: pkgs.runCommand name {
+ json = toJSON value;
+ passAsFile = [ "json" ];
+ } /* sh */ ''
+ ${pkgs.jq}/bin/jq . "$jsonPath" > "$out"
+ '';
writeNixFromCabal =
trace (toString [
diff --git a/lass/1systems/iso.nix b/lass/1systems/iso.nix
index 820ef74b8..4431a702c 100644
--- a/lass/1systems/iso.nix
+++ b/lass/1systems/iso.nix
@@ -151,25 +151,41 @@ with import <stockholm/lib>;
systemd.services.sshd.wantedBy = mkForce [ "multi-user.target" ];
}
{
- krebs.iptables = {
+ networking.firewall = {
enable = true;
- tables = {
- filter.INPUT.policy = "DROP";
- filter.FORWARD.policy = "DROP";
- filter.INPUT.rules = [
- { predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; precedence = 10001; }
- { predicate = "-p icmp"; target = "ACCEPT"; precedence = 10000; }
- { predicate = "-i lo"; target = "ACCEPT"; precedence = 9999; }
- { predicate = "-p tcp --dport 22"; target = "ACCEPT"; precedence = 9998; }
- { predicate = "-p tcp -i retiolum"; target = "REJECT --reject-with tcp-reset"; precedence = -10000; }
- { predicate = "-p udp -i retiolum"; target = "REJECT --reject-with icmp-port-unreachable"; v6 = false; precedence = -10000; }
- { predicate = "-i retiolum"; target = "REJECT --reject-with icmp-proto-unreachable"; v6 = false; precedence = -10000; }
- ];
- };
+ allowedTCPPorts = [ 22 ];
};
}
{
krebs.hidden-ssh.enable = true;
}
+ {
+ services.xserver = {
+ enable = true;
+ #videoDrivers = mkForce [ "ati_unfree" ];
+
+ desktopManager.xterm.enable = false;
+ desktopManager.default = "none";
+ displayManager.lightdm.enable = true;
+ displayManager.lightdm.autoLogin = {
+ enable = true;
+ user = "lass";
+ };
+ windowManager.default = "xmonad";
+ windowManager.session = [{
+ name = "xmonad";
+ start = ''
+ ${pkgs.xorg.xhost}/bin/xhost +LOCAL:
+ ${pkgs.xmonad-lass}/bin/xmonad &
+ waitPID=$!
+ '';
+ }];
+
+ layout = "us";
+ xkbModel = "evdev";
+ xkbVariant = "altgr-intl";
+ xkbOptions = "caps:backspace";
+ };
+ }
];
}
diff --git a/lib/eval-source.nix b/lib/eval-source.nix
index 468fc92d1..ff853185b 100644
--- a/lib/eval-source.nix
+++ b/lib/eval-source.nix
@@ -10,6 +10,12 @@ let
};
};
};
+ sanitize = x: getAttr (typeOf x) {
+ set = mapAttrs
+ (const sanitize)
+ (filterAttrs (name: value: name != "_module" && value != null) x);
+ string = x;
+ };
in
# This function's return value can be used as pkgs.populate input.
- _file: source: (eval _file source).config.source
+ _file: source: sanitize (eval _file source).config.source
diff --git a/shell.nix b/shell.nix
index 5ea9ff3b7..2973d4c51 100644
--- a/shell.nix
+++ b/shell.nix
@@ -2,6 +2,10 @@ let
lib = import ./lib;
pkgs = import <nixpkgs> { overlays = [(import ./krebs/5pkgs)]; };
+ #
+ # high level commands
+ #
+
# usage: deploy [--user=USER] --system=SYSTEM [--target=TARGET]
cmds.deploy = pkgs.writeDash "cmds.deploy" ''
set -efu
@@ -29,6 +33,69 @@ let
exec ${utils.build} config.system.build.toplevel
'';
+ #
+ # low level commands
+ #
+
+ # usage: get-source SOURCE_FILE
+ cmds.get-source = pkgs.writeDash "cmds.get-source" ''
+ set -efu
+ exec ${pkgs.nix}/bin/nix-instantiate \
+ --eval \
+ --json \
+ --readonly-mode \
+ --show-trace \
+ --strict \
+ "$1"
+ '';
+
+ # usage: parse-target [--default=TARGET] TARGET
+ # TARGET = [USER@]HOST[:PORT][/PATH]
+ cmds.parse-target = pkgs.writeDash "cmds.parse-target" ''
+ set -efu
+ args=$(${pkgs.utillinux}/bin/getopt -n "$0" -s sh \
+ -o d: \
+ -l default: \
+ -- "$@")
+ if \test $? != 0; then exit 1; fi
+ eval set -- "$args"
+ default_target=
+ while :; do case $1 in
+ -d|--default) default_target=$2; shift 2;;
+ --) shift; break;;
+ esac; done
+ target=$1; shift
+ for arg; do echo "$0: bad argument: $arg" >&2; done
+ if \test $# != 0; then exit 2; fi
+ exec ${pkgs.jq}/bin/jq \
+ -enr \
+ --arg default_target "$default_target" \
+ --arg target "$target" \
+ -f ${pkgs.writeText "cmds.parse-target.jq" ''
+ def parse: match("^(?:([^@]+)@)?([^:/]+)?(?::([0-9]+))?(/.*)?$") | {
+ user: .captures[0].string,
+ host: .captures[1].string,
+ port: .captures[2].string,
+ path: .captures[3].string,
+ };
+ def sanitize: with_entries(select(.value != null));
+ ($default_target | parse) + ($target | parse | sanitize) |
+ . + { local: (.user == env.LOGNAME and .host == env.HOSTNAME) }
+ ''}
+ '';
+
+ # usage: quote [ARGS...]
+ cmds.quote = pkgs.writeDash "cmds.quote" ''
+ set -efu
+ prefix=
+ for x; do
+ y=$(${pkgs.jq}/bin/jq -nr --arg x "$x" '$x | @sh "\(.)"')
+ echo -n "$prefix$y"
+ prefix=' '
+ done
+ echo
+ '';
+
init.args = pkgs.writeText "init.args" /* sh */ ''
args=$(${pkgs.utillinux}/bin/getopt -n "$command" -s sh \
-o s:t:u: \
@@ -54,7 +121,9 @@ let
export target
export user
- export target_object="$(${init.env.parsetarget} $target)"
+ default_target=root@$system:22/var/src
+
+ export target_object="$(parse-target "$target" -d "$default_target")"
export target_user="$(echo $target_object | ${pkgs.jq}/bin/jq -r .user)"
export target_host="$(echo $target_object | ${pkgs.jq}/bin/jq -r .host)"
export target_port="$(echo $target_object | ${pkgs.jq}/bin/jq -r .port)"
@@ -68,35 +137,9 @@ let
fi
fi
'' // {
- parsetarget = pkgs.writeDash "init.env.parsetarget" ''
- set -efu
- exec ${pkgs.jq}/bin/jq \
- -enr \
- --arg target "$1" \
- -f ${init.env.parsetarget.jq}
- '' // {
- jq = pkgs.writeText "init.env.parsetarget.jq" ''
- def when(c; f): if c then f else . end;
- def capturesDef(i; v): .captures[i].string | when(. == null; v);
- $target | match("^(?:([^@]+)@)?([^:/]+)?(?::([0-9]+))?(/.*)?$") | {
- user: capturesDef(0; "root"),
- host: capturesDef(1; env.system),
- port: capturesDef(2; "22"),
- path: capturesDef(3; "/var/src"),
- } | . + {
- local: (.user == env.LOGNAME and .host == env.HOSTNAME),
- }
- '';
- };
populate = pkgs.writeDash "init.env.populate" ''
set -efu
- _source=$(${pkgs.nix}/bin/nix-instantiate \
- --eval \
- --json \
- --readonly-mode \
- --show-trace \
- --strict \
- "$source")
+ _source=$(get-source "$source")
echo $_source |
${pkgs.populate}/bin/populate \
"$target_user@$target_host:$target_port$target_path" \
@@ -105,21 +148,17 @@ let
'';
proxy = pkgs.writeDash "init.env.proxy" ''
set -efu
- q() {
- ${pkgs.jq}/bin/jq -nr --arg x "$*" '$x | @sh "\(.)"'
- }
exec ${pkgs.openssh}/bin/ssh \
"$target_user@$target_host" -p "$target_port" \
cd "$target_path/stockholm" \; \
- NIX_PATH=$(q "$target_path") \
- STOCKHOLM_VERSION=$STOCKHOLM_VERSION \
- nix-shell \
- --run $(q \
- system=$system \
- target=$target \
- using_proxy=true \
- "$*"
- )
+ NIX_PATH=$(quote "$target_path") \
+ STOCKHOLM_VERSION=$(quote "$STOCKHOLM_VERSION") \
+ nix-shell --run "$(quote "
+ system=$(quote "$system") \
+ target=$(quote "$target") \
+ using_proxy=true \
+ $(quote "$@")
+ ")"
'';
};
@@ -162,7 +201,8 @@ let
in pkgs.stdenv.mkDerivation {
name = "stockholm";
shellHook = /* sh */ ''
- export NIX_PATH="stockholm=$PWD''${NIX_PATH+:$NIX_PATH}"
+ export NIX_PATH=stockholm=$PWD:nixpkgs=${toString <nixpkgs>}
+ export NIX_REMOTE=daemon
export PATH=${lib.makeBinPath [
shell.cmdspkg
]}
diff --git a/tv/1systems/caxi/config.nix b/tv/1systems/caxi/config.nix
deleted file mode 100644
index b136d1ade..000000000
--- a/tv/1systems/caxi/config.nix
+++ /dev/null
@@ -1,25 +0,0 @@
-{ config, ... }:
-
-with import <stockholm/lib>;
-
-{
- krebs.build.host = config.krebs.hosts.caxi;
-
- imports = [
- <stockholm/tv>
- <stockholm/tv/2configs/hw/CAC-Developer-1.nix>
- <stockholm/tv/2configs/fs/CAC-CentOS-7-64bit.nix>
- <stockholm/tv/2configs/retiolum.nix>
- ];
-
- networking = let
- inherit (config.krebs.build.host.nets.internet) ip4;
- in {
- interfaces.enp2s1.ip4 = singleton {
- address = ip4.addr;
- prefixLength = fromJSON (head (match ".*/([0-9]+)" ip4.prefix));
- };
- defaultGateway = head (match "([^/]*)\.0/[0-9]+" ip4.prefix) + ".1";
- nameservers = ["8.8.8.8"];
- };
-}
diff --git a/tv/1systems/caxi/source.nix b/tv/1systems/caxi/source.nix
deleted file mode 100644
index bc875b768..000000000
--- a/tv/1systems/caxi/source.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-import <stockholm/tv/source.nix> {
- name = "caxi";
-}
diff --git a/tv/2configs/nginx/krebs-pages.nix b/tv/2configs/nginx/krebs-pages.nix
new file mode 100644
index 000000000..4dd643db7
--- /dev/null
+++ b/tv/2configs/nginx/krebs-pages.nix
@@ -0,0 +1,13 @@
+{ config, pkgs, ... }:
+{
+ services.nginx = {
+ virtualHosts.krebs-pages = {
+ serverAliases = [
+ "krebs.${config.krebs.build.host.name}.r"
+ ];
+ extraConfig = ''
+ root ${pkgs.krebs-pages};
+ '';
+ };
+ };
+}
diff --git a/tv/2configs/vim.nix b/tv/2configs/vim.nix
index 7849b6f2d..f0b1cf520 100644
--- a/tv/2configs/vim.nix
+++ b/tv/2configs/vim.nix
@@ -230,6 +230,7 @@ let {
''write\(Ba\|Da\)sh[^ \t\r\n]*[ \t\r\n]*"[^"]*"''
''[a-z]*Phase[ \t\r\n]*=''
];
+ yaml = {};
vim.extraStart =
''write[^ \t\r\n]*[ \t\r\n]*"\(\([^"]*\.\)\?vimrc\|[^"]*\.vim\)"'';
xdefaults = {};
diff --git a/tv/5pkgs/default.nix b/tv/5pkgs/default.nix
index 02410e8e6..8a7a613ba 100644
--- a/tv/5pkgs/default.nix
+++ b/tv/5pkgs/default.nix
@@ -1,22 +1,18 @@
with import <stockholm/lib>;
-self: super: let
- # This callPackage will try to detect obsolete overrides.
- callPackage = path: args: let
- override = super.callPackage path args;
- upstream = optionalAttrs (override ? "name")
- (super.${(parseDrvName override.name).name} or {});
- in if upstream ? "name" &&
- override ? "name" &&
- compareVersions upstream.name override.name != -1
- then
- trace
- "Upstream `${upstream.name}' gets overridden by `${override.name}'."
- override
- else override;
+self: super:
-in {
+# Import files and subdirectories like they are overlays.
+foldl' mergeAttrs {}
+ (map
+ (name: import (./. + "/${name}") self super)
+ (filter
+ (name: name != "default.nix" && !hasPrefix "." name)
+ (attrNames (readDir ./.))))
+//
+
+{
# TODO use XDG_RUNTIME_DIR?
cr = self.writeDashBin "cr" ''
set -efu
@@ -42,9 +38,4 @@ in {
sha256 = "1as1i0j9d2n3iap9b471y4x01561r2s3vmjc5281qinirlr4al73";
}) {};
in nixpkgs-1509.wvdial;
-
}
-
-// mapAttrs (_: flip callPackage {})
- (filterAttrs (_: dir: pathExists (dir + "/default.nix"))
- (subdirsOf ./.))
diff --git a/tv/5pkgs/simple/default.nix b/tv/5pkgs/simple/default.nix
new file mode 100644
index 000000000..1b9d8c235
--- /dev/null
+++ b/tv/5pkgs/simple/default.nix
@@ -0,0 +1,24 @@
+with import <stockholm/lib>;
+
+self: super:
+
+let
+ # This callPackage will try to detect obsolete overrides.
+ callPackage = path: args: let
+ override = self.callPackage path args;
+ upstream = optionalAttrs (override ? "name")
+ (super.${(parseDrvName override.name).name} or {});
+ in if upstream ? "name" &&
+ override ? "name" &&
+ compareVersions upstream.name override.name != -1
+ then trace "Upstream `${upstream.name}' gets overridden by `${override.name}'." override
+ else override;
+in
+
+ listToAttrs
+ (map
+ (name: nameValuePair (removeSuffix ".nix" name)
+ (callPackage (./. + "/${name}") {}))
+ (filter
+ (name: name != "default.nix" && !hasPrefix "." name)
+ (attrNames (readDir ./.))))
diff --git a/tv/5pkgs/djbdns/default.nix b/tv/5pkgs/simple/djbdns/default.nix
index ad5a530bd..ad5a530bd 100644
--- a/tv/5pkgs/djbdns/default.nix
+++ b/tv/5pkgs/simple/djbdns/default.nix
diff --git a/tv/5pkgs/q/default.nix b/tv/5pkgs/simple/q/default.nix
index 2e7aa5cf2..2e7aa5cf2 100644
--- a/tv/5pkgs/q/default.nix
+++ b/tv/5pkgs/simple/q/default.nix
diff --git a/tv/5pkgs/viljetic-pages/default.nix b/tv/5pkgs/simple/viljetic-pages/default.nix
index 1ae55cca7..1ae55cca7 100644
--- a/tv/5pkgs/viljetic-pages/default.nix
+++ b/tv/5pkgs/simple/viljetic-pages/default.nix
diff --git a/tv/5pkgs/viljetic-pages/index.html b/tv/5pkgs/simple/viljetic-pages/index.html
index c06b3f97b..c06b3f97b 100644
--- a/tv/5pkgs/viljetic-pages/index.html
+++ b/tv/5pkgs/simple/viljetic-pages/index.html
diff --git a/tv/5pkgs/viljetic-pages/logo.xpm b/tv/5pkgs/simple/viljetic-pages/logo.xpm
index bb263dad9..bb263dad9 100644
--- a/tv/5pkgs/viljetic-pages/logo.xpm
+++ b/tv/5pkgs/simple/viljetic-pages/logo.xpm
diff --git a/tv/5pkgs/xmonad-tv/default.nix b/tv/5pkgs/simple/xmonad-tv/default.nix
index 5ac8f8372..5ac8f8372 100644
--- a/tv/5pkgs/xmonad-tv/default.nix
+++ b/tv/5pkgs/simple/xmonad-tv/default.nix