about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAzat Bahawi <azat@bahawi.net>2022-09-10 15:49:40 +0300
committerAzat Bahawi <azat@bahawi.net>2022-09-10 15:49:40 +0300
commitdcb02e0ea80821d60185569fb88ec66bea3f3f08 (patch)
treea2ab8943f94ce8f1ae1359051c7e42551c80806e
parent2022-09-07 (diff)
2022-09-10
-rw-r--r--configurations/melian/default.nix88
-rw-r--r--flake.nix5
-rw-r--r--lib/my.nix1
-rw-r--r--modules/nixfiles/common/nix/default.nix9
-rw-r--r--modules/nixfiles/common/users.nix1
-rw-r--r--modules/nixfiles/common/xdg.nix126
-rw-r--r--modules/nixfiles/default.nix1
-rw-r--r--modules/nixfiles/emacs/doom/config.el9
-rw-r--r--modules/nixfiles/firefox/userContent.css66
-rw-r--r--modules/nixfiles/games/minecraft.nix10
-rw-r--r--modules/nixfiles/monitoring/dashboards/endlessh.json1457
-rw-r--r--modules/nixfiles/monitoring/default.nix20
-rw-r--r--modules/nixfiles/nsd.nix1
-rw-r--r--modules/nixfiles/password-store.nix2
-rw-r--r--modules/nixfiles/profiles/headful.nix19
-rw-r--r--modules/nixfiles/solaar.nix51
-rw-r--r--modules/nixfiles/x11.nix35
17 files changed, 1690 insertions, 211 deletions
diff --git a/configurations/melian/default.nix b/configurations/melian/default.nix
index fb9b6e6..229b56a 100644
--- a/configurations/melian/default.nix
+++ b/configurations/melian/default.nix
@@ -47,7 +47,6 @@ with lib; {
 
     beets.enable = true;
     bluetooth.enable = true;
-    chromium.enable = true;
     libvirtd.enable = true;
     mpd.enable = true;
     qutebrowser.enable = true;
@@ -70,47 +69,47 @@ with lib; {
       maildirBasePath = "${config.my.home}/mail";
 
       accounts = let
-        base = {
-          mbsync = {
-            enable = true;
-            create = "both";
-            expunge = "both";
-            patterns = ["*"];
-          };
-          msmtp.enable = true;
-          mu.enable = true;
-        };
+        mkAccount = attrs:
+          mkMerge [
+            {
+              mbsync = {
+                enable = true;
+                create = "both";
+                expunge = "both";
+                patterns = ["*"];
+              };
+              msmtp.enable = true;
+              mu.enable = true;
+            }
+            attrs
+          ];
 
         pass = path: "${pkgs.pass}/bin/pass show ${path}";
       in {
-        shire =
-          base
-          // {
-            address = my.email;
-            gpg = {
-              inherit (my.pgp) key;
-              signByDefault = true;
-              encryptByDefault = false;
-            };
-
-            primary = true;
-
-            imap.host = "shire.me";
-            smtp.host = "shire.me";
-            userName = "azahi@shire.me";
-            passwordCommand = pass "email/shire.me/azahi";
+        shire = mkAccount {
+          address = my.email;
+          gpg = {
+            inherit (my.pgp) key;
+            signByDefault = true;
+            encryptByDefault = false;
           };
 
-        yahoo =
-          base
-          // {
-            address = "a.gondor@yahoo.com";
+          primary = true;
 
-            imap.host = "imap.yahoo.com";
-            smtp.host = "smtp.yahoo.com";
-            userName = "a.gondor@yahoo.com";
-            passwordCommand = pass "email/yahoo.com/a.gondor";
-          };
+          imap.host = "shire.me";
+          smtp.host = "shire.me";
+          userName = "azahi@shire.me";
+          passwordCommand = pass "email/shire.me/azahi";
+        };
+
+        yahoo = mkAccount {
+          address = "a.gondor@yahoo.com";
+
+          imap.host = "imap.yahoo.com";
+          smtp.host = "smtp.yahoo.com";
+          userName = "a.gondor@yahoo.com";
+          passwordCommand = pass "email/yahoo.com/a.gondor";
+        };
       };
     };
 
@@ -240,14 +239,15 @@ with lib; {
   };
 
   services = {
-    tlp = {
-      enable = false; # TODO Test this again.
-      settings = {
-        START_CHARGE_THRESH_BAT0 = 75;
-        STOP_CHARGE_THRESH_BAT0 = 80;
-        RESTORE_THRESHOLDS_ON_BAT = 1;
-      };
-    };
+    # No need for this anymore but it kept just in case.
+    # tlp = {
+    #   enable = true;
+    #   settings = {
+    #     START_CHARGE_THRESH_BAT0 = 75;
+    #     STOP_CHARGE_THRESH_BAT0 = 80;
+    #     RESTORE_THRESHOLDS_ON_BAT = 1;
+    #   };
+    # };
 
     throttled.enable = mkForce false;
 
diff --git a/flake.nix b/flake.nix
index 8d7981a..dce2869 100644
--- a/flake.nix
+++ b/flake.nix
@@ -222,7 +222,7 @@
     with inputs; let
       lib = nixpkgs.lib.extend (import ./lib);
     in
-      flake-utils.lib.eachSystem ["x86_64-linux"]
+      flake-utils.lib.eachSystem ["x86_64-linux" "aarch64-linux"]
       (system: let
         pkgs = import nixpkgs {
           inherit system;
@@ -240,6 +240,7 @@
           inherit (self.checks.${system}.preCommit) shellHook;
         };
 
+        # Very opinionated but works fast and doesn't get in a way like nixfmt.
         formatter = pkgs.alejandra;
 
         checks.preCommit = pre-commit-hooks.lib.${system}.run {
@@ -254,6 +255,7 @@
             shellcheck.enable = true;
             shfmt.enable = true;
             statix.enable = true;
+            # nix-linter.enable = true; # Takes annoyingly long time to parse stuff.
           };
         };
       })
@@ -265,6 +267,7 @@
         nixosConfigurations =
           import ./configurations {inherit inputs lib;};
 
+        # TODO Make it so self.pckages also can use this.
         overlays.default = final: _: {
           UltimMC = final.libsForQt5.callPackage ./packages/ultimmc.nix {};
           bruh = final.callPackage ./packages/bruh.nix {};
diff --git a/lib/my.nix b/lib/my.nix
index 977b70e..680d32e 100644
--- a/lib/my.nix
+++ b/lib/my.nix
@@ -166,6 +166,7 @@ with lib;
                 ipv6.address = "fd69::1:1";
                 publicKey = "@PUBLIC_KEY@";
               };
+              domains = with my.domain; ["minecraft.${shire}"];
             };
             yavanna = {
               isHeadless = true;
diff --git a/modules/nixfiles/common/nix/default.nix b/modules/nixfiles/common/nix/default.nix
index 3d320ae..04d4113 100644
--- a/modules/nixfiles/common/nix/default.nix
+++ b/modules/nixfiles/common/nix/default.nix
@@ -91,6 +91,7 @@ with lib; {
         // (with super; let
           np = nodePackages;
         in {
+          # Normalises package names.
           dockerfile-language-server = np.dockerfile-language-server-nodejs;
           editorconfig = editorconfig-core-c;
           inherit (np) bash-language-server;
@@ -116,14 +117,6 @@ with lib; {
   environment = {
     sessionVariables.NIX_SHELL_PRESERVE_PROMPT = "1";
 
-    etc = {
-      nixpkgs.source = inputs.nixpkgs;
-
-      gc-roots.text =
-        concatMapStrings (x: x + "\n")
-        (with inputs; [nixpkgs nixpkgs-master nixpkgs-stable]);
-    };
-
     systemPackages = with pkgs;
       optionals config.profile.headful [
         nix-top
diff --git a/modules/nixfiles/common/users.nix b/modules/nixfiles/common/users.nix
index a3626dd..e312477 100644
--- a/modules/nixfiles/common/users.nix
+++ b/modules/nixfiles/common/users.nix
@@ -15,7 +15,6 @@ with lib; {
         isNormalUser = true;
         uid = 1000;
         description = my.fullname;
-        # TODO Consider switching to passwordFile
         inherit (my) hashedPassword;
         openssh.authorizedKeys.keys = [my.ssh.key];
         extraGroups = ["wheel"];
diff --git a/modules/nixfiles/common/xdg.nix b/modules/nixfiles/common/xdg.nix
index c05f5e3..72a8e4c 100644
--- a/modules/nixfiles/common/xdg.nix
+++ b/modules/nixfiles/common/xdg.nix
@@ -15,72 +15,70 @@ with lib; {
     (mkAliasOptionModule ["userDirs"] (withBase "userDirs"))
   ];
 
-  hm = {
-    xdg = mkMerge [
-      {
-        enable = true;
+  hm.xdg = mkMerge [
+    {
+      enable = true;
 
-        userDirs = let
-          inherit (config.my) home;
-          tmp = home + "/tmp";
-        in {
-          enable = true;
+      userDirs = let
+        inherit (config.my) home;
+        tmp = home + "/tmp";
+      in {
+        enable = true;
 
-          createDirectories = this.isHeadful;
+        createDirectories = this.isHeadful;
 
-          desktop = tmp;
-          documents = "${home}/doc";
-          download = tmp;
-          music = tmp;
-          pictures = tmp;
-          videos = tmp;
-          templates = tmp;
-          publicShare = "${home}/share";
-        };
-      }
-      (mkIf this.isHeadful {
-        mimeApps = let
-          images = [
-            "image/bmp"
-            "image/gif"
-            "image/jpeg"
-            "image/jpg"
-            "image/png"
-            "image/svg+xml"
-            "image/tiff"
-            "image/webp"
-          ];
-          media = [
-            "audio/aac"
-            "audio/flac"
-            "audio/mp3"
-            "audio/ogg"
-            "audio/wav"
-            "audio/webm"
-            "video/mkv"
-            "video/mp4"
-            "video/ogg"
-            "video/webm"
-            "video/x-matroska"
-          ];
-        in {
-          enable = true;
+        desktop = tmp;
+        documents = "${home}/doc";
+        download = tmp;
+        music = tmp;
+        pictures = tmp;
+        videos = tmp;
+        templates = tmp;
+        publicShare = "${home}/share";
+      };
+    }
+    (mkIf this.isHeadful {
+      mimeApps = let
+        images = [
+          "image/bmp"
+          "image/gif"
+          "image/jpeg"
+          "image/jpg"
+          "image/png"
+          "image/svg+xml"
+          "image/tiff"
+          "image/webp"
+        ];
+        media = [
+          "audio/aac"
+          "audio/flac"
+          "audio/mp3"
+          "audio/ogg"
+          "audio/wav"
+          "audio/webm"
+          "video/mkv"
+          "video/mp4"
+          "video/ogg"
+          "video/webm"
+          "video/x-matroska"
+        ];
+      in {
+        enable = true;
 
-          defaultApplications =
-            mkMerge
-            (mapAttrsToList (n: ms: genAttrs ms (_: ["${n}.desktop"])) {
-              aria2 = ["application/x-bittorrent" "x-scheme-handler/magnet"];
-              emacsclient = ["x-scheme-handler/mailto"];
-              firefox = [
-                "text/html"
-                "x-scheme-handler/http"
-                "x-scheme-handler/https"
-              ];
-              gwenview = images;
-              mpv = media;
-            });
-        };
-      })
-    ];
-  };
+        defaultApplications = mkMerge (mapAttrsToList
+          (n: ms: genAttrs ms (_: ["${n}.desktop"]))
+          {
+            aria2 = ["application/x-bittorrent" "x-scheme-handler/magnet"];
+            emacsclient = ["x-scheme-handler/mailto"];
+            firefox = [
+              "text/html"
+              "x-scheme-handler/http"
+              "x-scheme-handler/https"
+            ];
+            gwenview = images;
+            mpv = media;
+          });
+      };
+    })
+  ];
 }
diff --git a/modules/nixfiles/default.nix b/modules/nixfiles/default.nix
index 29d9d19..c85ae77 100644
--- a/modules/nixfiles/default.nix
+++ b/modules/nixfiles/default.nix
@@ -59,6 +59,7 @@
     ./searx.nix
     ./shadowsocks.nix
     ./soju.nix
+    ./solaar.nix
     ./sonarr.nix
     ./sound.nix
     ./subversion.nix
diff --git a/modules/nixfiles/emacs/doom/config.el b/modules/nixfiles/emacs/doom/config.el
index 29eabc9..92659e9 100644
--- a/modules/nixfiles/emacs/doom/config.el
+++ b/modules/nixfiles/emacs/doom/config.el
@@ -53,11 +53,10 @@
                                  ("DONE" . +org-todo-cancel)
                                  ("KILL" . +org-todo-cancel))))
 
-(add-hook! 'org-mode-hook
-  (lambda (&rest _)
-    (setq fill-column 80)
-    (electric-indent-local-mode -1))
-  'auto-fill-mode)
+(add-hook! 'org-mode-hook 'auto-fill-mode)
+
+(add-hook! 'org-mode-hook (lambda (&rest _)
+                            (setq fill-column 80)))
 
 (setq org-roam-directory "~/doc/roam/"
       org-roam-db-location (concat org-roam-directory ".db"))
diff --git a/modules/nixfiles/firefox/userContent.css b/modules/nixfiles/firefox/userContent.css
index 97365f9..81cf04e 100644
--- a/modules/nixfiles/firefox/userContent.css
+++ b/modules/nixfiles/firefox/userContent.css
@@ -1,31 +1,29 @@
-@-moz-document url(about:blank), url(about:home), url(about:newtab), url(about:privatebrowsing) {
-    html,
+@-moz-document media-document(all) {
     body {
-        background: var(--background) !important;
+        background-image: none !important;
+        background-color: var(--background) !important;
     }
+}
 
+@-moz-document regexp("about:(blank|home|newtab|privatebrowsing|welcome)") {
+    html,
     body {
-        display: none !important;
+        background: var(--background) !important;
     }
-}
 
-@-moz-document media-document(all) {
     body {
-        background-image: none !important;
-        background-color: var(--background) !important;
+        display: none !important;
     }
 }
 
-@-moz-document url-prefix(https://gitlab.com/)
-{
+@-moz-document regexp("https?:\/\/(\.*.)?gitlab(\..*)?\.(com|org).*") {
     code {
         font-family: var(--monospace-font-family) !important;
         font-size: var(--monospace-font-size) !important;
     }
 }
 
-@-moz-document url-prefix(https://github.com/), url-prefix(https://gist.github.com/)
-{
+@-moz-document regexp("https?:\/\/(.*\.)?github.com.*") {
     .footer {
         display: none !important;
     }
@@ -41,8 +39,15 @@
     }
 }
 
-@-moz-document regexp("https:\/\/.*\.stackexchange\.com\/.*"), url-prefix(https://askubuntu.com/), url-prefix(https://serverfault.com/), url-prefix(https://stackoverflow.com/), url-prefix(https://superuser.com/)
-{
+@-moz-document regexp("https?:\/\/.*(stack(exchange|overflow)|askubuntu|superuser|serverfault)\.com.*") {
+    html,
+    body {
+        --ff-mono: var(--monospace-font-family) !important;
+        --ff-sans: var(--sans-serif-font-family) !important;
+        --ff-serif: var(--serif-font-family) !important;
+    }
+
+    #announcement-banner,
     #footer,
     #left-sidebar,
     #noscript-warning,
@@ -55,6 +60,7 @@
     .d-flex.g4,
     .d-flex.s-btn-group,
     .js-add-link.comments-link,
+    .js-consent-banner,
     .js-dismissable-hero,
     .js-post-issue,
     .js-show-link.comments-link,
@@ -66,10 +72,6 @@
         display: none !important;
     }
 
-    #question-header .question-hyperlink {
-        font-family: var(--sans-serif-font-family);
-    }
-
     #mainbar {
         width: 100% !important;
     }
@@ -136,37 +138,33 @@
     }
 }
 
-@-moz-document url-prefix("https://jisho.org")
-{
+@-moz-document regexp("https?:\/\/jisho\.org.*") {
     header,
     footer {
         display: none !important;
     }
 }
 
-@-moz-document url-prefix("https://search.nixos.org")
-{
+@-moz-document regexp("https?:\/\/search\.nixos\.org.*") {
     .search-sidebar,
     footer.container {
         display: none !important;
     }
 }
 
-@-moz-document url-prefix(https://gog.com)
-{
+@-moz-document regexp("https?:\/\/gog.com.*") {
     .galaxy-section-wrapper {
         display: none !important;
     }
 }
 
-@-moz-document url-prefix("https://steamdb.info")
-{
+@-moz-document regexp("https?:\/\/steamdb\.info.*") {
     #steamdb-extension-protip {
         display: none !important;
     }
 }
 
-@-moz-document regexp("https:\/\/\.*\.hh\.ru/.*") {
+@-moz-document regexp("https:\/\/\.*\.hh\.ru.*") {
     .HH-Supernova-Footer,
     .index-dashboard-applicant__banners,
     .notification-manager,
@@ -176,8 +174,7 @@
     }
 }
 
-@-moz-document url-prefix("https://utaten.com/lyric")
-{
+@-moz-document regexp("https?:\/\/utaten\.com\/lyric/.*") {
     :root {
         --kana-font-size: 20px;
         --furigana-font-size: 14px;
@@ -218,8 +215,7 @@
     }
 }
 
-@-moz-document url-prefix("https://www.songsterr.com")
-{
+@-moz-document regexp("https?:\/\/www\.songsterr\.com.*") {
     #favorite,
     #fullscreen,
     #logo,
@@ -237,8 +233,7 @@
     }
 }
 
-@-moz-document url-prefix("https://tabs.ultimate-guitar.com")
-{
+@-moz-document regexp("https?:\/\/tabs\.ultimate-guitar\.com.*") {
     #comment,
     #shots,
     a[rel*="noreferrer"],
@@ -248,8 +243,7 @@
     }
 }
 
-@-moz-document url-prefix("https://developer.mozilla.org")
-{
+@-moz-document regexp("https?:\/\/developer\.mozilla\.org.*") {
     .main-document-header-container.top-navigation {
         display: none !important;
     }
@@ -259,7 +253,7 @@
     }
 }
 
-@-moz-document regexp("https:\/\/\.*\.wikipedia\.org/.*") {
+@-moz-document regexp("https:\/\/\.*\.wikipedia\.org.*") {
     #footer,
     #mp-topbanner,
     #mw-head,
diff --git a/modules/nixfiles/games/minecraft.nix b/modules/nixfiles/games/minecraft.nix
index 4f3908b..2fc9bd8 100644
--- a/modules/nixfiles/games/minecraft.nix
+++ b/modules/nixfiles/games/minecraft.nix
@@ -22,10 +22,11 @@ in {
   };
 
   # Configurations, opslist, whitelist and plugins are managed imperatively.
+  # TODO Make it declarative.
   config = mkMerge [
     (mkIf cfg.client.enable {
       hm.home.packages = with pkgs; [
-        UltimMC # I refuse to use a Microsoft account.
+        UltimMC # I refuse to use a Microsoft account. Using GitHub is painful enough.
         jre # Unfortunately, this cannot be provided as a PATH injection to UltimMC.
       ];
     })
@@ -36,7 +37,7 @@ in {
 
         package = pkgs.minecraftServers.purpur_1_19_2;
 
-        # TODO Make PR fixing trailing whitespace on this.
+        # TODO Make a PR fixing trailing whitespace on this.
         jvmOpts =
           (concatStringsSep " " [
             "-Xmx${cfg.server.memory}"
@@ -44,9 +45,10 @@ in {
             "--add-modules=jdk.incubator.vector"
           ])
           + " ";
-
-        openFirewall = true;
       };
+
+      # Found in /var/lib/minecraft/server.properties.
+      networking.firewall.allowedTCPPorts = [55565];
     })
   ];
 }
diff --git a/modules/nixfiles/monitoring/dashboards/endlessh.json b/modules/nixfiles/monitoring/dashboards/endlessh.json
new file mode 100644
index 0000000..0b47ee2
--- /dev/null
+++ b/modules/nixfiles/monitoring/dashboards/endlessh.json
@@ -0,0 +1,1457 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": {
+          "type": "datasource",
+          "uid": "grafana"
+        },
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "target": {
+          "limit": 100,
+          "matchAny": false,
+          "tags": [],
+          "type": "dashboard"
+        },
+        "type": "dashboard"
+      }
+    ]
+  },
+  "description": "",
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "gnetId": 15156,
+  "graphTooltip": 0,
+  "links": [],
+  "liveNow": false,
+  "panels": [
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 0,
+        "y": 0
+      },
+      "id": 36,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "/^Total number connections that endlessh trapped$/",
+          "values": false
+        },
+        "text": {},
+        "textMode": "auto"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Connections",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Seen"
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Seen"
+              }
+            ],
+            "match": "any",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "reduce",
+          "options": {
+            "includeTimeField": false,
+            "labelsToFields": false,
+            "mode": "reduceFields",
+            "reducers": [
+              "sum"
+            ]
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {},
+            "indexByName": {},
+            "renameByName": {
+              "Value #Seen (sum)": "Total number connections that endlessh trapped"
+            }
+          }
+        }
+      ],
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "s"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 4,
+        "y": 0
+      },
+      "id": 42,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "/^Time spent on endlessh$/",
+          "values": false
+        },
+        "text": {},
+        "textMode": "auto"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Trapped Time",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Trapped"
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Trapped"
+              }
+            ],
+            "match": "all",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Trapped": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "reduce",
+          "options": {
+            "includeTimeField": false,
+            "labelsToFields": false,
+            "mode": "reduceFields",
+            "reducers": [
+              "sum"
+            ]
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {},
+            "indexByName": {},
+            "renameByName": {
+              "Total": "Seconds spent on endlessh",
+              "Value #Trapped (sum)": "Time spent on endlessh"
+            }
+          }
+        }
+      ],
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          },
+          "unit": "bytes"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 8,
+        "y": 0
+      },
+      "id": 18,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "text": {},
+        "textMode": "auto"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum(increase(endlessh_sent_bytes_total{instance=~\"$host\",job=~\"$job\"}[$__range]))",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Bytes sent by endlessh",
+          "refId": "sent_bytes"
+        }
+      ],
+      "title": "Sent Bytes",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 12,
+        "y": 0
+      },
+      "id": 38,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "/^Unique IPs connected$/",
+          "values": false
+        },
+        "text": {},
+        "textMode": "auto"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Unique IPs",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Seen"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "reduce",
+          "options": {
+            "includeTimeField": false,
+            "labelsToFields": false,
+            "mode": "reduceFields",
+            "reducers": [
+              "count"
+            ]
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {},
+            "indexByName": {},
+            "renameByName": {
+              "Value #Seen (sum)": "Unique IPs connected",
+              "ip": ""
+            }
+          }
+        }
+      ],
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "links": [
+            {
+              "targetBlank": true,
+              "title": "whois",
+              "url": "https://search.arin.net/rdap/?query=${__value.text}"
+            }
+          ],
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 16,
+        "y": 0
+      },
+      "id": 45,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "/^Client IP of the latest connection$/",
+          "values": false
+        },
+        "text": {},
+        "textMode": "value"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Latest Connection",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Seen"
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Seen"
+              }
+            ],
+            "match": "any",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Time": {
+                "aggregations": [
+                  "lastNotNull"
+                ],
+                "operation": "aggregate"
+              },
+              "Value #Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "sortBy",
+          "options": {
+            "fields": {},
+            "sort": [
+              {
+                "field": "Time (lastNotNull)"
+              }
+            ]
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {
+              "instance": true,
+              "job": true
+            },
+            "indexByName": {},
+            "renameByName": {
+              "Time (lastNotNull)": "Time",
+              "Value #Seen (sum)": "Count",
+              "ip": "Client IP of the latest connection"
+            }
+          }
+        }
+      ],
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "min": 0,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "#EAB839",
+                "value": 10
+              },
+              {
+                "color": "red",
+                "value": 20
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 4,
+        "x": 20,
+        "y": 0
+      },
+      "id": 20,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "text": {},
+        "textMode": "auto"
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "sum((endlessh_client_open_count_total{instance=~\"$host\",job=~\"$job\"}) - (endlessh_client_closed_count_total{instance=~\"$host\",job=~\"$job\"} offset $__interval  or endlessh_client_open_count_total{instance=~\"$host\",job=~\"$job\"} * 0))",
+          "instant": false,
+          "interval": "",
+          "legendFormat": "Open Connections",
+          "refId": "current_open"
+        }
+      ],
+      "title": "Current Connections",
+      "type": "stat"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "stepAfter",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "min": -0.01,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 4,
+        "w": 12,
+        "x": 0,
+        "y": 3
+      },
+      "id": 30,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom",
+          "showLegend": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 20,
+          "refId": "A"
+        }
+      ],
+      "title": "Concurrent Connections",
+      "type": "timeseries"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": []
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 3
+      },
+      "id": 32,
+      "options": {
+        "displayLabels": [],
+        "legend": {
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true,
+          "values": [
+            "value",
+            "percent"
+          ]
+        },
+        "pieType": "pie",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "tooltip": {
+          "mode": "single",
+          "sort": "none"
+        }
+      },
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Connections by country",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Seen"
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Seen"
+              }
+            ],
+            "match": "any",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "country": {
+                "aggregations": [
+                  "last"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Seen (sum)": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "country (last)": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "rowsToFields",
+          "options": {}
+        }
+      ],
+      "type": "piechart"
+    },
+    {
+      "datasource": {
+        "type": "datasource",
+        "uid": "-- Dashboard --"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "continuous-GrYlRd"
+          },
+          "custom": {
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "#96D98D",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 12,
+        "w": 12,
+        "x": 0,
+        "y": 7
+      },
+      "id": 48,
+      "links": [],
+      "options": {
+        "basemap": {
+          "config": {},
+          "name": "Layer 0",
+          "type": "default"
+        },
+        "controls": {
+          "mouseWheelZoom": false,
+          "showAttribution": false,
+          "showDebug": false,
+          "showScale": false,
+          "showZoom": true
+        },
+        "layers": [
+          {
+            "config": {
+              "color": {
+                "field": "Connections",
+                "fixed": "dark-green"
+              },
+              "fillOpacity": 0.4,
+              "shape": "circle",
+              "showLegend": false,
+              "size": {
+                "field": "Connections",
+                "fixed": 5,
+                "max": 10,
+                "min": 2
+              },
+              "style": {
+                "color": {
+                  "field": "Connections",
+                  "fixed": "dark-green"
+                },
+                "size": {
+                  "field": "Connections",
+                  "fixed": 5,
+                  "max": 9,
+                  "min": 2
+                },
+                "text": {
+                  "field": "location (lastNotNull) (lastNotNull)",
+                  "fixed": "",
+                  "mode": "fixed"
+                }
+              }
+            },
+            "location": {
+              "geohash": "Geohash",
+              "mode": "geohash"
+            },
+            "name": "Layer 1",
+            "type": "markers"
+          }
+        ],
+        "tooltip": {
+          "mode": "details"
+        },
+        "view": {
+          "id": "zero",
+          "lat": 0,
+          "lon": 0,
+          "zoom": 1
+        }
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "datasource",
+            "uid": "-- Dashboard --"
+          },
+          "panelId": 49,
+          "refId": "A"
+        }
+      ],
+      "title": "Locations",
+      "transformations": [
+        {
+          "id": "filterByRefId",
+          "options": {
+            "include": "Seen"
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Seen"
+              }
+            ],
+            "match": "any",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Value #Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "geohash": {
+                "aggregations": [
+                  "lastNotNull"
+                ],
+                "operation": "groupby"
+              },
+              "location": {
+                "aggregations": [
+                  "lastNotNull"
+                ],
+                "operation": "aggregate"
+              }
+            }
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {},
+            "indexByName": {
+              "Value #geo (lastNotNull) (sum)": 2,
+              "geohash (lastNotNull)": 0,
+              "location (lastNotNull) (lastNotNull)": 1
+            },
+            "renameByName": {
+              "Value #Seen (sum)": "Connections",
+              "geohash": "Geohash",
+              "location (lastNotNull)": "Location"
+            }
+          }
+        }
+      ],
+      "type": "geomap"
+    },
+    {
+      "datasource": {
+        "type": "prometheus",
+        "uid": "${DS_PROMETHEUS}"
+      },
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "custom": {
+            "align": "auto",
+            "displayMode": "auto",
+            "filterable": true,
+            "inspect": false,
+            "minWidth": 50
+          },
+          "links": [],
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              }
+            ]
+          }
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Last Connection"
+            },
+            "properties": [
+              {
+                "id": "custom.minWidth",
+                "value": 150
+              },
+              {
+                "id": "unit",
+                "value": "dateTimeAsIso"
+              },
+              {
+                "id": "custom.align",
+                "value": "left"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "IP"
+            },
+            "properties": [
+              {
+                "id": "links",
+                "value": [
+                  {
+                    "targetBlank": true,
+                    "title": "search ARIN",
+                    "url": "https://search.arin.net/rdap/?query=${__data.fields.IP}"
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Trapped Time"
+            },
+            "properties": [
+              {
+                "id": "unit",
+                "value": "s"
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 11
+      },
+      "id": 49,
+      "options": {
+        "footer": {
+          "fields": "",
+          "reducer": [
+            "sum"
+          ],
+          "show": false
+        },
+        "frameIndex": 0,
+        "showHeader": true,
+        "sortBy": [
+          {
+            "desc": true,
+            "displayName": "Last Connection"
+          }
+        ]
+      },
+      "pluginVersion": "9.1.2",
+      "targets": [
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "(endlessh_client_open_count{instance=~\"$host\",job=~\"$job\"} - endlessh_client_open_count{instance=~\"$host\",job=~\"$job\"} offset $__interval) > 0 or (endlessh_client_open_count{instance=~\"$host\",job=~\"$job\"}!=0 unless endlessh_client_open_count{instance=~\"$host\",job=~\"$job\"} offset $__interval)",
+          "format": "table",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Seen {{ip}}",
+          "refId": "Seen"
+        },
+        {
+          "datasource": {
+            "type": "prometheus",
+            "uid": "${DS_PROMETHEUS}"
+          },
+          "exemplar": true,
+          "expr": "(endlessh_client_trapped_time_seconds{instance=~\"$host\",job=~\"$job\"} - endlessh_client_trapped_time_seconds{instance=~\"$host\",job=~\"$job\"} offset $__interval) > 0 or (endlessh_client_trapped_time_seconds{instance=~\"$host\",job=~\"$job\"}!=0 unless endlessh_client_trapped_time_seconds{instance=~\"$host\",job=~\"$job\"} offset $__interval)",
+          "format": "table",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Trapped {{ip}}",
+          "refId": "Trapped"
+        }
+      ],
+      "title": "Clients",
+      "transformations": [
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Seen"
+              },
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Value #Trapped"
+              }
+            ],
+            "match": "any",
+            "type": "include"
+          }
+        },
+        {
+          "id": "merge",
+          "options": {}
+        },
+        {
+          "id": "calculateField",
+          "options": {
+            "alias": "Seen",
+            "mode": "reduceRow",
+            "reduce": {
+              "include": [
+                "Value #Seen"
+              ],
+              "reducer": "sum"
+            }
+          }
+        },
+        {
+          "id": "calculateField",
+          "options": {
+            "alias": "Trapped",
+            "mode": "reduceRow",
+            "reduce": {
+              "include": [
+                "Value #Trapped"
+              ],
+              "reducer": "sum"
+            }
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Seen"
+              },
+              {
+                "config": {
+                  "id": "greaterOrEqual",
+                  "options": {
+                    "value": 0
+                  }
+                },
+                "fieldName": "Trapped"
+              }
+            ],
+            "match": "all",
+            "type": "include"
+          }
+        },
+        {
+          "id": "groupBy",
+          "options": {
+            "fields": {
+              "Seen": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "Time": {
+                "aggregations": [
+                  "max"
+                ],
+                "operation": "aggregate"
+              },
+              "Trapped": {
+                "aggregations": [
+                  "sum"
+                ],
+                "operation": "aggregate"
+              },
+              "country": {
+                "aggregations": [
+                  "lastNotNull"
+                ],
+                "operation": "aggregate"
+              },
+              "ip": {
+                "aggregations": [],
+                "operation": "groupby"
+              }
+            }
+          }
+        },
+        {
+          "id": "filterByValue",
+          "options": {
+            "filters": [
+              {
+                "config": {
+                  "id": "isNull",
+                  "options": {}
+                },
+                "fieldName": "ip"
+              }
+            ],
+            "match": "any",
+            "type": "exclude"
+          }
+        },
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {},
+            "indexByName": {
+              "Seen (sum)": 3,
+              "Time (max)": 0,
+              "Trapped (sum)": 4,
+              "country (lastNotNull)": 2,
+              "ip": 1
+            },
+            "renameByName": {
+              "Seen (sum)": "Connections",
+              "Time (max)": "Last Connection",
+              "Trapped (sum)": "Trapped Time",
+              "country (lastNotNull)": "Country",
+              "ip": "IP"
+            }
+          }
+        }
+      ],
+      "type": "table"
+    }
+  ],
+  "refresh": "",
+  "schemaVersion": 37,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "text": "default",
+          "value": "default"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "label": "datasource",
+        "multi": false,
+        "name": "DS_PROMETHEUS",
+        "options": [],
+        "query": "prometheus",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "allValue": ".*",
+        "current": {
+          "selected": false,
+          "text": "All",
+          "value": "$__all"
+        },
+        "datasource": {
+          "type": "prometheus",
+          "uid": "${DS_PROMETHEUS}"
+        },
+        "definition": "label_values(endlessh_client_open_count_total, job)",
+        "hide": 0,
+        "includeAll": true,
+        "label": "Job",
+        "multi": true,
+        "name": "job",
+        "options": [],
+        "query": {
+          "query": "label_values(endlessh_client_open_count_total, job)",
+          "refId": "StandardVariableQuery"
+        },
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "type": "query"
+      },
+      {
+        "allValue": ".*",
+        "current": {
+          "selected": false,
+          "text": "All",
+          "value": "$__all"
+        },
+        "datasource": {
+          "type": "prometheus",
+          "uid": "${DS_PROMETHEUS}"
+        },
+        "definition": "label_values(endlessh_client_open_count_total{job=~\"$job\"}, instance)",
+        "hide": 0,
+        "includeAll": true,
+        "label": "Host",
+        "multi": true,
+        "name": "host",
+        "options": [],
+        "query": {
+          "query": "label_values(endlessh_client_open_count_total{job=~\"$job\"}, instance)",
+          "refId": "StandardVariableQuery"
+        },
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 1,
+        "type": "query"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-24h",
+    "to": "now"
+  },
+  "timepicker": {},
+  "timezone": "",
+  "title": "Endlessh",
+  "uid": "ATIxYkO7k",
+  "version": 1,
+  "weekStart": ""
+}
\ No newline at end of file
diff --git a/modules/nixfiles/monitoring/default.nix b/modules/nixfiles/monitoring/default.nix
index 5edd83b..9758cff 100644
--- a/modules/nixfiles/monitoring/default.nix
+++ b/modules/nixfiles/monitoring/default.nix
@@ -37,21 +37,15 @@ in {
           }
         ];
 
-        # TODO Move dashboards to this repository.
         dashboards = [
+          # System dashboard is imported manually from here[1]. Too bad
+          # provisioned dashboards cannot properly integrate dynamic datasources
+          # yet.
+          #
+          # [1]: https://grafana.com/grafana/dashboards/1860-node-exporter-full/
           {
-            name = "system";
-            options.path = pkgs.fetchurl {
-              url = "https://gist.githubusercontent.com/azahi/b8951223e6850d88159b0c34749a20aa/raw/00c6928374b5d231dc3afe617165550868b8c233/System-1645616603173.json";
-              sha256 = "sha256-vGlCOHT5Rp1K88Z8lkLGkvTDeFpgi967CSOb/797vwY=";
-            };
-          }
-          {
-            name = "endlessh-go";
-            options.path = pkgs.fetchurl {
-              url = "https://gist.githubusercontent.com/azahi/fd917e917fb53deacf3c6d7366bae2b2/raw/796530bd899e9328e423d18a462faf3c7d01c823/endlessh.json";
-              sha256 = "sha256-/wJDiFlrHEa1f82pDFtG/T2GRKGlAur0dlQ8eeVJ3m4=";
-            };
+            name = "endlessh";
+            options.path = ./dashboards/endlessh.json;
           }
           {
             name = "unbound";
diff --git a/modules/nixfiles/nsd.nix b/modules/nixfiles/nsd.nix
index 5426414..7abae70 100644
--- a/modules/nixfiles/nsd.nix
+++ b/modules/nixfiles/nsd.nix
@@ -104,6 +104,7 @@ in {
                       gotify = manwe;
                       grafana = manwe;
                       loki = manwe;
+                      minecraft = varda;
                       prometheus = manwe;
                       radicale = manwe;
                       rss-bridge = manwe;
diff --git a/modules/nixfiles/password-store.nix b/modules/nixfiles/password-store.nix
index 7824ae5..d40afab 100644
--- a/modules/nixfiles/password-store.nix
+++ b/modules/nixfiles/password-store.nix
@@ -19,7 +19,7 @@ in {
         settings.PASSWORD_STORE_DIR = "${config.my.home}/.password-store";
       };
 
-      # A dirty little hack to make completions for "otp" to work.
+      # https://github.com/NixOS/nixpkgs/issues/183604
       bash.initExtra = let
         completions = "${config.hm.programs.password-store.package}/share/bash-completion/completions";
       in
diff --git a/modules/nixfiles/profiles/headful.nix b/modules/nixfiles/profiles/headful.nix
index 3e94a0b..9fd7386 100644
--- a/modules/nixfiles/profiles/headful.nix
+++ b/modules/nixfiles/profiles/headful.nix
@@ -24,28 +24,33 @@ in {
     nixfiles.modules = {
       alacritty.enable = true;
       aria2.enable = true;
+      chromium.enable = true;
       emacs.enable = true;
       firefox.enable = true;
       mpv.enable = true;
       openssh.client.enable = true;
       password-store.enable = true;
+      solaar.enable = true;
       sound.enable = true;
       x11.enable = true;
 
       dwm.enable = mkDefault false;
+      gnome.enable = mkDefault false;
       kde.enable = mkDefault true;
       xmonad.enable = mkDefault false;
     };
 
     hm.home.packages = with pkgs; [convmv dos2unix];
 
-    # There are (arguably) not a lot of reasons to keep mitigations enabled not
-    # on a web facing machine. First of all, to completely mitigate any possible
-    # Spectre holes one would need to disable Hyperthreading which will
-    # essentially put one's computer into the stone age by not being able to to
-    # effectively utilise multi-core systems. Secondly, by enabling mitigations,
-    # we introduce a plethora of performace overheads[1], which, albeit small,
-    # but still contribute to overall speed of things.
+    # There are (arguably) not a lot of reasons to keep mitigations enabled for
+    # on machine that is not web-facing. First of all, to completely mitigate
+    # any possible Spectre holes one would need to disable Hyperthreading
+    # altogether which will essentially put one's computer into the stone age by
+    # not being able to to effectively utilise multi-core its multicore
+    # capabilities. Secondly, by enabling mitigations, we introduce a plethora
+    # of performace overheads[1], which, albeit small, but still contribute to
+    # the overall speed of things. This is however still poses a security risk,
+    # which I am willing to take.
     #
     # [1]: https://www.phoronix.com/scan.php?page=article&item=spectre-meltdown-2&num=11
     boot.kernelParams = ["mitigations=off"];
diff --git a/modules/nixfiles/solaar.nix b/modules/nixfiles/solaar.nix
new file mode 100644
index 0000000..073beb0
--- /dev/null
+++ b/modules/nixfiles/solaar.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.solaar;
+in {
+  options.nixfiles.modules.solaar = {
+    enable = mkEnableOption "Solaar";
+  };
+
+  config = mkIf cfg.enable {
+    hm = {
+      home.packages = with pkgs; [solaar];
+
+      systemd.user.services.solaar = {
+        Unit = {
+          Description = "Device manager for Logitech devices";
+          After = ["graphical-session-pre.target"];
+          PartOf = ["graphical-session.target"];
+        };
+        Service = {
+          # The dirtiest hack I've ever implemented... I should be ashamed of it.
+          ExecStartPre = let
+            pkg = pkgs.writeShellApplication {
+              name = "solaar-pre";
+              text = ''
+                for i in /dev/hidraw*; do
+                  if [ -c "$i" ]; then
+                    sudo chown root:input "$i"
+                    sudo chmod 0660 "$i"
+                  fi
+                done
+              '';
+            };
+          in "${pkg}/bin/solaar-pre";
+          ExecStart = "${pkgs.solaar}/bin/solaar --window=hide";
+        };
+        Install.WantedBy = ["graphical-session.target"];
+      };
+    };
+
+    boot.kernelModules = ["hid_logitech_dj" "hid_logitech_hidpp"];
+
+    hardware.uinput.enable = true;
+
+    my.extraGroups = ["uinput" "input"];
+  };
+}
diff --git a/modules/nixfiles/x11.nix b/modules/nixfiles/x11.nix
index 502a24b..03c11cb 100644
--- a/modules/nixfiles/x11.nix
+++ b/modules/nixfiles/x11.nix
@@ -13,36 +13,17 @@ in {
     nixfiles.modules.fonts.enable = true;
 
     hm = {
-      home = {
-        # TODO Get these out of the global state.
-        # packages = with pkgs;
-        #   [xclip xdotool]
-        #   ++ (with xorg; [
-        #     xdpyinfo
-        #     xdriinfo
-        #     xev
-        #     xfontsel
-        #     xkill
-        #     xlsatoms
-        #     xlsclients
-        #     xlsfonts
-        #     xprop
-        #     xrandr
-        #     xwininfo
-        #   ]);
-
-        sessionVariables = with config.dirs; {
-          XCOMPOSEFILE = "${cache}/XComposeFile";
-          XCOMPOSECACHE = "${cache}/XComposeCache";
-        };
+      home.sessionVariables = with config.dirs; {
+        XCOMPOSEFILE = "${cache}/XComposeFile";
+        XCOMPOSECACHE = "${cache}/XComposeCache";
       };
 
       xsession.scriptPath = ".xinitrc";
 
-      xresources.properties = with config.nixfiles.modules; let
-        font = with config.fontScheme.monospaceFont; "${family}:style=${style}:size=${toString size}";
-      in
-        {
+      xresources.properties = with config.nixfiles.modules;
+        (let
+          font = with config.fontScheme.monospaceFont; "${family}:style=${style}:size=${toString size}";
+        in {
           "*.font" = font;
 
           "Xft.antialias" = 1;
@@ -52,7 +33,7 @@ in {
           "Xft.hintstyle" = "hintslight";
           "Xft.lcdfilter" = "lcddefault";
           "Xft.rgba" = "rgb";
-        }
+        })
         // (with profiles.common.colourScheme; {
           "*.color0" = black;
           "*.color8" = brightBlack;

Consider giving Nix/NixOS a try! <3