summaryrefslogtreecommitdiffstats
path: root/configs
diff options
context:
space:
mode:
Diffstat (limited to 'configs')
-rw-r--r--configs/autotether.nix19
-rw-r--r--configs/backup.nix108
-rw-r--r--configs/bash/default.nix66
-rw-r--r--configs/binary-cache/default.nix28
-rw-r--r--configs/br.nix49
-rw-r--r--configs/default.nix131
-rw-r--r--configs/elm-packages-proxy.nix359
-rw-r--r--configs/exim-retiolum.nix8
-rw-r--r--configs/exim-smarthost.nix45
-rw-r--r--configs/fs/CAC-CentOS-7-64bit.nix20
-rw-r--r--configs/gitconfig.nix15
-rw-r--r--configs/gitrepos.nix237
-rw-r--r--configs/htop.nix39
-rw-r--r--configs/hw/AO753.nix47
-rw-r--r--configs/hw/winmax2.nix48
-rw-r--r--configs/hw/x220.nix88
-rw-r--r--configs/imgur.nix21
-rw-r--r--configs/initrd/sshd.nix17
-rw-r--r--configs/mail-client.nix9
-rw-r--r--configs/man.nix13
-rw-r--r--configs/nets/hkw.nix68
-rw-r--r--configs/networkd.nix4
-rw-r--r--configs/nginx/default.nix21
-rw-r--r--configs/nginx/public_html.nix17
-rw-r--r--configs/nix.nix9
-rw-r--r--configs/pki/certs/tv.crt31
-rw-r--r--configs/pki/default.nix67
-rw-r--r--configs/ppp.nix85
-rw-r--r--configs/pulse.nix119
-rw-r--r--configs/repo-sync/wiki.nix39
-rw-r--r--configs/retiolum.nix26
-rw-r--r--configs/smartd.nix17
-rw-r--r--configs/ssh.nix21
-rw-r--r--configs/sshd.nix26
-rw-r--r--configs/urlwatch.nix118
-rw-r--r--configs/vim.nix184
-rw-r--r--configs/weechat-server.nix24
-rw-r--r--configs/wiregrill.nix36
-rw-r--r--configs/xdg.nix10
-rw-r--r--configs/xserver/Xmodmap.nix28
-rw-r--r--configs/xserver/default.nix166
-rw-r--r--configs/xserver/sxiv.nix11
-rw-r--r--configs/xserver/urxvt.nix72
-rw-r--r--configs/xserver/xkiller.nix14
-rw-r--r--configs/xserver/xserver.conf.nix38
-rw-r--r--configs/xsessions/default.nix5
-rw-r--r--configs/xsessions/urxvtd.nix15
47 files changed, 2638 insertions, 0 deletions
diff --git a/configs/autotether.nix b/configs/autotether.nix
new file mode 100644
index 0000000..43b5575
--- /dev/null
+++ b/configs/autotether.nix
@@ -0,0 +1,19 @@
+{ config, pkgs, ... }: let
+ cfg.serial = "17e064850405";
+in {
+ systemd.services.usb_tether.serviceConfig = {
+ SyslogIdentifier = "usb_tether";
+ ExecStartPre = "${pkgs.android-tools}/bin/adb -s ${cfg.serial} wait-for-device";
+ ExecStart = "${pkgs.android-tools}/bin/adb -s ${cfg.serial} shell svc usb setFunctions rndis";
+ };
+ services.udev.extraRules = /* sh */ ''
+ ACTION=="add", SUBSYSTEM=="net", KERNEL=="usb*", NAME="android"
+
+ ACTION=="add", SUBSYSTEM=="usb", ATTR{serial}=="${cfg.serial}", \
+ TAG+="systemd", ENV{SYSTEMD_WANTS}="usb_tether.service"
+ '';
+ systemd.network.networks.android = {
+ matchConfig.Name = "android";
+ DHCP = "yes";
+ };
+}
diff --git a/configs/backup.nix b/configs/backup.nix
new file mode 100644
index 0000000..30d6011
--- /dev/null
+++ b/configs/backup.nix
@@ -0,0 +1,108 @@
+{ config, lib, mylib, pkgs, ... }: {
+ krebs.backup.plans = {
+ } // lib.mapAttrs (_: lib.recursiveUpdate {
+ snapshots = {
+ daily = { format = "%Y-%m-%d"; retain = 7; };
+ weekly = { format = "%YW%W"; retain = 4; };
+ monthly = { format = "%Y-%m"; retain = 12; };
+ yearly = { format = "%Y"; };
+ };
+ }) {
+ bu-home-xu = {
+ method = "push";
+ src = { host = config.krebs.hosts.bu; path = "/home"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/bu-home"; };
+ startAt = "05:20";
+ };
+ bu-home-zu = {
+ method = "push";
+ src = { host = config.krebs.hosts.bu; path = "/home"; };
+ dst = { host = config.krebs.hosts.zu; path = "/bku/bu-home"; };
+ startAt = "05:25";
+ };
+ nomic-home-xu = {
+ method = "push";
+ src = { host = config.krebs.hosts.nomic; path = "/home"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/nomic-home"; };
+ startAt = "05:00";
+ };
+ nomic-home-zu = {
+ method = "push";
+ src = { host = config.krebs.hosts.nomic; path = "/home"; };
+ dst = { host = config.krebs.hosts.zu; path = "/bku/nomic-home"; };
+ startAt = "04:20";
+ };
+ nomic-pull-querel-home = {
+ method = "pull";
+ src = { host = config.krebs.hosts.querel; path = "/home"; };
+ dst = { host = config.krebs.hosts.nomic; path = "/fs/ponyhof/bku/querel-home"; };
+ startAt = "22:00";
+ };
+ xu-home-bu = {
+ method = "push";
+ src = { host = config.krebs.hosts.xu; path = "/home"; };
+ dst = { host = config.krebs.hosts.bu; path = "/bku/xu-home"; };
+ startAt = "04:50";
+ };
+ xu-home-nomic = {
+ method = "push";
+ src = { host = config.krebs.hosts.xu; path = "/home"; };
+ dst = { host = config.krebs.hosts.nomic; path = "/fs/cis3hG/bku/xu-home"; };
+ startAt = "05:20";
+ };
+ xu-home-zu = {
+ method = "push";
+ src = { host = config.krebs.hosts.xu; path = "/home"; };
+ dst = { host = config.krebs.hosts.zu; path = "/bku/xu-home"; };
+ startAt = "06:20";
+ };
+ xu-pull-ni-ejabberd = {
+ method = "pull";
+ src = { host = config.krebs.hosts.ni; path = "/var/lib/ejabberd"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/ni-ejabberd"; };
+ startAt = "07:00";
+ };
+ xu-pull-ni-home = {
+ method = "pull";
+ src = { host = config.krebs.hosts.ni; path = "/home"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/ni-home"; };
+ startAt = "07:00";
+ };
+ zu-home-xu = {
+ method = "push";
+ src = { host = config.krebs.hosts.zu; path = "/home"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/zu-home"; };
+ startAt = "05:00";
+ };
+ zu-pull-ni-ejabberd = {
+ method = "pull";
+ src = { host = config.krebs.hosts.ni; path = "/var/lib/ejabberd"; };
+ dst = { host = config.krebs.hosts.zu; path = "/bku/ni-ejabberd"; };
+ startAt = "06:00";
+ };
+ zu-pull-ni-home = {
+ method = "pull";
+ src = { host = config.krebs.hosts.ni; path = "/home"; };
+ dst = { host = config.krebs.hosts.zu; path = "/bku/ni-home"; };
+ startAt = "06:30";
+ };
+ } // lib.mapAttrs (_: lib.recursiveUpdate {
+ snapshots = {
+ minutely = { format = "%Y-%m-%dT%H:%M"; retain = 3; };
+ hourly = { format = "%Y-%m-%dT%H"; retain = 3; };
+ daily = { format = "%Y-%m-%d"; retain = 3; };
+ };
+ startAt = null;
+ }) {
+ xu-test-push-xu = {
+ method = "push";
+ src = { host = config.krebs.hosts.xu; path = "/tmp/xu-bku-test-data"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/xu-test-push"; };
+ };
+ xu-test-pull-xu = {
+ method = "pull";
+ src = { host = config.krebs.hosts.xu; path = "/tmp/xu-bku-test-data"; };
+ dst = { host = config.krebs.hosts.xu; path = "/bku/xu-test-pull"; };
+ };
+ };
+}
diff --git a/configs/bash/default.nix b/configs/bash/default.nix
new file mode 100644
index 0000000..2e18d5b
--- /dev/null
+++ b/configs/bash/default.nix
@@ -0,0 +1,66 @@
+{ config, mylib, pkgs, ... }: {
+ programs.bash = {
+ interactiveShellInit = /* sh */ ''
+ HISTCONTROL='erasedups:ignorespace'
+ HISTSIZE=900001
+ HISTFILESIZE=$HISTSIZE
+ HISTTIMEFORMAT=
+
+ shopt -s checkhash
+ shopt -s histappend histreedit histverify
+ shopt -s no_empty_cmd_completion
+ complete -d cd
+
+ case $UID in
+ ${mylib.shell.escape (toString config.krebs.users.tv.uid)})
+ if test ''${SHLVL-1} = 1 && test -n "''${DISPLAY-}"; then
+ _CURRENT_DESKTOP_NAME=''${_CURRENT_DESKTOP_NAME-$(
+ ${pkgs.xorg.xprop}/bin/xprop -notype -root \
+ 32i _NET_CURRENT_DESKTOP \
+ 8s _NET_DESKTOP_NAMES \
+ |
+ ${pkgs.gnused}/bin/sed -r 's/.* = //;s/"//g;s/, /\a/g' |
+ {
+ read -r _NET_CURRENT_DESKTOP
+ IFS=$'\a' read -ra _NET_DESKTOP_NAMES
+ echo "''${_NET_DESKTOP_NAMES[$_NET_CURRENT_DESKTOP]}"
+ }
+ )}
+ case $_CURRENT_DESKTOP_NAME in
+ stockholm)
+ cd ~/stockholm
+ ;;
+ esac
+ fi
+
+ export NIX_PATH="stockholm=$HOME/stockholm:$NIX_PATH"
+ ;;
+ esac
+
+ ${pkgs.bash-fzf-history.bind}
+
+ if test -n "''${BASH_EXTRA_INIT-}"; then
+ . "$BASH_EXTRA_INIT"
+ fi
+ '';
+ promptInit = /* sh */ ''
+ case $UID in
+ 0)
+ PS1='\[\e[1;31m\]\w\[\e[0m\] '
+ ;;
+ ${toString config.krebs.build.user.uid})
+ PS1='\[\e[1;32m\]\w\[\e[0m\] '
+ ;;
+ *)
+ PS1='\[\e[1;35m\]\u \[\e[1;32m\]\w\[\e[0m\] '
+ ;;
+ esac
+ if test -n "$SSH_CLIENT"; then
+ PS1='\[\e[35m\]\h'" $PS1"
+ fi
+ if test -n "$SSH_AGENT_PID"; then
+ PS1="ssh-agent[$SSH_AGENT_PID] $PS1"
+ fi
+ '';
+ };
+}
diff --git a/configs/binary-cache/default.nix b/configs/binary-cache/default.nix
new file mode 100644
index 0000000..d9e87c7
--- /dev/null
+++ b/configs/binary-cache/default.nix
@@ -0,0 +1,28 @@
+{ config, pkgs, ... }: {
+ environment.etc."binary-cache.pubkey".text =
+ config.krebs.build.host.binary-cache.pubkey;
+
+ nixpkgs.overlays = [
+ (self: super: {
+ nix-serve = self.haskellPackages.nix-serve-ng;
+ })
+ ];
+
+ services.nix-serve = {
+ enable = true;
+ secretKeyFile = "${config.krebs.secret.directory}/nix-serve.key";
+ };
+
+ services.nginx = {
+ enable = true;
+ virtualHosts.nix-serve = {
+ serverAliases = [
+ "cache.${config.krebs.build.host.name}.hkw"
+ "cache.${config.krebs.build.host.name}.r"
+ ];
+ locations."/".extraConfig = ''
+ proxy_pass http://localhost:${toString config.services.nix-serve.port};
+ '';
+ };
+ };
+}
diff --git a/configs/br.nix b/configs/br.nix
new file mode 100644
index 0000000..b9bc70b
--- /dev/null
+++ b/configs/br.nix
@@ -0,0 +1,49 @@
+{ config, lib, modulesPath, mylib, pkgs, ... }: {
+
+ imports = [
+ (modulesPath + "/services/hardware/sane_extra_backends/brscan4.nix")
+ ];
+
+ krebs.nixpkgs.allowUnfreePredicate =
+ pkg: lib.any (mylib.eq (mylib.packageName pkg)) [
+ "brother-udev-rule-type1"
+ "brscan4"
+ "brscan4-etc-files"
+ "mfcl2700dnlpr"
+ ];
+
+ hardware.sane = {
+ enable = true;
+ brscan4 = {
+ enable = true;
+ netDevices = {
+ bra = {
+ model = "MFCL2700DN";
+ ip = "10.23.1.214";
+ };
+ };
+ };
+ };
+
+ services.saned.enable = true;
+
+ # usage: scanimage -d "$(find-scanner bra)" --batch --format=tiff --resolution 150 -x 211 -y 298
+ environment.systemPackages = [
+ (pkgs.writeDashBin "find-scanner" ''
+ set -efu
+ name=$1
+ ${pkgs.sane-backends}/bin/scanimage -f '%m %d
+ ' \
+ | ${pkgs.gawk}/bin/awk -v dev="*$name" '$1 == dev { print $2; exit }' \
+ | ${pkgs.gnugrep}/bin/grep .
+ '')
+ ];
+
+ services.printing = {
+ enable = true;
+ drivers = [
+ pkgs.mfcl2700dncupswrapper
+ ];
+ };
+
+}
diff --git a/configs/default.nix b/configs/default.nix
new file mode 100644
index 0000000..5d74d96
--- /dev/null
+++ b/configs/default.nix
@@ -0,0 +1,131 @@
+{ config, inputs, lib, mylib, pkgs, ... }: {
+ boot.tmpOnTmpfs = true;
+
+ krebs.enable = true;
+
+ krebs.build.user = config.krebs.users.tv;
+
+ networking.hostId = lib.mkDefault (mylib.hashToLength 8 config.networking.hostName);
+ networking.hostName = config.krebs.build.host.name;
+
+ imports = [
+ ./backup.nix
+ ./bash
+ ./htop.nix
+ ./nets/hkw.nix
+ ./networkd.nix
+ ./nginx
+ ./nix.nix
+ ./pki
+ ./ssh.nix
+ ./sshd.nix
+ ./vim.nix
+ ./xdg.nix
+ {
+ users = {
+ defaultUserShell = "/run/current-system/sw/bin/bash";
+ mutableUsers = false;
+ users = {
+ tv = {
+ inherit (config.krebs.users.tv) home uid;
+ isNormalUser = true;
+ extraGroups = [ "tv" ];
+ };
+ };
+ };
+ }
+ {
+ i18n.defaultLocale = lib.mkDefault "C.UTF-8";
+ security.sudo.extraConfig = ''
+ Defaults env_keep+="SSH_CLIENT _CURRENT_DESKTOP_NAME"
+ Defaults mailto="${config.krebs.users.tv.mail}"
+ Defaults !lecture
+ '';
+ time.timeZone = "Europe/Berlin";
+ }
+
+ {
+ nixpkgs.config.allowUnfree = false;
+ }
+ {
+ environment.homeBinInPath = true;
+
+ environment.profileRelativeEnvVars.PATH = lib.mkForce [ "/bin" ];
+
+ environment.systemPackages = with pkgs; [
+ rxvt_unicode.terminfo
+ ];
+
+ environment.shellAliases = lib.mkForce {
+ gp = "${pkgs.pari}/bin/gp -q";
+ df = "df -h";
+ du = "du -h";
+
+ # TODO alias cannot contain #\'
+ # "ps?" = "ps ax | head -n 1;ps ax | fgrep -v ' grep --color=auto ' | grep";
+
+ ls = "ls -h --color=auto --group-directories-first";
+ dmesg = "dmesg -L --reltime";
+ view = "vim -R";
+ };
+
+ environment.variables = {
+ NIX_PATH = lib.mkForce (lib.concatStringsSep ":" [
+ "secrets=/var/src/stockholm/null"
+ "/var/src"
+ ]);
+ };
+ }
+
+ {
+ services.cron.enable = false;
+ services.ntp.enable = false;
+ services.timesyncd.enable = true;
+ }
+
+ {
+ boot.kernel.sysctl = {
+ # Enable IPv6 Privacy Extensions
+ #
+ # XXX use mkForce here because since NixOS 21.11 there's a collision in
+ # net.ipv6.conf.default.use_tempaddr, and boot.kernel.sysctl incapable
+ # of merging.
+ #
+ # XXX net.ipv6.conf.all.use_tempaddr is set because it was mentioned in
+ # https://tldp.org/HOWTO/Linux+IPv6-HOWTO/ch06s05.html
+ # TODO check if that is really necessary, otherwise we can rely solely
+ # on networking.tempAddresses in the future (when nothing is <21.11)
+ "net.ipv6.conf.all.use_tempaddr" = lib.mkForce 2;
+ "net.ipv6.conf.default.use_tempaddr" = lib.mkForce 2;
+ };
+ }
+
+ {
+ tv.iptables.enable = true;
+ tv.iptables.accept-echo-request = "internet";
+ }
+
+ {
+ services.journald.extraConfig = ''
+ SystemMaxUse=1G
+ RuntimeMaxUse=128M
+ '';
+ }
+
+ {
+ environment.systemPackages = [
+ pkgs.field
+ pkgs.get
+ pkgs.git
+ pkgs.git-crypt
+ pkgs.git-preview
+ pkgs.hashPassword
+ pkgs.htop
+ pkgs.kpaste
+ pkgs.nix-prefetch-scripts
+ pkgs.ovh-zone
+ pkgs.push
+ ];
+ }
+ ];
+}
diff --git a/configs/elm-packages-proxy.nix b/configs/elm-packages-proxy.nix
new file mode 100644
index 0000000..caea188
--- /dev/null
+++ b/configs/elm-packages-proxy.nix
@@ -0,0 +1,359 @@
+{ config, lib, pkgs, ... }: let
+
+ cfg.nameserver = "1.1.1.1";
+ cfg.packageDir = "/var/lib/elm-packages";
+ cfg.port = 7782;
+
+ # TODO secret files
+ cfg.htpasswd = "/var/lib/certs/package.elm-lang.org/htpasswd";
+ cfg.sslCertificate = "/var/lib/certs/package.elm-lang.org/fullchain.pem";
+ cfg.sslCertificateKey = "/var/lib/certs/package.elm-lang.org/key.pem";
+
+ semverRegex =
+ "(?<major>0|[1-9]\\d*)\\.(?<minor>0|[1-9]\\d*)\\.(?<patch>0|[1-9]\\d*)(?:-(?<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?";
+
+in {
+ services.nginx.virtualHosts."package.elm-lang.org" = {
+ addSSL = true;
+
+ sslCertificate = cfg.sslCertificate;
+ sslCertificateKey = cfg.sslCertificateKey;
+
+ locations."/all-packages".extraConfig = ''
+ proxy_pass http://127.0.0.1:${toString config.krebs.htgen.elm-packages-proxy.port};
+ proxy_pass_header Server;
+ '';
+
+ locations."/all-packages/since/".extraConfig = ''
+ proxy_pass http://127.0.0.1:${toString config.krebs.htgen.elm-packages-proxy.port};
+ proxy_pass_header Server;
+ '';
+
+ locations."~ ^/packages/(?<author>[A-Za-z0-9-]+)/(?<pname>[A-Za-z0-9-]+)/(?<version>${semverRegex})\$".extraConfig = ''
+ auth_basic "Restricted Area";
+ auth_basic_user_file ${cfg.htpasswd};
+
+ proxy_set_header X-User $remote_user;
+ proxy_set_header X-Author $author;
+ proxy_set_header X-Package $pname;
+ proxy_set_header X-Version $version;
+ proxy_pass_header Server;
+
+ proxy_pass http://127.0.0.1:${toString config.krebs.htgen.elm-packages-proxy.port};
+ '';
+
+ locations."~ ^/packages/(?<author>[A-Za-z0-9-]+)/(?<pname>[A-Za-z0-9-]+)/(?<version>${semverRegex})/(?:zipball|elm.json|endpoint.json)\$".extraConfig = ''
+ set $zipball "${cfg.packageDir}/$author/$pname/$version/zipball";
+ proxy_set_header X-Author $author;
+ proxy_set_header X-Package $pname;
+ proxy_set_header X-Version $version;
+ proxy_set_header X-Zipball $zipball;
+ proxy_pass_header Server;
+ resolver ${cfg.nameserver};
+
+ if (-f $zipball) {
+ set $new_uri http://127.0.0.1:${toString config.krebs.htgen.elm-packages-proxy.port};
+ }
+ if (!-f $zipball) {
+ set $new_uri https://package.elm-lang.org$request_uri;
+ }
+
+ proxy_pass $new_uri;
+ '';
+
+ locations."/search.json".extraConfig = ''
+ proxy_pass http://127.0.0.1:${toString config.krebs.htgen.elm-packages-proxy.port};
+ proxy_pass_header Server;
+ '';
+ };
+
+ krebs.htgen.elm-packages-proxy = {
+ port = cfg.port;
+ script = /* sh */ ''. ${pkgs.writeDash "elm-packages-proxy.sh" ''
+ PATH=${lib.makeBinPath [
+ pkgs.attr
+ pkgs.coreutils
+ pkgs.curl
+ pkgs.findutils
+ pkgs.gnugrep
+ pkgs.jq
+ pkgs.p7zip
+ ]}
+ export PATH
+ file_response() {(
+ status_code=$1
+ status_reason=$2
+ file=$3
+ content_type=$4
+
+ content_length=$(wc -c "$file" | cut -d\ -f1)
+
+ printf "HTTP/1.1 $status_code $status_reason\r\n"
+ printf 'Connection: close\r\n'
+ printf 'Content-Length: %d\r\n' "$content_length"
+ printf 'Content-Type: %s\r\n' "$content_type"
+ printf 'Server: %s\r\n' "$Server"
+ printf '\r\n'
+ cat "$file"
+ )}
+ string_response() {(
+ status_code=$1
+ status_reason=$2
+ response_body=$3
+ content_type=$4
+
+ printf "HTTP/1.1 $status_code $status_reason\r\n"
+ printf 'Connection: close\r\n'
+ printf 'Content-Length: %d\r\n' "$(expr ''${#response_body} + 1)"
+ printf 'Content-Type: %s\r\n' "$content_type"
+ printf 'Server: %s\r\n' "$Server"
+ printf '\r\n'
+ printf '%s\n' "$response_body"
+ )}
+
+ case "$Method $Request_URI" in
+ 'GET /packages/'*)
+
+ author=$req_x_author
+ pname=$req_x_package
+ version=$req_x_version
+
+ zipball=${cfg.packageDir}/$author/$pname/$version/zipball
+ elmjson=$HOME/cache/$author%2F$pname%2F$version%2Felm.json
+ endpointjson=$HOME/cache/$author%2F$pname%2F$version%2Fendpoint.json
+ mkdir -p "$HOME/cache"
+
+ case $(basename $Request_URI) in
+ zipball)
+ file_response 200 OK "$zipball" application/zip
+ exit
+ ;;
+ elm.json)
+ if ! test -f "$elmjson"; then
+ 7z x -so "$zipball" \*/elm.json > "$elmjson"
+ fi
+ file_response 200 OK "$elmjson" 'application/json; charset=UTF-8'
+ exit
+ ;;
+ endpoint.json)
+ if ! test -f "$endpointjson"; then
+ hash=$(sha1sum "$zipball" | cut -d\ -f1)
+ url=https://package.elm-lang.org/packages/$author/$pname/$version/zipball
+ jq -n \
+ --arg hash "$hash" \
+ --arg url "$url" \
+ '{ $hash, $url }' \
+ > "$endpointjson"
+ fi
+ file_response 200 OK "$endpointjson" 'application/json; charset=UTF-8'
+ exit
+ ;;
+ esac
+ ;;
+ 'POST /packages/'*)
+
+ author=$req_x_author
+ pname=$req_x_package
+ user=$req_x_user
+ version=$req_x_version
+
+ action=uploading
+ force=''${req_x_force-false}
+ zipball=${cfg.packageDir}/$author/$pname/$version/zipball
+ elmjson=$HOME/cache/$author%2F$pname%2F$version%2Felm.json
+ endpointjson=$HOME/cache/$author%2F$pname%2F$version%2Fendpoint.json
+
+ if test -e "$zipball"; then
+ if test "$force" = true; then
+ zipball_owner=$(attr -q -g X-User "$zipball" || :)
+ if test "$zipball_owner" = "$req_x_user"; then
+ action=replacing
+ rm -f "$elmjson"
+ rm -f "$endpointjson"
+ else
+ string_response 403 Forbidden \
+ "package already exists: $author/$pname@$version" \
+ text/plain
+ exit
+ fi
+ else
+ string_response 409 Conflict \
+ "package already exists: $author/$pname@$version" \
+ text/plain
+ exit
+ fi
+ fi
+
+ echo "user $user is $action package $author/$pname@$version" >&2
+ # TODO check package
+ mkdir -p "$(dirname "$zipball")"
+ head -c $req_content_length > "$zipball"
+
+ attr -q -s X-User -V "$user" "$zipball" || :
+
+ string_response 200 OK \
+ "package created: $author/$pname@$version" \
+ text/plain
+
+ exit
+ ;;
+ 'DELETE /packages/'*)
+
+ author=$req_x_author
+ pname=$req_x_package
+ user=$req_x_user
+ version=$req_x_version
+
+ zipball=${cfg.packageDir}/$author/$pname/$version/zipball
+ elmjson=$HOME/cache/$author%2F$pname%2F$version%2Felm.json
+ endpointjson=$HOME/cache/$author%2F$pname%2F$version%2Fendpoint.json
+
+ if test -e "$zipball"; then
+ zipball_owner=$(attr -q -g X-User "$zipball" || :)
+ if test "$zipball_owner" = "$req_x_user"; then
+ echo "user $user is deleting package $author/$pname@$version" >&2
+ rm -f "$elmjson"
+ rm -f "$endpointjson"
+ rm "$zipball"
+ string_response 200 OK \
+ "package deleted: $author/$pname@$version" \
+ text/plain
+ exit
+ else
+ string_response 403 Forbidden \
+ "package already exists: $author/$pname@$version" \
+ text/plain
+ exit
+ fi
+ fi
+ ;;
+ 'GET /all-packages'|'POST /all-packages')
+
+ response=$(mktemp -t htgen.$$.elm-packages-proxy.all-packages.XXXXXXXX)
+ trap "rm $response >&2" EXIT
+
+ {
+ # upstream packages
+ curl -fsS https://package.elm-lang.org"$Request_URI"
+
+ # private packages
+ (cd ${cfg.packageDir}; find -mindepth 3 -maxdepth 3) |
+ jq -Rs '
+ split("\n") |
+ map(
+ select(.!="") |
+ match("^\\./(?<author>[^/]+)/(?<pname>[^/]+)/(?<version>[^/]+)$").captures |
+ map({key:.name,value:.string}) |
+ from_entries
+ ) |
+ reduce .[] as $item ({};
+ ($item|"\(.author)/\(.pname)") as $name |
+ . + { "\($name)": ((.[$name] // []) + [$item.version]) }
+ )
+ '
+ } |
+ jq -cs add > $response
+
+ file_response 200 OK "$response" 'application/json; charset=UTF-8'
+ exit
+ ;;
+ 'GET /all-packages/since/'*|'POST /all-packages/since/'*)
+
+ response=$(mktemp -t htgen.$$.elm-packages-proxy.all-packages.XXXXXXXX)
+ trap "rm $response >&2" EXIT
+
+ {
+ # upstream packages
+ curl -fsS https://package.elm-lang.org"$Request_URI"
+
+ # private packages
+ (cd ${cfg.packageDir}; find -mindepth 3 -maxdepth 3) |
+ jq -Rs '
+ split("\n") |
+ map(
+ select(.!="") |
+ sub("^\\./(?<author>[^/]+)/(?<pname>[^/]+)/(?<version>[^/]+)$";"\(.author)/\(.pname)@\(.version)")
+ ) |
+ sort_by(split("@") | [.[0]]+(.[1]|split(".")|map(tonumber))) |
+ reverse
+ '
+ } |
+ jq -cs add > $response
+
+ file_response 200 OK "$response" 'application/json; charset=UTF-8'
+ exit
+ ;;
+ 'GET /search.json')
+
+ searchjson=$HOME/cache/search.json
+ mkdir -p "$HOME/cache"
+
+ # update cached search.json
+ (
+ last_modified=$(
+ if test -f "$searchjson"; then
+ date -Rr "$searchjson"
+ else
+ date -R -d @0
+ fi
+ )
+ tempsearchjson=$(mktemp "$searchjson.XXXXXXXX")
+ trap 'rm "$tempsearchjson" >&2' EXIT
+ curl -fsS --compressed https://package.elm-lang.org/search.json \
+ -H "If-Modified-Since: $last_modified" \
+ -o "$tempsearchjson"
+ if test -s "$tempsearchjson"; then
+ mv "$tempsearchjson" "$searchjson"
+ trap - EXIT
+ fi
+ )
+
+ response=$(mktemp -t htgen.$$.elm-packages-proxy.search.XXXXXXXX)
+ trap 'rm "$response" >&2' EXIT
+
+ {
+ printf '{"upstream":'; cat "$searchjson"
+ printf ',"private":'; (cd ${cfg.packageDir}; find -mindepth 3 -maxdepth 3) |
+ jq -Rs '
+ split("\n") |
+ map(
+ select(.!="") |
+ match("^\\./(?<author>[^/]+)/(?<pname>[^/]+)/(?<version>[^/]+)$").captures |
+ map({key:.name,value:.string}) |
+ from_entries
+ ) |
+ map({
+ key: "\(.author)/\(.pname)",
+ value: .version,
+ }) |
+ from_entries
+ '
+ printf '}'
+ } |
+ jq -c '
+ reduce .upstream[] as $upstreamItem ({ private, output: [] };
+ .private[$upstreamItem.name] as $privateItem |
+ if $privateItem then
+ .output += [$upstreamItem * { version: $privateItem.version }] |
+ .private |= del(.[$upstreamItem.name])
+ else
+ .output += [$upstreamItem]
+ end
+ ) |
+
+ .output + (.private | to_entries | sort_by(.key) | map({
+ name: .key,
+ version: .value,
+ summary: "dummy summary",
+ license: "dummy license",
+ }))
+ ' \
+ > $response
+
+ file_response 200 OK "$response" 'application/json; charset=UTF-8'
+ exit
+ ;;
+ esac
+ ''}'';
+ };
+}
diff --git a/configs/exim-retiolum.nix b/configs/exim-retiolum.nix
new file mode 100644
index 0000000..7903ac3
--- /dev/null
+++ b/configs/exim-retiolum.nix
@@ -0,0 +1,8 @@
+{ config, pkgs, ... }: {
+ environment.systemPackages = [
+ pkgs.eximlog
+ ];
+ krebs.exim-retiolum.enable = true;
+ krebs.exim-retiolum.rspamd.enable = config.krebs.build.host.name == "nomic";
+ tv.iptables.input-retiolum-accept-tcp = [ "smtp" ];
+}
diff --git a/configs/exim-smarthost.nix b/configs/exim-smarthost.nix
new file mode 100644
index 0000000..d983165
--- /dev/null
+++ b/configs/exim-smarthost.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }: {
+ environment.systemPackages = [
+ pkgs.eximlog
+ ];
+ krebs.exim-smarthost = {
+ enable = true;
+ dkim = [
+ { domain = "viljetic.de"; }
+ ];
+ sender_domains = [
+ "krebsco.de"
+ "shackspace.de"
+ "viljetic.de"
+ ];
+ relay_from_hosts = lib.concatMap (host: host.nets.retiolum.addrs) [
+ config.krebs.hosts.nomic
+ config.krebs.hosts.xu
+ ];
+ internet-aliases = with config.krebs.users; [
+ { from = "bku-eppler@viljetic.de"; to = tv.mail; }
+ { from = "postmaster@viljetic.de"; to = tv.mail; } # RFC 822
+ { from = "mirko@viljetic.de"; to = mv-ni.mail; }
+ { from = "tomislav@viljetic.de"; to = tv.mail; }
+ { from = "tv@viljetic.de"; to = tv.mail; }
+ { from = "tv@shackspace.de"; to = tv.mail; }
+ ];
+ system-aliases = [
+ { from = "mailer-daemon"; to = "postmaster"; }
+ { from = "postmaster"; to = "root"; }
+ { from = "nobody"; to = "root"; }
+ { from = "hostmaster"; to = "root"; }
+ { from = "usenet"; to = "root"; }
+ { from = "news"; to = "root"; }
+ { from = "webmaster"; to = "root"; }
+ { from = "www"; to = "root"; }
+ { from = "ftp"; to = "root"; }
+ { from = "abuse"; to = "root"; }
+ { from = "noc"; to = "root"; }
+ { from = "security"; to = "root"; }
+ { from = "root"; to = "tv"; }
+ { from = "mirko"; to = "mv"; }
+ ];
+ };
+ tv.iptables.input-internet-accept-tcp = lib.singleton "smtp";
+}
diff --git a/configs/fs/CAC-CentOS-7-64bit.nix b/configs/fs/CAC-CentOS-7-64bit.nix
new file mode 100644
index 0000000..c9eb97f
--- /dev/null
+++ b/configs/fs/CAC-CentOS-7-64bit.nix
@@ -0,0 +1,20 @@
+_:
+
+{
+ boot.loader.grub = {
+ device = "/dev/sda";
+ };
+ fileSystems = {
+ "/" = {
+ device = "/dev/centos/root";
+ fsType = "xfs";
+ };
+ "/boot" = {
+ device = "/dev/sda1";
+ fsType = "xfs";
+ };
+ };
+ swapDevices = [
+ { device = "/dev/centos/swap"; }
+ ];
+}
diff --git a/configs/gitconfig.nix b/configs/gitconfig.nix
new file mode 100644
index 0000000..c4111ed
--- /dev/null
+++ b/configs/gitconfig.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }: {
+ environment.etc.gitconfig.text = ''
+ [alias]
+ patch = !${pkgs.git}/bin/git --no-pager diff --no-color
+ [diff-so-fancy]
+ markEmptyLines = false
+ stripLeadingSymbols = false
+ [pager]
+ diff = ${pkgs.gitAndTools.diff-so-fancy}/bin/diff-so-fancy \
+ | ${pkgs.less}/bin/less -FRX
+ [user]
+ email = tv@krebsco.de
+ name = tv
+ '';
+}
diff --git a/configs/gitrepos.nix b/configs/gitrepos.nix
new file mode 100644
index 0000000..c69ffa4
--- /dev/null
+++ b/configs/gitrepos.nix
@@ -0,0 +1,237 @@
+{ config, lib, mylib, pkgs, ... }: let {
+
+ body = {
+
+ nixpkgs.config.packageOverrides = super: {
+ cgit = pkgs.symlinkJoin {
+ name = "${super.cgit.name}-tv";
+ paths = [
+ (pkgs.runCommand "${super.cgit.name}-tv-overrides" {
+ } /* sh */ ''
+ mkdir -p $out/lib/cgit/filters
+ cd $out/lib/cgit/filters
+ cp \
+ ${super.cgit}/lib/cgit/filters/syntax-highlighting.py \
+ ${super.cgit}/lib/cgit/filters/.syntax-highlighting.py-wrapped \
+ .
+ sed -i "s:${super.cgit}:$out:" syntax-highlighting.py
+ sed -i '
+ s:^\(formatter =\).*:\1 HtmlFormatter(style="algol_nu"):
+ ' .syntax-highlighting.py-wrapped
+ '')
+ super.cgit
+ ];
+ };
+ };
+
+ krebs.git = {
+ enable = true;
+ cgit = {
+ settings = {
+ about-filter = pkgs.exec "krebs.cgit.about-filter" rec {
+ filename = "${pkgs.python3Packages.markdown2}/bin/markdown2";
+ argv = [
+ filename
+ "--extras=fenced-code-blocks"
+ ];
+ envp = {};
+ };
+ readme = [
+ ":README.md"
+ ];
+ root-desc = "mostly krebs";
+ root-title = "repositories at ${config.krebs.build.host.name}";
+ source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
+ };
+ };
+ repos = repos;
+ rules = rules;
+ };
+ };
+
+ cgit-clear-cache = pkgs.cgit-clear-cache.override {
+ inherit (config.krebs.git.cgit.settings) cache-root;
+ };
+
+ repos =
+ public-repos //
+ lib.optionalAttrs config.krebs.build.host.secure restricted-repos;
+
+ rules = lib.concatMap make-rules (builtins.attrValues repos);
+
+ public-repos = lib.mapAttrs make-public-repo ({
+ } // lib.mapAttrs (_: lib.recursiveUpdate { cgit.section = "1. miscellaneous"; }) {
+ couchfs = {
+ cgit.desc = "filesystem (in userspace) on top of CouchDB";
+ };
+ crx = {
+ cgit.desc = "utilities for working with Chrome extensions";
+ };
+ dic = {
+ cgit.desc = "dict.leo.org command line interface";
+ };
+ disko = {
+ cgit.desc = "declarative partitioning and formatting tool";
+ };
+ fswm = {
+ cgit.desc = "simple full screen window manager";
+ };
+ htgen = {
+ cgit.desc = "toy HTTP server";
+ };
+ ircaids = {
+ cgit.desc = "Assortment of aids for working with Internet relay chat";
+ };
+ krops = {
+ cgit.desc = "deployment tools";
+ };
+ mailaids = {
+ cgit.desc = "Assortment of aids for working with electronic mail";
+ };
+ much = {};
+ netcup = {
+ cgit.desc = "netcup command line interface";
+ };
+ nix-writers = {
+ cgit.desc = "collection of package builders";
+ };
+ nixpkgs = {
+ cgit.desc = "Nix Packages collection";
+ };
+ pager = {
+ };
+ populate = {
+ cgit.desc = "source code installer";
+ };
+ q = {};
+ reaktor2 = {};
+ stockholm = {
+ cgit.desc = "NixOS configuration";
+ };
+ TabFS = {
+ cgit.desc = "mount browser tabs & co. as a filesystem";
+ };
+ texnix = {
+ cgit.desc = "TeX live environment generator";
+ };
+ with-ssh = {};
+ } // lib.mapAttrs (_: lib.recursiveUpdate { cgit.section = "2. Host configurations"; }) {
+ ni = {
+ };
+ } // lib.mapAttrs (_: lib.recursiveUpdate { cgit.section = "3. Haskell libraries"; }) {
+ X11-aeson = {};
+ blessings = {};
+ hack = {};
+ hc = {};
+ mime = {};
+ quipper = {};
+ scanner = {};
+ wai-middleware-time = {};
+ web-routes-wai-custom = {};
+ xintmap = {};
+ xmonad-aeson = {};
+ xmonad-web = {};
+ } // lib.mapAttrs (_: lib.recursiveUpdate { cgit.section = "4. museum"; }) {
+ cac-api = {
+ cgit.desc = "CloudAtCost API command line interface";
+ };
+ cgserver = {};
+ crude-mail-setup = {};
+ dot-xmonad = {};
+ flameshot-once = {
+ cgit.desc = "flameshot runner that automatically starts/stops the daemon";
+ };
+ hirc = {};
+ hstool = {
+ cgit.desc = "Haskell Development Environment ^_^";
+ };
+ kirk = {
+ cgit.desc = "IRC tools";
+ };
+ make-snapshot = {};
+ nixos-infest = {};
+ painload = {};
+ push = {};
+ Reaktor = {};
+ regfish = {};
+ with-tmpdir = {};
+ get = {};
+ load-env = {};
+ loldns = {
+ cgit.desc = "toy DNS server";
+ };
+ soundcloud = {
+ cgit.desc = "SoundCloud command line interface";
+ };
+ xmonad-stockholm = {};
+ });
+
+ restricted-repos = lib.mapAttrs make-restricted-repo (
+ {
+ brain = {
+ collaborators = with config.krebs.users; [ lass makefu ];
+ hooks = {
+ post-receive = /* sh */ ''
+ (${irc-announce { cgit_endpoint = null; }})
+ ${cgit-clear-cache}/bin/cgit-clear-cache
+ '';
+ };
+ };
+ } //
+ # TODO don't put secrets/repos.nix into the store
+ mylib.importSecret "repos.nix" { inherit config lib pkgs; }
+ );
+
+ irc-announce = args: pkgs.git-hooks.irc-announce (lib.recursiveUpdate {
+ channel = "#xxx";
+ # TODO make nick = config.krebs.build.host.name the default
+ nick = config.krebs.build.host.name;
+ server = "irc.r";
+ verbose = {
+ exclude = [
+ "refs/heads/head"
+ ];
+ };
+ } args);
+
+ make-public-repo = name: { cgit ? {}, ... }: {
+ inherit cgit name;
+ public = true;
+ hooks = {
+ post-receive = /* sh */ ''
+ (${lib.optionalString (config.krebs.build.host.name == "ni")
+ (irc-announce {})})
+ ${cgit-clear-cache}/bin/cgit-clear-cache
+ '';
+ };
+ };
+
+ make-restricted-repo = name: { collaborators ? [], hooks ? {}, ... }: {
+ inherit collaborators name;
+ public = false;
+ hooks = hooks // {
+ post-receive = /* sh */ ''
+ (${hooks.post-receive or ":"})
+ ${cgit-clear-cache}/bin/cgit-clear-cache
+ '';
+ };
+ };
+
+ make-rules =
+ with mylib.git // config.krebs.users;
+ repo:
+ [
+ {
+ user = [ tv tv-xu ];
+ repo = [ repo ];
+ perm = push "refs/*" [ non-fast-forward create delete merge ];
+ }
+ ]
+ ++
+ lib.optional (repo.collaborators or [] != []) {
+ user = repo.collaborators;
+ repo = [ repo ];
+ perm = fetch;
+ };
+
+}
diff --git a/configs/htop.nix b/configs/htop.nix
new file mode 100644
index 0000000..e60cc51
--- /dev/null
+++ b/configs/htop.nix
@@ -0,0 +1,39 @@
+{ pkgs, ... }: {
+ nixpkgs.config.packageOverrides = super: {
+ htop = pkgs.symlinkJoin {
+ name = "htop";
+ paths = [
+ (pkgs.writeDashBin "htop" ''
+ export HTOPRC=${pkgs.writeText "htoprc" ''
+ fields=0 48 17 18 38 39 40 2 46 47 49 1
+ sort_key=46
+ sort_direction=1
+ hide_threads=0
+ hide_kernel_threads=1
+ hide_userland_threads=0
+ shadow_other_users=1
+ show_thread_names=1
+ show_program_path=1
+ highlight_base_name=1
+ highlight_megabytes=1
+ highlight_threads=1
+ tree_view=1
+ header_margin=0
+ detailed_cpu_time=0
+ cpu_count_from_zero=0
+ update_process_names=0
+ account_guest_in_cpu_meter=1
+ color_scheme=0
+ delay=15
+ left_meters=LeftCPUs2 RightCPUs2 Memory Swap
+ left_meter_modes=1 1 1 1
+ right_meters=Uptime Tasks LoadAverage Battery
+ right_meter_modes=2 2 2 2
+ ''}
+ exec ${super.htop}/bin/htop "$@"
+ '')
+ super.htop
+ ];
+ };
+ };
+}
diff --git a/configs/hw/AO753.nix b/configs/hw/AO753.nix
new file mode 100644
index 0000000..ea58c01
--- /dev/null
+++ b/configs/hw/AO753.nix
@@ -0,0 +1,47 @@
+{ config, ... }: {
+ imports = [
+ ../smartd.nix
+
+ {
+ nix.settings.cores = 2;
+ nix.settings.max-jobs = 2;
+ }
+ (if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then {
+ nix.daemonCPUSchedPolicy = "batch";
+ nix.daemonIOSchedPriority = 1;
+ } else {
+ nix.daemonIONiceLevel = 1;
+ nix.daemonNiceLevel = 1;
+ })
+ ];
+
+ boot.loader.grub = {
+ device = "/dev/sda";
+ splashImage = null;
+ };
+
+ boot.initrd.availableKernelModules = [
+ "ahci"
+ ];
+
+ boot.kernelModules = [
+ "kvm-intel"
+ "wl"
+ ];
+
+ boot.extraModulePackages = [
+ config.boot.kernelPackages.broadcom_sta
+ ];
+
+ services.logind.extraConfig = ''
+ HandleHibernateKey=ignore
+ HandleLidSwitch=ignore
+ HandlePowerKey=ignore
+ HandleSuspendKey=ignore
+ '';
+
+ krebs.nixpkgs.allowUnfreePredicate = pkg: packageName pkg == "broadcom-sta";
+
+ tv.hw.screens.primary.width = 1366;
+ tv.hw.screens.primary.height = 768;
+}
diff --git a/configs/hw/winmax2.nix b/configs/hw/winmax2.nix
new file mode 100644
index 0000000..7b28466
--- /dev/null
+++ b/configs/hw/winmax2.nix
@@ -0,0 +1,48 @@
+{ pkgs, ... }: {
+
+ imports = [
+ ../smartd.nix
+ ];
+
+ boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" ];
+ boot.initrd.kernelModules = [ "amdgpu" ];
+ boot.kernelModules = [
+ "amd-pstate"
+ "kvm-amd"
+ ];
+ boot.kernelPackages = pkgs.linuxPackages_latest;
+ boot.kernelParams = [
+ "amd_pstate=passive"
+ ];
+
+ hardware.bluetooth.enable = true;
+
+ hardware.cpu.amd.updateMicrocode = true;
+ hardware.enableRedistributableFirmware = true;
+
+ hardware.opengl.enable = true;
+ hardware.opengl.extraPackages = [
+ pkgs.amdvlk
+ pkgs.rocm-opencl-icd
+ pkgs.rocm-opencl-runtime
+ ];
+
+ networking.wireless.enable = true;
+ networking.wireless.interfaces = [
+ "wlp1s0"
+ ];
+ networking.interfaces.wlp1s0.useDHCP = true;
+
+ nixpkgs.hostPlatform = "x86_64-linux";
+
+ services.illum.enable = true;
+
+ services.logind.extraConfig = /* ini */ ''
+ HandlePowerKey=ignore
+ '';
+
+ tv.lidControl.enable = true;
+
+ tv.hw.screens.primary.width = 2560;
+ tv.hw.screens.primary.height = 1600;
+}
diff --git a/configs/hw/x220.nix b/configs/hw/x220.nix
new file mode 100644
index 0000000..6993413
--- /dev/null
+++ b/configs/hw/x220.nix
@@ -0,0 +1,88 @@
+{ config, lib, pkgs, ... }: {
+ imports = [
+ ../smartd.nix
+ {
+ boot.extraModulePackages = [
+ config.boot.kernelPackages.acpi_call
+ ];
+
+ boot.kernelModules = [
+ "acpi_call"
+ ];
+
+ environment.systemPackages = [
+ pkgs.tpacpi-bat
+ ];
+ }
+
+ # fix jumpy touchpad
+ # https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X220#X220_Touchpad_cursor_jump/imprecise
+ {
+ services.udev.extraHwdb = /* sh */ ''
+ touchpad:i8042:*
+ LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81=1
+ '';
+ }
+
+ {
+ nix.settings.cores = 2;
+ nix.settings.max-jobs = 2;
+ }
+ (if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then {
+ nix.daemonCPUSchedPolicy = "batch";
+ nix.daemonIOSchedPriority = 1;
+ } else {
+ nix.daemonIONiceLevel = 1;
+ nix.daemonNiceLevel = 1;
+ })
+ ];
+
+ boot.extraModulePackages = [
+ config.boot.kernelPackages.tp_smapi
+ ];
+
+ boot.kernelModules = [ "tp_smapi" ];
+
+ boot.loader.systemd-boot.enable = true;
+ boot.loader.efi.canTouchEfiVariables = true;
+
+ # Required for Centrino.
+ hardware.enableRedistributableFirmware = true;
+
+ hardware.opengl.extraPackages = [ pkgs.vaapiIntel pkgs.vaapiVdpau ];
+
+ hardware.trackpoint = {
+ enable = true;
+ sensitivity = 220;
+ speed = 0;
+ emulateWheel = true;
+ };
+
+ # Conflicts with TLP, but gets enabled by DEs.
+ services.power-profiles-daemon.enable = false;
+
+ services.tlp.enable = true;
+ services.tlp.settings = {
+ START_CHARGE_THRESH_BAT0 = 80;
+ };
+
+
+ services.logind.extraConfig = ''
+ HandleHibernateKey=ignore
+ HandleLidSwitch=ignore
+ HandlePowerKey=ignore
+ HandleSuspendKey=ignore
+ '';
+
+ # because extraConfig is not extra enough:
+ services.logind.lidSwitch = "ignore";
+ services.logind.lidSwitchDocked = "ignore";
+ services.logind.lidSwitchExternalPower = "ignore";
+
+ services.xserver = {
+ videoDriver = "intel";
+ };
+
+ tv.hw.screens.primary.width = lib.mkDefault 1366;
+ tv.hw.screens.primary.height = lib.mkDefault 768;
+}
diff --git a/configs/imgur.nix b/configs/imgur.nix
new file mode 100644
index 0000000..ece4749
--- /dev/null
+++ b/configs/imgur.nix
@@ -0,0 +1,21 @@
+{ config, pkgs, ... }: {
+ services.nginx.virtualHosts."ni.r" = {
+ locations."/image" = {
+ extraConfig = /* nginx */ ''
+ client_max_body_size 20M;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ proxy_pass http://127.0.0.1:${toString config.krebs.htgen.imgur.port};
+ proxy_pass_header Server;
+ '';
+ };
+ };
+
+ krebs.htgen.imgur = {
+ port = 7771;
+ scriptFile = "${pkgs.htgen-imgur}/bin/htgen-imgur";
+ };
+}
diff --git a/configs/initrd/sshd.nix b/configs/initrd/sshd.nix
new file mode 100644
index 0000000..eff8480
--- /dev/null
+++ b/configs/initrd/sshd.nix
@@ -0,0 +1,17 @@
+{ config, ... }: {
+ boot.initrd.availableKernelModules = [
+ "e1000e"
+ ];
+ boot.initrd.network.enable = true;
+ boot.initrd.network.ssh = {
+ enable = true;
+ port = 11423;
+ authorizedKeys = [
+ config.krebs.users.tv.pubkey
+ ];
+ ignoreEmptyHostKeys = true;
+ };
+ boot.initrd.secrets = {
+ "/etc/ssh/ssh_host_rsa_key" = <secrets/initrd/ssh_host_rsa_key>;
+ };
+}
diff --git a/configs/mail-client.nix b/configs/mail-client.nix
new file mode 100644
index 0000000..fc8fc81
--- /dev/null
+++ b/configs/mail-client.nix
@@ -0,0 +1,9 @@
+{ pkgs, ... }: {
+ environment.systemPackages = [
+ pkgs.haskellPackages.much
+ pkgs.msmtp
+ pkgs.notmuch
+ pkgs.qprint
+ pkgs.w3m
+ ];
+}
diff --git a/configs/man.nix b/configs/man.nix
new file mode 100644
index 0000000..c723138
--- /dev/null
+++ b/configs/man.nix
@@ -0,0 +1,13 @@
+{ config, lib, pkgs, ... }:
+{
+ #environment.etc."man.conf".source = pkgs.runCommand "man.conf" {} ''
+ # ${pkgs.gnused}/bin/sed <${pkgs.man}/lib/man.conf >$out '
+ # s:^NROFF\t.*:& -Wbreak:
+ # '
+ #'';
+ environment.systemPackages = [
+ pkgs.man-pages
+ pkgs.posix_man_pages
+ pkgs.xorg.xorgdocs
+ ];
+}
diff --git a/configs/nets/hkw.nix b/configs/nets/hkw.nix
new file mode 100644
index 0000000..51a8a73
--- /dev/null
+++ b/configs/nets/hkw.nix
@@ -0,0 +1,68 @@
+{
+ krebs = {
+ dns.providers.hkw = "hosts";
+ hosts = {
+ au = {
+ nets.hkw = {
+ ip4 = {
+ addr = "10.23.1.39";
+ prefix = "10.23.1.0/24";
+ };
+ aliases = [
+ "au.hkw"
+ ];
+ ssh.port = 11423;
+ };
+ };
+ nomic = {
+ nets.hkw = {
+ ip4 = {
+ addr = "10.23.1.110";
+ prefix = "10.23.1.0/24";
+ };
+ aliases = [
+ "nomic.hkw"
+ ];
+ ssh.port = 11423;
+ };
+ };
+ ok = {
+ external = true;
+ nets.hkw = {
+ ip4 = {
+ addr = "10.23.1.1";
+ prefix = "10.23.1.0/24";
+ };
+ aliases = [
+ "ok.hkw"
+ ];
+ };
+ };
+ xu = {
+ nets.hkw = {
+ ip4 = {
+ addr = "10.23.1.38";
+ prefix = "10.23.1.0/24";
+ };
+ aliases = [
+ "xu.hkw"
+ "cache.xu.hkw"
+ ];
+ ssh.port = 11423;
+ };
+ };
+ zu = {
+ nets.hkw = {
+ ip4 = {
+ addr = "10.23.1.40";
+ prefix = "10.23.1.0/24";
+ };
+ aliases = [
+ "zu.hkw"
+ ];
+ ssh.port = 11423;
+ };
+ };
+ };
+ };
+}
diff --git a/configs/networkd.nix b/configs/networkd.nix
new file mode 100644
index 0000000..da0d9ce
--- /dev/null
+++ b/configs/networkd.nix
@@ -0,0 +1,4 @@
+{
+ # often hangs
+ systemd.services.systemd-networkd-wait-online.enable = false;
+}
diff --git a/configs/nginx/default.nix b/configs/nginx/default.nix
new file mode 100644
index 0000000..e288c52
--- /dev/null
+++ b/configs/nginx/default.nix
@@ -0,0 +1,21 @@
+{ config, ... }: {
+ services.nginx = {
+ enableReload = true;
+
+ recommendedGzipSettings = true;
+ recommendedOptimisation = true;
+ recommendedTlsSettings = true;
+
+ virtualHosts.${builtins.toJSON ""} = {
+ default = true;
+ extraConfig = ''
+ error_page 400 =444 /;
+ return 444;
+ '';
+ rejectSSL = true;
+ };
+ };
+ tv.iptables = {
+ input-retiolum-accept-tcp = [ "http" ];
+ };
+}
diff --git a/configs/nginx/public_html.nix b/configs/nginx/public_html.nix
new file mode 100644
index 0000000..cd8e3c4
--- /dev/null
+++ b/configs/nginx/public_html.nix
@@ -0,0 +1,17 @@
+{ config, ... }: {
+ services.nginx = {
+ enable = true;
+ virtualHosts.default = {
+ serverAliases = [
+ "localhost"
+ "${config.krebs.build.host.name}"
+ "${config.krebs.build.host.name}.hkw"
+ "${config.krebs.build.host.name}.r"
+ ];
+ locations."~ ^/~([a-z]+)(?:/(.*))?\$" = {
+ alias = "/srv/$1/public_html/$2";
+ };
+ };
+ };
+ tv.iptables.input-internet-accept-tcp = [ "http" ];
+}
diff --git a/configs/nix.nix b/configs/nix.nix
new file mode 100644
index 0000000..fa96d45
--- /dev/null
+++ b/configs/nix.nix
@@ -0,0 +1,9 @@
+{ pkgs, ... }: {
+ nix.settings.auto-optimise-store = true;
+
+ # TODO check if both are required:
+ nix.settings.extra-sandbox-paths = [
+ "/etc/protocols"
+ pkgs.iana-etc.outPath
+ ];
+}
diff --git a/configs/pki/certs/tv.crt b/configs/pki/certs/tv.crt
new file mode 100644
index 0000000..ccb2623
--- /dev/null
+++ b/configs/pki/certs/tv.crt
@@ -0,0 +1,31 @@
+tv Root CA
+-----BEGIN CERTIFICATE-----
+MIIFGzCCAwOgAwIBAgIUbLFkDA1OgKbej/FQiJZ4gpGPg/4wDQYJKoZIhvcNAQEL
+BQAwFTETMBEGA1UEAwwKdHYgUm9vdCBDQTAeFw0xOTA0MjEwNzI1MTdaFw0yOTA0
+MTgwNzI1MTdaMBUxEzARBgNVBAMMCnR2IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDEVpZo1PLayK2AULwNtRY/2RIs/h+Uz1k/I7AY5o7H
+HTD6pxNH3DZS82Y89nAHDVEnotK26TW6N1O2fBHUxH2GXVD+MaA/D9ngbNTJa7DW
+2EThezOyesAbXk7dkoHh4Bouj5L7Ronka5+IREFmb3mHmcXLuR/sot9Pwr9A7Lwm
+55Avv+VwMFnqVMXiCYQsDL7Mxf7Vm79+kXShpfDhNmHhyZc/xPjVk7lttSEp0LCq
+hhJjte3xDGbk7OThTSxoqP+K4Ek7NGatCcm4AUZlDl1kLN2QKudYqj0VRQpfE+4Q
+jMAAtttc/10MV0e08pRK0FvJsDsi70YZrHnDP6hIBrRNjC8iB/8rz2pjnYzgriUt
+HHEDr26234VB5Zqhsi8pmXA16FVkoKlucADXXKEcR/3VreTvZLdSsP3OrDdSCwhi
+H2W/7tshDPp+I9Q9fGNixry7PODbud1h/wLsq3Geg/U6VkDdl7uDNMB/O7LvlFaC
+7jkHv/xFLqV1Xx9+yFMdJTKLf9jnIIjeINfV4VcJZDrtgGpnC6cYD5DNLA4j7Mny
+EnBV9IRhmKiZLvUZP62dPhqIfSSPNxXV2+rT5ZfaXCuVe79R5npgJzF7/qslvnZ6
+0mjZfQdJiXY+/oT9zPUxTroFx7Qtda15aIVwXR+1cMRY/Hg/uBQyp7yWsvwhPYwH
+awIDAQABo2MwYTAdBgNVHQ4EFgQUWYjGpR7J/UqggxQV87hBQ8ZT0qkwHwYDVR0j
+BBgwFoAUWYjGpR7J/UqggxQV87hBQ8ZT0qkwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAA++eAA7KLEd4n05n8w95sJ7
+cxqQSkVxV3ASnEUQRwVGo3CqEKcNufbCTG7KKGQFUi2Xd3/SWgnEiSZZWo06azbV
+vlquG+9ilwnrnqfjlbUEjLMHDzukrEeIiRuFY7gZv6S2o4WkW/M9IPkP34+PRjip
+AJ8kFcy7wLPaeH7OagslAVUcf68lMm+8W4U1g0HZaY2zXFgdRrIO1dXKlJ22Wh4X
+fcblHjkASAGi+BK+xRJ9G7s3sie2wPyk+WKKv0Z+WheKf+L+TPBg2sJ+d25gW+gG
+XNJSQOzCqSfHrCtcW1xkGgifog28/ymN03ggn8oMBUebOp+ayLkbPQDaj6te3y1v
+YE0cfkzQ0T6sSzPzoOrwBEuSX8cLWTpzO2Zgqbf36UtHjgxi58vY46p7MjAInxAf
+j+k67rF7qWH38drg4nfGjNgiEdeJw9dtDFdmso+ZiWipUyGF4VYh+Q6JnXDMF0+A
+wXcYWa7ckXvVOLVpHJfrLDYTXznGnk2u4ToVNEk1j/klMRn96lxfFg04iv8fz8m6
+/Y8g0G1uIT5Mq9l68oZUoEkUHZabPNhYOiYtg4t5v/T3AIV8nm2A5jZYj0am26xT
+iqF/tqL3alWXs9OHP7FNdrVWtwO8vcspYcd4mOHdAC/dmhq+77BowR5Lldx9T+mR
+QT8jW9PXL0IH0wKMBXxf
+-----END CERTIFICATE-----
diff --git a/configs/pki/default.nix b/configs/pki/default.nix
new file mode 100644
index 0000000..05a608d
--- /dev/null
+++ b/configs/pki/default.nix
@@ -0,0 +1,67 @@
+{ config, lib, mylib, pkgs, ... }: let
+
+ certFile = config.environment.etc."ssl/certs/ca-certificates.crt".source;
+
+in {
+
+ environment.etc."pki/nssdb".source =
+ pkgs.runCommand "system-wide-nssdb" {
+ inherit certFile;
+ buildInputs = [
+ pkgs.jq
+ pkgs.nssTools
+ ];
+ parseInfoScript = /* jq */ ''
+ ${builtins.toJSON certFile} as $certFile |
+
+ split("\t-----END CERTIFICATE-----\n")[] |
+ select(test("\t-----BEGIN CERTIFICATE-----\n")) |
+ . + "\t-----END CERTIFICATE-----\n" |
+
+ sub("^([0-9]+\t\n)*";"") |
+
+ (match("^([0-9]+)\t").captures[0].string | tonumber) as $lineNumber |
+
+ gsub("(?m)^[0-9]+\t";"") |
+
+ match("^([^\n]+)\n(.*)";"m").captures | map(.string) |
+
+ # Line numbers are added to the names to ensure uniqueness.
+ "\(.[0]) (\($certFile):\($lineNumber))" as $name |
+ .[1] as $cert |
+
+ { $name, $cert }
+ '';
+ passAsFile = [
+ "parseInfoScript"
+ ];
+ } /* sh */ ''
+ mkdir nssdb
+
+ nl -ba -w1 "$certFile" |
+ jq -ceRs -f "$parseInfoScriptPath" > certinfo.ndjson
+
+ exec < certinfo.ndjson
+ while read -r certinfo; do
+ name=$(printf %s "$certinfo" | jq -er .name)
+ cert=$(printf %s "$certinfo" | jq -er .cert)
+
+ printf %s "$cert" | certutil -A -d nssdb -n "$name" -t C,C,C
+ done
+
+ mv nssdb "$out"
+ '';
+
+ environment.variables = lib.flip lib.genAttrs (_: toString certFile) [
+ "CURL_CA_BUNDLE"
+ "GIT_SSL_CAINFO"
+ "SSL_CERT_FILE"
+ ];
+
+ security.pki.certificateFiles =
+ lib.mapAttrsToList
+ (name: _: (./certs + "/${name}"))
+ (lib.filterAttrs (_: (mylib.eq "regular"))
+ (builtins.readDir ./certs));
+
+}
diff --git a/configs/ppp.nix b/configs/ppp.nix
new file mode 100644
index 0000000..63e75af
--- /dev/null
+++ b/configs/ppp.nix
@@ -0,0 +1,85 @@
+{ config, mylib, pkgs, ... }: let
+ cfg = {
+ pin = "@${config.krebs.secret.directory}/o2.pin";
+ ttys.ppp = "/dev/ttyACM0";
+ ttys.com = "/dev/ttyACM1";
+ };
+in {
+ assertions = [
+ {
+ assertion =
+ config.networking.resolvconf.enable ||
+ config.networking.useNetworkd;
+ message = "ppp configuration needs resolvconf or networkd";
+ }
+ ];
+ environment.etc."ppp/ip-up".source = pkgs.writeDash "ppp.ip-up" ''
+ ${pkgs.openresolv}/bin/resolvconf -a "$IFNAME" < /etc/ppp/resolv.conf
+ '';
+ environment.etc."ppp/ip-down".source = pkgs.writeDash "ppp.ip-down" ''
+ ${pkgs.openresolv}/bin/resolvconf -fd "$IFNAME"
+ '';
+ environment.etc."ppp/peers/o2".text = /* sh */ ''
+ ${cfg.ttys.ppp}
+ 921600
+ crtscts
+ defaultroute
+ holdoff 10
+ lock
+ maxfail 0
+ noauth
+ nodetach
+ noipdefault
+ passive
+ persist
+ usepeerdns
+ connect "${pkgs.ppp}/bin/chat ''${DEBUG+-v} -Ss -f ${pkgs.writeText "o2.chat" /* sh */ ''
+ ABORT "BUSY"
+ ABORT "NO CARRIER"
+ REPORT CONNECT
+ "*EMRDY: 1"
+ ATZ OK
+ AT+CFUN=1 OK
+ ${cfg.pin} TIMEOUT 2 ERROR-AT-OK
+ AT+CGDCONT=1,\042IP\042,\042internet\042 OK
+ ATDT*99***1# CONNECT
+ ''}"
+ '';
+ users.users.root.packages = [
+ (pkgs.writeDashBin "connect" ''
+ # usage:
+ # connect wlan
+ # connect wwan [PEERNAME]
+ set -efu
+ rfkill_wlan=/sys/class/rfkill/rfkill2
+ rfkill_wwan=/sys/class/rfkill/rfkill1
+ case $1 in
+ wlan)
+ ${pkgs.procps}/bin/pkill pppd || :
+ echo 0 > "$rfkill_wwan"/state
+ echo 1 > "$rfkill_wlan"/state
+ ;;
+ wwan)
+ name=''${2-o2}
+ echo 0 > "$rfkill_wlan"/state
+ echo 1 > "$rfkill_wwan"/state
+ ${pkgs.ppp}/bin/pppd call "$name" updetach
+ ;;
+ *)
+ echo "$0: error: bad arguments: $*" >&2
+ exit 1
+ esac
+ '')
+ (pkgs.writeDashBin "modem-send" ''
+ # usage: modem-send ATCOMMAND
+ set -efu
+ tty=${mylib.shell.escape cfg.ttys.com}
+ exec <"$tty"
+ printf '%s\r\n' "$1" >"$tty"
+ ${pkgs.gnused}/bin/sed -E '
+ /^OK\r?$/q
+ /^ERROR\r?$/q
+ '
+ '')
+ ];
+}
diff --git a/configs/pulse.nix b/configs/pulse.nix
new file mode 100644
index 0000000..17c203c
--- /dev/null
+++ b/configs/pulse.nix
@@ -0,0 +1,119 @@
+{ config, lib, mylib, pkgs, ... }: let
+ pkg = pkgs.pulseaudio;
+ runDir = "/run/pulse";
+
+ pkgs_i686 = pkgs.pkgsi686Linux;
+
+ support32Bit =
+ pkgs.stdenv.isx86_64 &&
+ pkgs_i686.alsaLib != null &&
+ pkgs_i686.libpulseaudio != null;
+
+ alsaConf = pkgs.writeText "asound.conf" ''
+ ctl_type.pulse {
+ libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so;
+ ${lib.optionalString support32Bit
+ "libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so;"}
+ }
+ pcm_type.pulse {
+ libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so;
+ ${lib.optionalString support32Bit
+ "libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so;"}
+ }
+ ctl.!default {
+ type pulse
+ }
+ pcm.!default {
+ type pulse
+ }
+ '';
+
+ clientConf = pkgs.writeText "client.conf" ''
+ autospawn=no
+ default-server = unix:${runDir}/socket
+ '';
+
+ configFile = pkgs.writeText "default.pa" ''
+ .include ${pkg}/etc/pulse/default.pa
+ load-module ${toString [
+ "module-native-protocol-unix"
+ "auth-anonymous=1"
+ "socket=${runDir}/socket"
+ ]}
+ ${lib.optionalString (config.krebs.build.host.name == "au") ''
+ load-module ${toString [
+ "module-native-protocol-tcp"
+ "auth-ip-acl=127.0.0.1;10.23.1.0/24"
+ ]}
+ ''}
+ ${lib.optionalString (config.krebs.build.host.name != "au") ''
+ load-module ${toString [
+ "module-tunnel-sink-new"
+ "server=au.hkw"
+ "sink_name=au"
+ "channels=2"
+ "rate=44100"
+ ]}
+ ''}
+ '';
+in
+
+{
+ environment = {
+ etc = {
+ "asound.conf".source = alsaConf;
+ # XXX mkForce is not strong enough (and neither is mkOverride) to create
+ # /etc/pulse/client.conf, see pulseaudio-hack below for a solution.
+ #"pulse/client.conf" = mkForce { source = clientConf; };
+ #"pulse/client.conf".source = mkForce clientConf;
+ "pulse/default.pa".source = configFile;
+ };
+ systemPackages = [
+ pkg
+ ] ++ lib.optionals config.services.xserver.enable [
+ pkgs.pavucontrol
+ ];
+ };
+
+ hardware.pulseaudio = {
+ inherit support32Bit;
+ };
+
+ # Allow PulseAudio to get realtime priority using rtkit.
+ security.rtkit.enable = true;
+
+ system.activationScripts.pulseaudio-hack = ''
+ ln -fns ${clientConf} /etc/pulse/client.conf
+ '';
+
+ systemd.services.pulse = {
+ wantedBy = [ "sound.target" ];
+ before = [ "sound.target" ];
+ environment = {
+ PULSE_RUNTIME_PATH = "${runDir}/home";
+ };
+ serviceConfig = {
+ ExecStart = "${pkg}/bin/pulseaudio --exit-idle-time=-1";
+ ExecStartPre = pkgs.writeDash "pulse-start" ''
+ install -o pulse -g pulse -m 0750 -d ${runDir}
+ install -o pulse -g pulse -m 0700 -d ${runDir}/home
+ '';
+ PermissionsStartOnly = "true";
+ User = "pulse";
+ };
+ };
+
+ # TODO assert that pulse is the only user with "audio" in group/extraGroups
+ # otherwise the audio device can be hijacked while the pulse service restarts
+ # (e.g. when mpv is running) and then the service will fail.
+ users = {
+ groups.pulse.gid = config.users.users.pulse.uid;
+ users.pulse = {
+ uid = mylib.genid_uint31 "pulse";
+ group = "pulse";
+ extraGroups = [ "audio" ];
+ home = "${runDir}/home";
+ isSystemUser = true;
+ };
+ };
+}
diff --git a/configs/repo-sync/wiki.nix b/configs/repo-sync/wiki.nix
new file mode 100644
index 0000000..94f7e80
--- /dev/null
+++ b/configs/repo-sync/wiki.nix
@@ -0,0 +1,39 @@
+{ config, lib, mylib, pkgs, ... }: {
+ krebs.repo-sync.enable = true;
+ krebs.repo-sync.repos.wiki.branches.hotdog = {
+ origin.url = "http://cgit.hotdog.r/wiki";
+ mirror.url = "git@${config.krebs.build.host.name}.r:wiki";
+ };
+ krebs.git.repos.wiki = {
+ public = true;
+ name = "wiki";
+ cgit.desc = toString [
+ "mirror of"
+ config.krebs.repo-sync.repos.wiki.branches.hotdog.origin.url
+ ];
+ cgit.section = "7. mirrors";
+ hooks.post-receive = /* sh */ ''
+ ${pkgs.git-hooks.irc-announce {
+ channel = "#xxx";
+ nick = config.krebs.build.host.name;
+ server = "irc.r";
+ }}
+ ${pkgs.cgit-clear-cache.override {
+ inherit (config.krebs.git.cgit.settings) cache-root;
+ }}/bin/cgit-clear-cache
+ '';
+ };
+ krebs.git.rules = lib.singleton {
+ user = lib.singleton config.krebs.users.repo-sync;
+ repo = lib.singleton config.krebs.git.repos.wiki;
+ perm = mylib.git.push "refs/*" [
+ mylib.git.create
+ mylib.git.delete
+ mylib.git.merge
+ mylib.git.non-fast-forward
+ ];
+ };
+ krebs.users.${config.krebs.repo-sync.user.name}.pubkey = {
+ ni = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINK9U0Ob9/O0kxg3trhZY/vDnbqfN+R5cASGiClRr4IM";
+ }.${config.krebs.build.host.name};
+}
diff --git a/configs/retiolum.nix b/configs/retiolum.nix
new file mode 100644
index 0000000..632cc97
--- /dev/null
+++ b/configs/retiolum.nix
@@ -0,0 +1,26 @@
+{ config, lib, mylib, pkgs, ... }: {
+ krebs.tinc.retiolum = {
+ enable = true;
+ connectTo = builtins.filter (mylib.ne config.krebs.build.host.name) [
+ "ni"
+ "prism"
+ "eve"
+ ];
+ extraConfig = ''
+ LocalDiscovery = yes
+ '';
+ tincPackage = pkgs.tinc_pre;
+ tincUp = lib.mkIf config.systemd.network.enable "";
+ };
+ systemd.network.networks.retiolum = {
+ matchConfig.Name = "retiolum";
+ address = let
+ inherit (config.krebs.build.host.nets.retiolum) ip4 ip6;
+ in [
+ "${ip4.addr}/${toString ip4.prefixLength}"
+ "${ip6.addr}/${toString ip6.prefixLength}"
+ ];
+ };
+ tv.iptables.input-internet-accept-tcp = [ "tinc" ];
+ tv.iptables.input-internet-accept-udp = [ "tinc" ];
+}
diff --git a/configs/smartd.nix b/configs/smartd.nix
new file mode 100644
index 0000000..9c4d8b2
--- /dev/null
+++ b/configs/smartd.nix
@@ -0,0 +1,17 @@
+{ config, pkgs, ... }:
+
+{
+ services.smartd = {
+ enable = true;
+ devices = [
+ {
+ device = "DEVICESCAN";
+ options = toString [
+ "-a"
+ "-m ${config.krebs.users.tv.mail}"
+ "-s (O/../.././09|S/../.././04|L/../../6/05)"
+ ];
+ }
+ ];
+ };
+}
diff --git a/configs/ssh.nix b/configs/ssh.nix
new file mode 100644
index 0000000..0dda6e5
--- /dev/null
+++ b/configs/ssh.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }: {
+ # Override NixOS's "Allow DSA keys for now."
+ environment.etc."ssh/ssh_config".text = lib.mkForce ''
+ AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
+
+ ${lib.optionalString config.programs.ssh.setXAuthLocation ''
+ XAuthLocation ${pkgs.xorg.xauth}/bin/xauth
+ ''}
+
+ ForwardX11 ${if config.programs.ssh.forwardX11 then "yes" else "no"}
+
+ ${config.programs.ssh.extraConfig}
+ '';
+
+ programs.ssh = {
+ extraConfig = ''
+ UseRoaming no
+ '';
+ startAgent = false;
+ };
+}
diff --git a/configs/sshd.nix b/configs/sshd.nix
new file mode 100644
index 0000000..281d498
--- /dev/null
+++ b/configs/sshd.nix
@@ -0,0 +1,26 @@
+{ config, lib, ... }: let
+ cfg.host = config.krebs.build.host;
+ nets =
+ lib.optional (cfg.host.nets?retiolum) cfg.host.nets.retiolum ++
+ lib.optional (cfg.host.nets?wiregrill) cfg.host.nets.wiregrill;
+in {
+ services.openssh = {
+ enable = true;
+ };
+ tv.iptables.input-internet-accept-tcp = [ "ssh" ];
+ tv.iptables.extra.nat.OUTPUT = [
+ "-o lo -p tcp --dport 11423 -j REDIRECT --to-ports 22"
+ ];
+ tv.iptables.extra4.nat.PREROUTING =
+ map
+ (net: "-d ${net.ip4.addr} -p tcp --dport 22 -j ACCEPT")
+ (builtins.filter (net: net.ip4 != null) nets);
+ tv.iptables.extra6.nat.PREROUTING =
+ map
+ (net: "-d ${net.ip6.addr} -p tcp --dport 22 -j ACCEPT")
+ (builtins.filter (net: net.ip6 != null) nets);
+ tv.iptables.extra.nat.PREROUTING = [
+ "-p tcp --dport 22 -j REDIRECT --to-ports 0"
+ "-p tcp --dport 11423 -j REDIRECT --to-ports 22"
+ ];
+}
diff --git a/configs/urlwatch.nix b/configs/urlwatch.nix
new file mode 100644
index 0000000..19f28b1
--- /dev/null
+++ b/configs/urlwatch.nix
@@ -0,0 +1,118 @@
+{ config, lib, mylib, pkgs, ... }: let
+ exec = filename: args: url: {
+ inherit url;
+ filter = [
+ {
+ system =
+ lib.concatMapStringsSep " " mylib.shell.escape ([filename] ++ lib.toList args);
+ }
+ ];
+ };
+ json = json' ["."];
+ json' = exec "${pkgs.jq}/bin/jq";
+ urigrep' = exec (pkgs.writeDash "urigrep" ''
+ ${pkgs.urix}/bin/urix | ${pkgs.gnugrep}/bin/grep -E "$1"
+ '');
+ xml = xml' ["--format" "-"];
+ xml' = exec "${pkgs.libxml2}/bin/xmllint";
+in {
+ krebs.urlwatch = {
+ enable = true;
+ mailto = config.krebs.users.tv.mail;
+ onCalendar = "*-*-* 05:00:00";
+ urls = [
+ ## nixpkgs maintenance
+
+ # 2014-07-29 when one of the following urls change
+ # then we have to update the package
+
+ http://www.exim.org/
+
+ # ref src/nixpkgs/pkgs/tools/networking/urlwatch/default.nix
+ {
+ url = https://thp.io/2008/urlwatch/;
+ # workaround: ('Received response with content-encoding: gzip, but
+ # failed to decode it.', error('Error -3 while decompressing data:
+ # incorrect header check',))
+ ignore_cached = true;
+ }
+
+ # 2015-02-18
+ # ref ~/src/nixpkgs/pkgs/tools/text/qprint/default.nix
+ http://www.fourmilab.ch/webtools/qprint/
+
+ # 2014-09-24 ref https://github.com/4z3/xintmap
+ http://www.mathstat.dal.ca/~selinger/quipper/
+
+ ## 2014-10-17
+ ## TODO update ~/src/login/default.nix
+ #http://hackage.haskell.org/package/bcrypt
+ #http://hackage.haskell.org/package/cron
+ #http://hackage.haskell.org/package/hyphenation
+ #http://hackage.haskell.org/package/iso8601-time
+ #http://hackage.haskell.org/package/ixset-typed
+ #http://hackage.haskell.org/package/system-command
+ #http://hackage.haskell.org/package/transformers
+ #http://hackage.haskell.org/package/web-routes-wai
+ #http://hackage.haskell.org/package/web-page
+
+ # ref <stockholm/krebs/3modules>, services.openssh.knownHosts.github*
+ (json https://api.github.com/meta)
+
+ # ref <nixpkgs/pkgs/tools/security/ssh-audit>
+ (json https://api.github.com/repos/arthepsy/ssh-audit/tags)
+
+ # 2014-12-20 ref src/nixpkgs/pkgs/tools/networking/tlsdate/default.nix
+ (json https://api.github.com/repos/ioerror/tlsdate/tags)
+
+ # ref src/nixpkgs/pkgs/tools/admin/sec/default.nix
+ (json https://api.github.com/repos/simple-evcorr/sec/tags)
+
+ # <stockholm/tv/2configs/xserver/xserver.conf.nix>
+ # is derived from `configFile` in:
+ https://raw.githubusercontent.com/NixOS/nixpkgs/master/nixos/modules/services/x11/xserver.nix
+
+ https://www.rabbitmq.com/changelog.html
+
+ (urigrep' ["software-resources"] https://semiconductor.samsung.com/consumer-storage/support/tools/)
+ ];
+ hooksFile = builtins.toFile "hooks.py" ''
+ import subprocess
+ import urlwatch
+
+ class SystemFilter(urlwatch.filters.FilterBase):
+ """Filter for piping data through an external process"""
+
+ __kind__ = 'system'
+
+ __supported_subfilters__ = {
+ 'command': 'shell command line to tranform data',
+ }
+
+ __default_subfilter__ = 'command'
+
+ def filter(self, data, subfilter=None):
+ if 'command' not in subfilter:
+ raise ValueError('{} filter needs a command'.format(self.__kind__))
+
+ proc = subprocess.Popen(
+ subfilter['command'],
+ shell=True,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+
+ (stdout, stderr) = proc.communicate(data.encode())
+
+ if proc.returncode != 0:
+ raise RuntimeError(
+ "system filter returned non-zero exit status %d; stderr:\n"
+ % proc.returncode
+ + stderr.decode()
+ )
+
+ return stdout.decode()
+ '';
+ };
+}
diff --git a/configs/vim.nix b/configs/vim.nix
new file mode 100644
index 0000000..b06b196
--- /dev/null
+++ b/configs/vim.nix
@@ -0,0 +1,184 @@
+{ config, lib, mylib, pkgs, ... }: let {
+ body = {
+ environment.systemPackages = [
+ vim-wrapper
+ ];
+
+ environment.etc.vimrc.source = vimrc;
+
+ environment.variables.EDITOR = lib.mkForce "vim";
+ environment.variables.VIMINIT = ":so /etc/vimrc";
+ };
+
+ base-plugins = [
+ pkgs.tv.vimPlugins.file-line
+ pkgs.tv.vimPlugins.hack
+ pkgs.vimPlugins.undotree
+ (pkgs.tv.vim.makePlugin (pkgs.write "vim-tv-base" {
+ "/ftplugin/haskell.vim".text = ''
+ if exists("g:vim_tv_ftplugin_haskell_loaded")
+ finish
+ endif
+ let g:vim_tv_ftplugin_haskell_loaded = 1
+
+ setlocal iskeyword+='
+ '';
+ }))
+ ];
+
+ extra-plugins = [
+ pkgs.tv.vimPlugins.elixir
+ pkgs.tv.vimPlugins.fzf
+ pkgs.tv.vimPlugins.jq
+ pkgs.tv.vimPlugins.nix
+ pkgs.tv.vimPlugins.showsyntax
+ pkgs.tv.vimPlugins.tv
+ pkgs.tv.vimPlugins.vim
+ pkgs.vimPlugins.fzfWrapper
+ pkgs.vimPlugins.vim-nftables
+ ];
+
+ dirs = {
+ backupdir = "$HOME/.cache/vim/backup";
+ swapdir = "$HOME/.cache/vim/swap";
+ undodir = "$HOME/.cache/vim/undo";
+ };
+ files = {
+ viminfo = "$HOME/.cache/vim/info";
+ };
+
+ need-dirs = let
+ dirOf = s:
+ let
+ out = lib.concatStringsSep "/" (lib.init (lib.splitString "/" s));
+ in assert out != ""; out;
+ alldirs = builtins.attrValues dirs ++ map dirOf (builtins.attrValues files);
+ in lib.unique (builtins.sort builtins.lessThan alldirs);
+
+ vim-wrapper = pkgs.symlinkJoin {
+ name = "vim";
+ paths = [
+ (pkgs.writeDashBin "vim" ''
+ set -efu
+ export FZF_DEFAULT_COMMAND='${pkgs.ripgrep}/bin/rg --files'
+ export PATH=$PATH:${lib.makeBinPath [
+ pkgs.fzf
+ pkgs.ripgrep
+ ]}
+ (umask 0077; exec ${pkgs.coreutils}/bin/mkdir -p ${toString need-dirs})
+ exec ${pkgs.vim}/bin/vim "$@"
+ '')
+ pkgs.vim
+ ];
+ };
+
+ vimrc = pkgs.writeText "vimrc" /* vim */ ''
+ vim9script
+
+ set nocompatible
+
+ set autoindent
+ set backspace=indent,eol,start
+ set backup
+ set backupdir=${dirs.backupdir}/
+ set directory=${dirs.swapdir}//
+ set hlsearch
+ set incsearch
+ set mouse=a
+ set noruler
+ set pastetoggle=<INS>
+ set runtimepath=${pkgs.tv.vim.makeRuntimePath base-plugins},$VIMRUNTIME
+ set shortmess+=I
+ set showcmd
+ set showmatch
+ set timeoutlen=0
+ set ttimeoutlen=0
+ set ttymouse=sgr
+ set undodir=${dirs.undodir}
+ set undofile
+ set undolevels=1000000
+ set undoreload=1000000
+ set viminfo='20,<1000,s100,h,n${files.viminfo}
+ set visualbell
+ set wildignore+=*.o,*.class,*.hi,*.dyn_hi,*.dyn_o
+ set wildmenu
+ set wildmode=longest,full
+
+ set runtimepath^=${pkgs.tv.vim.makeRuntimePath extra-plugins}
+ syntax on
+
+ set et ts=2 sts=2 sw=2
+
+ filetype plugin indent on
+
+ set t_Co=256
+ colorscheme hack
+
+ au Syntax * syn match Garbage containedin=ALL /\s\+$/
+ \ | syn match TabStop containedin=ALL /\t\+/
+ \ | syn keyword Todo containedin=ALL TODO
+
+ au BufRead,BufNewFile *.nix set ft=nix
+
+ au BufRead,BufNewFile /dev/shm/* set nobackup nowritebackup noswapfile
+
+ cnoremap <C-A> <Home>
+
+ noremap <C-c> :q<cr>
+
+ nnoremap <esc>[5^ :tabp<cr>
+ nnoremap <esc>[6^ :tabn<cr>
+ nnoremap <esc>[5@ :tabm -1<cr>
+ nnoremap <esc>[6@ :tabm +1<cr>
+
+ nnoremap <f1> :tabp<cr>
+ nnoremap <f2> :tabn<cr>
+ imap <f1> <esc><f1>
+ imap <f2> <esc><f2>
+
+ nnoremap <S-f1> :tabm -1<cr>
+ nnoremap <S-f2> :tabm +1<cr>
+ imap <S-f1> <esc><S-f1>
+ imap <S-f2> <esc><S-f2>
+
+ noremap <f3> :ShowSyntax<cr>
+
+ # <C-{Up,Down,Right,Left}>
+ noremap <esc>Oa <nop> | noremap! <esc>Oa <nop>
+ noremap <esc>Ob <nop> | noremap! <esc>Ob <nop>
+ noremap <esc>Oc <nop> | noremap! <esc>Oc <nop>
+ noremap <esc>Od <nop> | noremap! <esc>Od <nop>
+ # <[C]S-{Up,Down,Right,Left}>
+ noremap <esc>[a <nop> | noremap! <esc>[a <nop>
+ noremap <esc>[b <nop> | noremap! <esc>[b <nop>
+ noremap <esc>[c <nop> | noremap! <esc>[c <nop>
+ noremap <esc>[d <nop> | noremap! <esc>[d <nop>
+ vnoremap u <nop>
+
+ # fzf
+ nnoremap <esc>q :Buffers<cr>
+ nnoremap <esc>f :Files<cr>
+ nnoremap <esc>w :Rg<cr>
+
+ # edit alternate buffer
+ # For some reason neither putting <ctrl>6 nor <ctrl>^ works here...
+ nnoremap <esc>a 
+
+ if $TOUCHSCREEN == "1"
+ nnoremap <ScrollWheelUp> <C-y>
+ nnoremap <ScrollWheelDown> <C-e>
+ nnoremap <C-ScrollWheelUp> 3<C-y>
+ nnoremap <C-ScrollWheelDown> 3<C-e>
+ nnoremap <S-ScrollWheelUp> 3<C-y>
+ nnoremap <S-ScrollWheelDown> 3<C-e>
+ nnoremap <C-S-ScrollWheelUp> <PageUp>
+ nnoremap <C-S-ScrollWheelDown> <PageDown>
+ endif
+
+ # remember last position
+ autocmd BufReadPost *
+ \ if line("'\"") > 0 && line("'\"") <= line("$") |
+ \ exe "normal! g`\"" |
+ \ endif
+ '';
+}
diff --git a/configs/weechat-server.nix b/configs/weechat-server.nix
new file mode 100644
index 0000000..41f157c
--- /dev/null
+++ b/configs/weechat-server.nix
@@ -0,0 +1,24 @@
+{ config, pkgs, ... }: {
+ users.users.tv.packages = [
+ (pkgs.writers.writeDashBin "weechat-client" ''
+ set -efu
+ exec ${pkgs.tmux}/bin/tmux attach -t weechat
+ '')
+ ];
+ systemd.services.weechat = {
+ wantedBy = [ "multi-user.target" ];
+ environment = {
+ TERM = "rxvt-unicode-256color";
+ };
+ serviceConfig = {
+ ExecStart = "${pkgs.tmux}/bin/tmux new -d -s weechat ${pkgs.weechat}/bin/weechat";
+ OOMScoreAdjust = -1000;
+ Restart = "always";
+ RestartSec = "100ms";
+ Type = "forking";
+ StartLimitBurst = 0;
+ User = "tv";
+ WorkingDirectory = "/home/tv";
+ };
+ };
+}
diff --git a/configs/wiregrill.nix b/configs/wiregrill.nix
new file mode 100644
index 0000000..55bb6f5
--- /dev/null
+++ b/configs/wiregrill.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }: let
+ cfg = {
+ enable = cfg.net != null;
+ net = config.krebs.build.host.nets.wiregrill or null;
+ };
+ toCidrNotation = ip: "${ip.addr}/${toString ip.prefixLength}";
+in
+ lib.mkIf cfg.enable {
+ networking.wireguard.interfaces.wiregrill = {
+ ips =
+ lib.optional (cfg.net.ip4 != null) cfg.net.ip4.addr ++
+ lib.optional (cfg.net.ip6 != null) cfg.net.ip6.addr;
+ listenPort = 51820;
+ privateKeyFile = "${config.krebs.secret.directory}/wiregrill.key";
+ allowedIPsAsRoutes = true;
+ peers = lib.mapAttrsToList
+ (_: host: {
+ allowedIPs = host.nets.wiregrill.wireguard.subnets;
+ endpoint =
+ lib.mkIf (host.nets.wiregrill.via != null) (host.nets.wiregrill.via.ip4.addr + ":${toString host.nets.wiregrill.wireguard.port}");
+ persistentKeepalive = lib.mkIf (host.nets.wiregrill.via != null) 61;
+ publicKey =
+ lib.replaceStrings ["\n"] [""] host.nets.wiregrill.wireguard.pubkey;
+ })
+ (lib.filterAttrs (_: h: lib.hasAttr "wiregrill" h.nets) config.krebs.hosts);
+ };
+ systemd.network.networks.wiregrill = {
+ matchConfig.Name = "wiregrill";
+ address =
+ lib.optional (cfg.net.ip4 != null) (toCidrNotation cfg.net.ip4) ++
+ lib.optional (cfg.net.ip6 != null) (toCidrNotation cfg.net.ip6);
+ };
+ tv.iptables.extra.filter.INPUT = [
+ "-p udp --dport ${toString cfg.net.wireguard.port} -j ACCEPT"
+ ];
+ }
diff --git a/configs/xdg.nix b/configs/xdg.nix
new file mode 100644
index 0000000..33f35f0
--- /dev/null
+++ b/configs/xdg.nix
@@ -0,0 +1,10 @@
+{ config, lib, ... }: {
+ environment.variables.XDG_RUNTIME_DIR = "/run/xdg/$LOGNAME";
+
+ systemd.tmpfiles.rules = let
+ forUsers = lib.flip map users;
+ isUser = { name, group, ... }:
+ name == "root" || lib.hasSuffix "users" group;
+ users = builtins.filter isUser (builtins.attrValues config.users.users);
+ in forUsers (u: "d /run/xdg/${u.name} 0700 ${u.name} ${u.group} -");
+}
diff --git a/configs/xserver/Xmodmap.nix b/configs/xserver/Xmodmap.nix
new file mode 100644
index 0000000..8e555e9
--- /dev/null
+++ b/configs/xserver/Xmodmap.nix
@@ -0,0 +1,28 @@
+{ config, pkgs, ... }:
+
+with import ./lib;
+
+pkgs.writeText "Xmodmap" ''
+ !keycode 66 = Caps_Lock
+ !remove Lock = Caps_Lock
+ clear Lock
+
+ ! caps lock
+ keycode 66 = Mode_switch
+
+ keycode 13 = 4 dollar EuroSign cent
+ keycode 30 = u U udiaeresis Udiaeresis
+ keycode 32 = o O odiaeresis Odiaeresis
+ keycode 38 = a A adiaeresis Adiaeresis
+ keycode 39 = s S ssharp
+
+ keycode 33 = p P Greek_pi Greek_PI
+ keycode 40 = d D Greek_delta Greek_DELTA
+ keycode 46 = l L Greek_lambda Greek_LAMBDA
+
+ keycode 54 = c C cacute Cacute
+
+ ! BULLET OPERATOR
+ keycode 17 = 8 asterisk U2219
+ keycode 27 = r R r U211D
+''
diff --git a/configs/xserver/default.nix b/configs/xserver/default.nix
new file mode 100644
index 0000000..df83ba5
--- /dev/null
+++ b/configs/xserver/default.nix
@@ -0,0 +1,166 @@
+{ config, pkgs, ... }@args: let
+ cfg = {
+ cacheDir = cfg.dataDir;
+ configDir = "/var/empty";
+ dataDir = "/run/xdg/${cfg.user.name}/xmonad";
+ user = config.krebs.build.user;
+ xmonad.pkg = pkgs.haskellPackages.xmonad-tv.overrideAttrs (_: {
+ au = {
+ XMONAD_BUILD_SCREEN_WIDTH = 1920;
+ XMONAD_BUILD_TERM_FONT_WIDTH = 10;
+ XMONAD_BUILD_TERM_FONT = "xft:Input Mono:size=12:style=Regular";
+ XMONAD_BUILD_TERM_PADDING = 2;
+ };
+ }.${config.krebs.build.host.name} or {
+ XMONAD_BUILD_SCREEN_WIDTH = 1366;
+ XMONAD_BUILD_TERM_FONT_WIDTH = 6;
+ XMONAD_BUILD_TERM_FONT = "-*-clean-*-*-*-*-*-*-*-*-*-*-iso10646-1";
+ XMONAD_BUILD_TERM_PADDING = 2;
+ });
+ };
+in {
+
+ imports = [
+ ./sxiv.nix
+ ./urxvt.nix
+ ];
+
+ environment.systemPackages = [
+ pkgs.ff
+ pkgs.font-size
+ pkgs.gitAndTools.qgit
+ pkgs.mpv
+ pkgs.xdotool
+ pkgs.xsel
+ pkgs.zathura
+ ];
+
+ fonts.fonts = [
+ pkgs.xorg.fontschumachermisc
+ ];
+
+ services.xserver = {
+
+ # Don't install feh into systemPackages
+ # refs <nixpkgs/nixos/modules/services/x11/desktop-managers>
+ desktopManager.session = mkForce [];
+
+ displayManager.lightdm.enable = mkForce false;
+ displayManager.job.execCmd = mkForce "derp";
+
+ enable = true;
+ display = mkForce 11;
+ tty = mkForce 11;
+ };
+
+ systemd.services.display-manager.enable = false;
+
+ systemd.services.xmonad = let
+ xmonad = "${cfg.xmonad.pkg}/bin/xmonad";
+ xmonad-start = pkgs.writeDash "xmonad-start" ''
+ ${pkgs.coreutils}/bin/mkdir -p "$XMONAD_CACHE_DIR"
+ ${pkgs.coreutils}/bin/mkdir -p "$XMONAD_CONFIG_DIR"
+ ${pkgs.coreutils}/bin/mkdir -p "$XMONAD_DATA_DIR"
+
+ f=$HOME/.dbus/session-bus/$(${pkgs.coreutils}/bin/cat /etc/machine-id)-${
+ toString config.services.xserver.display
+ }
+ if test -e "$f" &&
+ . "$f" &&
+ ${pkgs.coreutils}/bin/kill -0 "$DBUS_SESSION_BUS_PID"
+ then
+ export DBUS_SESSION_BUS_ADDRESS
+ else
+ eval "$(${pkgs.dbus.lib}/bin/dbus-launch --sh-syntax)"
+ fi
+
+ exec ${xmonad}
+ '';
+ xmonad-ready = pkgs.writeDash "xmonad-ready" ''
+ ${pkgs.systemd}/bin/systemd-notify --ready
+ {
+ ${pkgs.xorg.xhost}/bin/xhost +SI:localuser:${cfg.user.name}
+ ${pkgs.xorg.xhost}/bin/xhost -LOCAL:
+ } &
+ ${pkgs.xorg.xmodmap}/bin/xmodmap ${import ./Xmodmap.nix args} &
+ ${pkgs.xorg.xsetroot}/bin/xsetroot -solid '#1c1c1c' &
+ wait
+ '';
+ in {
+ wantedBy = [ "graphical.target" ];
+ requires = [ "xserver.service" ];
+ environment = {
+ DISPLAY = ":${toString config.services.xserver.display}";
+ FZMENU_FZF_DEFAULT_OPTS = toString [
+ "--color=dark,border:126,bg+:090"
+ "--inline-info"
+ ];
+ XMONAD_CACHE_DIR = cfg.cacheDir;
+ XMONAD_CONFIG_DIR = cfg.configDir;
+ XMONAD_DATA_DIR = cfg.dataDir;
+ XMONAD_STARTUP_HOOK = xmonad-ready;
+ XMONAD_WORKSPACES0_FILE = pkgs.writeJSON "xmonad-workspaces0.json" [
+ "Dashboard" # we start here
+ "23"
+ "cr"
+ "ff"
+ "hack"
+ "im"
+ "mail"
+ "stockholm"
+ "za" "zh" "zj" "zs"
+ ];
+ };
+ path = [
+ config.tv.slock.package
+ pkgs.flameshot-once-tv
+ pkgs.pulseaudio.out
+ pkgs.rxvt_unicode
+ pkgs.xcalib
+ "/run/wrappers" # for su
+ ];
+ serviceConfig = {
+ ExecStart = "@${xmonad-start} xmonad-${currentSystem}";
+ ExecStop = "@${xmonad} xmonad-${currentSystem} --shutdown";
+ SyslogIdentifier = "xmonad";
+ User = cfg.user.name;
+ WorkingDirectory = cfg.user.home;
+
+ NotifyAccess = "all";
+ Type = "notify";
+ };
+ };
+
+ systemd.services.xserver = {
+ after = [
+ "acpid.service"
+ "local-fs.target"
+ "systemd-udev-settle.service"
+ ];
+ wants = [
+ "systemd-udev-settle.service"
+ ];
+ restartIfChanged = false;
+ environment = {
+ LD_LIBRARY_PATH = concatStringsSep ":" ([ "/run/opengl-driver/lib" ]
+ ++ concatLists (catAttrs "libPath" config.services.xserver.drivers));
+ };
+ serviceConfig = {
+ SyslogIdentifier = "xserver";
+ ExecStart = toString [
+ "${pkgs.xorg.xorgserver}/bin/X"
+ ":${toString config.services.xserver.display}"
+ "vt${toString config.services.xserver.tty}"
+ "-config ${import ./xserver.conf.nix args}"
+ "-logfile /dev/null -logverbose 0 -verbose 3"
+ "-nolisten tcp"
+ "-xkbdir ${config.services.xserver.xkbDir}"
+ ];
+ };
+ };
+
+ tv.slock = {
+ enable = true;
+ user = cfg.user;
+ };
+}
diff --git a/configs/xserver/sxiv.nix b/configs/xserver/sxiv.nix
new file mode 100644
index 0000000..13cfd65
--- /dev/null
+++ b/configs/xserver/sxiv.nix
@@ -0,0 +1,11 @@
+{ config, pkgs, ... }: let
+ cfg.user = config.krebs.build.user;
+in {
+ tv.Xresources = {
+ "Sxiv.foreground" = "#232323";
+ "Sxiv.background" = "#424242";
+ };
+ users.users.${cfg.user.name}.packages = [
+ pkgs.sxiv
+ ];
+}
diff --git a/configs/xserver/urxvt.nix b/configs/xserver/urxvt.nix
new file mode 100644
index 0000000..c4e619d
--- /dev/null
+++ b/configs/xserver/urxvt.nix
@@ -0,0 +1,72 @@
+{ config, pkgs, ... }: let
+ cfg.user = config.krebs.build.user;
+in {
+ systemd.services.urxvtd = {
+ wantedBy = [ "graphical.target" ];
+ restartIfChanged = false;
+ serviceConfig = {
+ SyslogIdentifier = "urxvtd";
+ ExecStart = "${pkgs.rxvt_unicode}/bin/urxvtd";
+ Restart = "always";
+ RestartSec = "2s";
+ StartLimitBurst = 0;
+ User = cfg.user.name;
+ };
+ };
+ tv.Xresources = {
+ "URxvt*cutchars" = ''"\\`\"'&()*,;<=>?@[]^{|}‘’"'';
+ "URxvt*eightBitInput" = "false";
+ "URxvt*font" = "-*-clean-*-*-*-*-*-*-*-*-*-*-iso10646-1";
+ "URxvt*boldFont" = "-*-clean-*-*-*-*-*-*-*-*-*-*-iso10646-1";
+ "URxvt*scrollBar" = "false";
+ "URxvt*background" = "#050505";
+ "URxvt*foreground" = "#d0d7d0";
+ "URxvt*cursorColor" = "#f042b0";
+ "URxvt*cursorColor2" = "#f0b000";
+ "URxvt*cursorBlink" = "off";
+ "URxvt*jumpScroll" = "true";
+ "URxvt*allowSendEvents" = "false";
+ "URxvt*charClass" = "33:48,37-38:48,45-47:48,61:48,63-64:48";
+ "URxvt*cutNewline" = "False";
+ "URxvt*cutToBeginningOfLine" = "False";
+
+ "URxvt*color0" = "#232342";
+ "URxvt*color3" = "#c07000";
+ "URxvt*color4" = "#4040c0";
+ "URxvt*color7" = "#c0c0c0";
+ "URxvt*color8" = "#707070";
+ "URxvt*color9" = "#ff6060";
+ "URxvt*color10" = "#70ff70";
+ "URxvt*color11" = "#ffff70";
+ "URxvt*color12" = "#7070ff";
+ "URxvt*color13" = "#ff50ff";
+ "URxvt*color14" = "#70ffff";
+ "URxvt*color15" = "#ffffff";
+
+ "URxvt*iso14755" = "False";
+
+ "URxvt*urgentOnBell" = "True";
+ "URxvt*visualBell" = "True";
+
+ # ref https://github.com/muennich/urxvt-perls
+ "URxvt*perl-ext" = "default,url-select";
+ "URxvt*keysym.M-u" = "perl:url-select:select_next";
+ "URxvt*url-select.launcher" =
+ "/etc/profiles/per-user/${cfg.user.name}/bin/ff -new-tab";
+ "URxvt*url-select.underline" = "true";
+ "URxvt*colorUL" = "#4682B4";
+ "URxvt.perl-lib" = "${pkgs.urxvt_perls}/lib/urxvt/perl";
+ "URxvt*saveLines" = "10000";
+ "URxvt*modifier" = "mod1";
+
+ "root-urxvt*background" = "#230000";
+ "root-urxvt*foreground" = "#e0c0c0";
+ "root-urxvt*BorderColor" = "#400000";
+ "root-urxvt*color0" = "#800000";
+
+ "fzmenu-urxvt*background" = "rgb:42/23/42";
+ "fzmenu-urxvt*externalBorder" = "1";
+ "fzmenu-urxvt*geometry" = "70x9";
+ "fzmenu-urxvt*internalBorder" = "1";
+ };
+}
diff --git a/configs/xserver/xkiller.nix b/configs/xserver/xkiller.nix
new file mode 100644
index 0000000..2f97630
--- /dev/null
+++ b/configs/xserver/xkiller.nix
@@ -0,0 +1,14 @@
+{ pkgs, ... }: {
+
+ services.acpid.enable = true;
+ services.acpid.handlers.xkiller = {
+ action = /* sh */ ''
+ event=($1)
+ if test "''${event[2]}" = 00000080; then
+ ${pkgs.systemd}/bin/systemd-cat -t xkiller ${pkgs.xkiller}
+ fi
+ '';
+ event = "button/prog1";
+ };
+
+}
diff --git a/configs/xserver/xserver.conf.nix b/configs/xserver/xserver.conf.nix
new file mode 100644
index 0000000..3a80567
--- /dev/null
+++ b/configs/xserver/xserver.conf.nix
@@ -0,0 +1,38 @@
+{ config, pkgs, ... }:
+
+let
+ cfg = config.services.xserver;
+in
+
+pkgs.stdenv.mkDerivation {
+ name = "xserver.conf";
+
+ fontPath = optionalString (cfg.fontPath != null)
+ ''FontPath "${toString cfg.fontPath}"'';
+
+ inherit (cfg) config;
+
+ buildCommand =
+ ''
+ echo 'Section "Files"' >> $out
+ echo $fontPath >> $out
+
+ for i in ${toString config.fonts.fonts}; do
+ if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then
+ for j in $(find $i -name fonts.dir); do
+ echo " FontPath \"$(dirname $j)\"" >> $out
+ done
+ fi
+ done
+
+ for i in $(find ${toString cfg.modules} -type d); do
+ if test $(echo $i/*.so* | wc -w) -ne 0; then
+ echo " ModulePath \"$i\"" >> $out
+ fi
+ done
+
+ echo 'EndSection' >> $out
+
+ echo "$config" >> $out
+ '';
+}
diff --git a/configs/xsessions/default.nix b/configs/xsessions/default.nix
new file mode 100644
index 0000000..384c9c5
--- /dev/null
+++ b/configs/xsessions/default.nix
@@ -0,0 +1,5 @@
+{
+ imports = [
+ ./urxvtd.nix
+ ];
+}
diff --git a/configs/xsessions/urxvtd.nix b/configs/xsessions/urxvtd.nix
new file mode 100644
index 0000000..de16a63
--- /dev/null
+++ b/configs/xsessions/urxvtd.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }: {
+ systemd.user.sockets.urxvtd = {
+ wantedBy = [ "sockets.target" ];
+ socketConfig.ListenStream = "%t/urxvtd";
+ };
+ systemd.user.services.urxvtd = {
+ restartIfChanged = false;
+ environment = {
+ RXVT_SOCKET = "%t/urxvtd";
+ };
+ serviceConfig = {
+ ExecStart = "${pkgs.rxvt_unicode}/bin/urxvtd";
+ };
+ };
+}