From eed797fb13e383d2a002ff04382b46247dc0582e Mon Sep 17 00:00:00 2001
From: Pim Kunis <pim@kunis.nl>
Date: Mon, 28 Oct 2024 14:11:40 +0100
Subject: [PATCH 1/2] Use treefmt-nix and Alejandro

---
 flake.nix     | 11 ++++++++---
 formatter.nix |  9 +++++++++
 treefmt.nix   |  4 ++++
 3 files changed, 21 insertions(+), 3 deletions(-)
 create mode 100644 formatter.nix
 create mode 100644 treefmt.nix

diff --git a/flake.nix b/flake.nix
index e7ee847..3b34261 100644
--- a/flake.nix
+++ b/flake.nix
@@ -17,6 +17,12 @@
     deploy-rs.url = "github:serokell/deploy-rs";
     nixos-hardware.url = "github:NixOS/nixos-hardware/master";
     flake-utils.url = "github:numtide/flake-utils";
+    treefmt-nix.url = "github:numtide/treefmt-nix";
+
+    pre-commit-hooks = {
+      url = "github:cachix/git-hooks.nix";
+      inputs.nixpkgs.follows = "nixpkgs-unstable";
+    };
 
     disko = {
       url = "github:nix-community/disko";
@@ -58,7 +64,6 @@
       ./shell.nix
       ./utils
       ./machines
-    ] // (flake-utils.lib.eachDefaultSystem (system: {
-      formatter = nixpkgs.legacyPackages.${system}.nixfmt;
-    }));
+      ./formatter.nix
+    ];
 }
diff --git a/formatter.nix b/formatter.nix
new file mode 100644
index 0000000..8696b53
--- /dev/null
+++ b/formatter.nix
@@ -0,0 +1,9 @@
+{ nixpkgs, treefmt-nix, flake-utils, ...}: flake-utils.lib.eachDefaultSystem (system:
+let
+  pkgs = nixpkgs.legacyPackages.${system};
+  treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
+in
+{
+  formatter = treefmtEval.config.build.wrapper;
+}
+)
diff --git a/treefmt.nix b/treefmt.nix
new file mode 100644
index 0000000..e6da195
--- /dev/null
+++ b/treefmt.nix
@@ -0,0 +1,4 @@
+{...}: {
+  projectRootFile = "flake.nix";
+  programs.alejandra.enable = true;
+}

From 5341235bc3435efa4cf3015954e06ca278570c1f Mon Sep 17 00:00:00 2001
From: Pim Kunis <pim@kunis.nl>
Date: Mon, 28 Oct 2024 14:12:06 +0100
Subject: [PATCH 2/2] Format repo

---
 deploy.nix                     |   34 +-
 flake.lock                     |  116 ++-
 flake.nix                      |    7 +-
 formatter.nix                  |   19 +-
 machines/default.nix           |   40 +-
 machines/pikvm.nix             |    9 +-
 machines/talos.nix             |    2 +-
 modules/backups.nix            |   27 +-
 modules/data-sharing.nix       |   18 +-
 modules/default.nix            |   48 +-
 modules/k3s/bootstrap.nix      |    4 +-
 modules/k3s/default.nix        |  148 +--
 modules/monitoring/default.nix |   37 +-
 modules/networking/default.nix |    6 +-
 modules/storage.nix            |   16 +-
 modules/tailscale.nix          |   26 +-
 nixos.nix                      |   21 +-
 scripts/default.nix            |   34 +-
 shell.nix                      |   13 +-
 utils/default.nix              |   24 +-
 utils/net.nix                  | 1627 +++++++++++++++-----------------
 21 files changed, 1200 insertions(+), 1076 deletions(-)

diff --git a/deploy.nix b/deploy.nix
index 5da2ab6..e8886c7 100644
--- a/deploy.nix
+++ b/deploy.nix
@@ -1,26 +1,26 @@
-{ self, deploy-rs, ... }:
-let
+{
+  self,
+  deploy-rs,
+  ...
+}: let
   deployArch = "x86_64-linux";
   mkDeployNodes = nodeDef:
     builtins.mapAttrs
-      (name: machine: nodeDef name machine)
-      self.machines.${deployArch};
-in
-{
+    (name: machine: nodeDef name machine)
+    self.machines.${deployArch};
+in {
   deploy = {
     sshUser = "root";
     user = "root";
 
-    nodes = mkDeployNodes (name: machine:
-      let
-        nixosConfiguration = self.nixosConfigurations.${name};
-      in
-      {
-        hostname = nixosConfiguration.config.networking.fqdn;
-        profiles.system = {
-          remoteBuild = machine.arch != deployArch;
-          path = deploy-rs.lib.${machine.arch}.activate.nixos nixosConfiguration;
-        };
-      });
+    nodes = mkDeployNodes (name: machine: let
+      nixosConfiguration = self.nixosConfigurations.${name};
+    in {
+      hostname = nixosConfiguration.config.networking.fqdn;
+      profiles.system = {
+        remoteBuild = machine.arch != deployArch;
+        path = deploy-rs.lib.${machine.arch}.activate.nixos nixosConfiguration;
+      };
+    });
   };
 }
diff --git a/flake.lock b/flake.lock
index 34d0281..074e833 100644
--- a/flake.lock
+++ b/flake.lock
@@ -109,6 +109,22 @@
         "type": "github"
       }
     },
+    "flake-compat_4": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": [
@@ -163,6 +179,27 @@
         "type": "github"
       }
     },
+    "gitignore": {
+      "inputs": {
+        "nixpkgs": [
+          "pre-commit-hooks",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "type": "github"
+      }
+    },
     "kubenix": {
       "inputs": {
         "flake-compat": "flake-compat_2",
@@ -262,6 +299,22 @@
       }
     },
     "nixpkgs-stable": {
+      "locked": {
+        "lastModified": 1720386169,
+        "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-24.05",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs-stable_2": {
       "locked": {
         "lastModified": 1729357638,
         "narHash": "sha256-66RHecx+zohbZwJVEPF7uuwHeqf8rykZTMCTqIrOew4=",
@@ -309,6 +362,45 @@
         "type": "github"
       }
     },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1726871744,
+        "narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "pre-commit-hooks": {
+      "inputs": {
+        "flake-compat": "flake-compat_4",
+        "gitignore": "gitignore",
+        "nixpkgs": [
+          "nixpkgs-unstable"
+        ],
+        "nixpkgs-stable": "nixpkgs-stable"
+      },
+      "locked": {
+        "lastModified": 1729104314,
+        "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
         "deploy-rs": "deploy-rs",
@@ -321,7 +413,9 @@
         "nixos-hardware": "nixos-hardware",
         "nixpkgs": "nixpkgs_2",
         "nixpkgs-unstable": "nixpkgs-unstable",
-        "sops-nix": "sops-nix"
+        "pre-commit-hooks": "pre-commit-hooks",
+        "sops-nix": "sops-nix",
+        "treefmt-nix": "treefmt-nix"
       }
     },
     "sops-nix": {
@@ -329,7 +423,7 @@
         "nixpkgs": [
           "nixpkgs"
         ],
-        "nixpkgs-stable": "nixpkgs-stable"
+        "nixpkgs-stable": "nixpkgs-stable_2"
       },
       "locked": {
         "lastModified": 1729775275,
@@ -410,6 +504,24 @@
         "type": "github"
       }
     },
+    "treefmt-nix": {
+      "inputs": {
+        "nixpkgs": "nixpkgs_3"
+      },
+      "locked": {
+        "lastModified": 1730025913,
+        "narHash": "sha256-Y9NtFmP8ciLyRsopcCx1tyoaaStKeq+EndwtGCgww7I=",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "rev": "bae131e525cc8718da22fbeb8d8c7c43c4ea502a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "type": "github"
+      }
+    },
     "utils": {
       "inputs": {
         "systems": "systems"
diff --git a/flake.nix b/flake.nix
index 3b34261..0238d94 100644
--- a/flake.nix
+++ b/flake.nix
@@ -55,8 +55,11 @@
     };
   };
 
-  outputs =
-    inputs@{ nixpkgs, flake-utils, ... }:
+  outputs = inputs @ {
+    nixpkgs,
+    flake-utils,
+    ...
+  }:
     flake-utils.lib.meld inputs [
       ./scripts
       ./deploy.nix
diff --git a/formatter.nix b/formatter.nix
index 8696b53..0d42f9c 100644
--- a/formatter.nix
+++ b/formatter.nix
@@ -1,9 +1,14 @@
-{ nixpkgs, treefmt-nix, flake-utils, ...}: flake-utils.lib.eachDefaultSystem (system:
-let
-  pkgs = nixpkgs.legacyPackages.${system};
-  treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
-in
 {
-  formatter = treefmtEval.config.build.wrapper;
-}
+  nixpkgs,
+  treefmt-nix,
+  flake-utils,
+  ...
+}:
+flake-utils.lib.eachDefaultSystem (
+  system: let
+    pkgs = nixpkgs.legacyPackages.${system};
+    treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
+  in {
+    formatter = treefmtEval.config.build.wrapper;
+  }
 )
diff --git a/machines/default.nix b/machines/default.nix
index 74aa74e..261980b 100644
--- a/machines/default.nix
+++ b/machines/default.nix
@@ -1,9 +1,13 @@
-{ nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system:
-let
+{
+  nixpkgs,
+  flake-utils,
+  ...
+}:
+flake-utils.lib.eachDefaultSystem (system: let
   pkgs = nixpkgs.legacyPackages.${system};
   lib = pkgs.lib;
 
-  machineOpts = { config, ... }: {
+  machineOpts = {config, ...}: {
     options = {
       arch = lib.mkOption {
         default = null;
@@ -19,7 +23,7 @@ let
       };
 
       nixosModule = lib.mkOption {
-        default = { ... }: { };
+        default = {...}: {};
         type = lib.types.anything;
         description = ''
           Customized configuration for this machine in the form of a NixOS module.
@@ -43,17 +47,19 @@ let
       };
     };
   };
-in
-{
-  machines = (lib.modules.evalModules {
-    modules = [
-      allOpts
-      ./warwick.nix
-      ./atlas.nix
-      ./jefke.nix
-      ./lewis.nix
-      # ./talos.nix
-      # ./pikvm.nix
-    ];
-  }).config.machines;
+in {
+  machines =
+    (lib.modules.evalModules {
+      modules = [
+        allOpts
+        ./warwick.nix
+        ./atlas.nix
+        ./jefke.nix
+        ./lewis.nix
+        # ./talos.nix
+        # ./pikvm.nix
+      ];
+    })
+    .config
+    .machines;
 })
diff --git a/machines/pikvm.nix b/machines/pikvm.nix
index 6a7bc14..d384897 100644
--- a/machines/pikvm.nix
+++ b/machines/pikvm.nix
@@ -3,7 +3,12 @@
     arch = "aarch64-linux";
     isRaspberryPi = true;
 
-    nixosModule = { config, inputs, lib, ... }: {
+    nixosModule = {
+      config,
+      inputs,
+      lib,
+      ...
+    }: {
       # imports = [ "${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix" ];
       lab = {
         storage.profile = "pi";
@@ -17,7 +22,7 @@
         v4l-utils
       ];
 
-      boot.extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ];
+      boot.extraModulePackages = with config.boot.kernelPackages; [v4l2loopback];
     };
   };
 }
diff --git a/machines/talos.nix b/machines/talos.nix
index 0fa0311..56ada95 100644
--- a/machines/talos.nix
+++ b/machines/talos.nix
@@ -2,7 +2,7 @@
   machines.talos = {
     arch = "x86_64-linux";
 
-    nixosModule = { lib, ... }: {
+    nixosModule = {lib, ...}: {
       lab.storage.profile = "normal";
 
       # boot.loader.systemd-boot.enable = lib.mkForce false;
diff --git a/modules/backups.nix b/modules/backups.nix
index bf1c9a5..18e7240 100644
--- a/modules/backups.nix
+++ b/modules/backups.nix
@@ -1,12 +1,16 @@
-{ pkgs, lib, config, ... }:
-let
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}: let
   cfg = config.lab.backups;
 
   borgmaticConfig = pkgs.writeTextFile {
     name = "borgmatic-config.yaml";
 
-    text = lib.generators.toYAML { } {
-      source_directories = [ "/mnt/longhorn/persistent/longhorn-backup" ];
+    text = lib.generators.toYAML {} {
+      source_directories = ["/mnt/longhorn/persistent/longhorn-backup"];
 
       repositories = [
         {
@@ -27,8 +31,7 @@ let
       encryption_passcommand = "${pkgs.coreutils}/bin/cat ${config.sops.secrets."borg/borgPassphrase".path}";
     };
   };
-in
-{
+in {
   options.lab.backups = {
     enable = lib.mkOption {
       default = false;
@@ -48,13 +51,13 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [ borgbackup ];
+    environment.systemPackages = with pkgs; [borgbackup];
     # Converted from:
     # https://github.com/borgmatic-collective/borgmatic/tree/84823dfb912db650936e3492f6ead7e0e0d32a0f/sample/systemd
     systemd.services.borgmatic = {
       description = "borgmatic backup";
-      wants = [ "network-online.target" ];
-      after = [ "network-online.target" ];
+      wants = ["network-online.target"];
+      after = ["network-online.target"];
       unitConfig.ConditionACPower = true;
       preStart = "${pkgs.coreutils}/bin/sleep 10s";
 
@@ -75,7 +78,7 @@ in
 
     systemd.timers.borgmatic = {
       description = "Run borgmatic backup";
-      wantedBy = [ "timers.target" ];
+      wantedBy = ["timers.target"];
       timerConfig = {
         OnCalendar = "*-*-* 3:00:00";
         Persistent = true;
@@ -84,8 +87,8 @@ in
     };
 
     sops.secrets = {
-      "borg/borgPassphrase" = { };
-      "borg/borgbasePrivateKey" = { };
+      "borg/borgPassphrase" = {};
+      "borg/borgbasePrivateKey" = {};
     };
   };
 }
diff --git a/modules/data-sharing.nix b/modules/data-sharing.nix
index ac6c456..8fe6c37 100644
--- a/modules/data-sharing.nix
+++ b/modules/data-sharing.nix
@@ -1,5 +1,8 @@
-{ lib, config, ... }:
-let
+{
+  lib,
+  config,
+  ...
+}: let
   cfg = config.lab.data-sharing;
 
   nfsShares = [
@@ -13,13 +16,12 @@ let
 
   nfsExports = lib.strings.concatLines (
     builtins.map
-      (share:
-        "${share} 192.168.30.0/16(rw,sync,no_subtree_check,no_root_squash) 127.0.0.1/8(rw,sync,no_subtree_check,no_root_squash) 10.0.0.0/8(rw,sync,no_subtree_check,no_root_squash)"
-      )
-      nfsShares
+    (
+      share: "${share} 192.168.30.0/16(rw,sync,no_subtree_check,no_root_squash) 127.0.0.1/8(rw,sync,no_subtree_check,no_root_squash) 10.0.0.0/8(rw,sync,no_subtree_check,no_root_squash)"
+    )
+    nfsShares
   );
-in
-{
+in {
   options.lab.data-sharing = {
     enable = lib.mkOption {
       default = false;
diff --git a/modules/default.nix b/modules/default.nix
index 7628bdb..8749267 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -1,17 +1,27 @@
-{ self, pkgs, config, lib, inputs, machine, ... }: {
-  imports = [
-    ./storage.nix
-    ./backups.nix
-    ./networking
-    ./data-sharing.nix
-    ./monitoring
-    ./k3s
-    ./tailscale.nix
-    machine.nixosModule
-    inputs.disko.nixosModules.disko
-    inputs.sops-nix.nixosModules.sops
-    inputs.nix-snapshotter.nixosModules.nix-snapshotter
-  ] ++ lib.lists.optional (machine.isRaspberryPi) inputs.nixos-hardware.nixosModules.raspberry-pi-4;
+{
+  self,
+  pkgs,
+  config,
+  lib,
+  inputs,
+  machine,
+  ...
+}: {
+  imports =
+    [
+      ./storage.nix
+      ./backups.nix
+      ./networking
+      ./data-sharing.nix
+      ./monitoring
+      ./k3s
+      ./tailscale.nix
+      machine.nixosModule
+      inputs.disko.nixosModules.disko
+      inputs.sops-nix.nixosModules.sops
+      inputs.nix-snapshotter.nixosModules.nix-snapshotter
+    ]
+    ++ lib.lists.optional (machine.isRaspberryPi) inputs.nixos-hardware.nixosModules.raspberry-pi-4;
 
   config = {
     time.timeZone = "Europe/Amsterdam";
@@ -31,7 +41,9 @@
     i18n = {
       defaultLocale = "en_US.UTF-8";
 
-      extraLocaleSettings = let extraLocale = "nl_NL.UTF-8"; in {
+      extraLocaleSettings = let
+        extraLocale = "nl_NL.UTF-8";
+      in {
         LC_ADDRESS = extraLocale;
         LC_IDENTIFICATION = extraLocale;
         LC_MEASUREMENT = extraLocale;
@@ -97,12 +109,12 @@
     ];
 
     boot = lib.mkIf (! machine.isRaspberryPi) {
-      kernelModules = [ "kvm-intel" ];
-      extraModulePackages = [ ];
+      kernelModules = ["kvm-intel"];
+      extraModulePackages = [];
       kernel.sysctl."fs.inotify.max_user_instances" = 256;
 
       initrd = {
-        kernelModules = [ ];
+        kernelModules = [];
 
         availableKernelModules = [
           "ahci"
diff --git a/modules/k3s/bootstrap.nix b/modules/k3s/bootstrap.nix
index 28a8aa9..e49770b 100644
--- a/modules/k3s/bootstrap.nix
+++ b/modules/k3s/bootstrap.nix
@@ -1,5 +1,5 @@
-{ kubenix, ... }: {
-  imports = [ kubenix.modules.k8s ];
+{kubenix, ...}: {
+  imports = [kubenix.modules.k8s];
   kubernetes.resources.clusterRoleBindings.cluster-admins = {
     roleRef = {
       apiGroup = "rbac.authorization.k8s.io";
diff --git a/modules/k3s/default.nix b/modules/k3s/default.nix
index d638c81..9b00024 100644
--- a/modules/k3s/default.nix
+++ b/modules/k3s/default.nix
@@ -1,8 +1,13 @@
-{ self, inputs, pkgs, lib, config, ... }:
-let
-  cfg = config.lab.k3s;
-in
 {
+  self,
+  inputs,
+  pkgs,
+  lib,
+  config,
+  ...
+}: let
+  cfg = config.lab.k3s;
+in {
   options.lab.k3s = {
     enable = lib.mkOption {
       default = false;
@@ -62,68 +67,66 @@ in
           address = "/run/nix-snapshotter/nix-snapshotter.sock";
         };
 
-        plugins =
-          let
-            k3s-cni-plugins = pkgs.buildEnv {
-              name = "k3s-cni-plugins";
-              paths = with pkgs; [
-                cni-plugins
-                cni-plugin-flannel
-              ];
-            };
-          in
-          {
-            "io.containerd.grpc.v1.cri" = {
-              stream_server_address = "127.0.0.1";
-              stream_server_port = "10010";
-              enable_selinux = false;
-              enable_unprivileged_ports = true;
-              enable_unprivileged_icmp = true;
-              disable_apparmor = true;
-              disable_cgroup = true;
-              restrict_oom_score_adj = true;
-              sandbox_image = "rancher/mirrored-pause:3.6";
-              containerd.snapshotter = "nix";
+        plugins = let
+          k3s-cni-plugins = pkgs.buildEnv {
+            name = "k3s-cni-plugins";
+            paths = with pkgs; [
+              cni-plugins
+              cni-plugin-flannel
+            ];
+          };
+        in {
+          "io.containerd.grpc.v1.cri" = {
+            stream_server_address = "127.0.0.1";
+            stream_server_port = "10010";
+            enable_selinux = false;
+            enable_unprivileged_ports = true;
+            enable_unprivileged_icmp = true;
+            disable_apparmor = true;
+            disable_cgroup = true;
+            restrict_oom_score_adj = true;
+            sandbox_image = "rancher/mirrored-pause:3.6";
+            containerd.snapshotter = "nix";
 
-              cni = {
-                conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d/";
-                bin_dir = "${k3s-cni-plugins}/bin";
-              };
+            cni = {
+              conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d/";
+              bin_dir = "${k3s-cni-plugins}/bin";
             };
+          };
 
-            "io.containerd.transfer.v1.local".unpack_config = [{
+          "io.containerd.transfer.v1.local".unpack_config = [
+            {
               platform = "linux/amd64";
               snapshotter = "nix";
-            }];
-          };
+            }
+          ];
+        };
       };
     };
 
     services = {
       nix-snapshotter.enable = true;
 
-      k3s =
-        let
-          serverFlagList = [
-            "--image-service-endpoint=unix:///run/nix-snapshotter/nix-snapshotter.sock"
-            "--snapshotter=overlayfs"
-            "--container-runtime-endpoint=unix:///run/containerd/containerd.sock"
-            "--tls-san=${config.networking.fqdn}"
-            "--disable=servicelb"
-            "--cluster-cidr=10.42.0.0/16,2001:cafe:42::/56"
-            "--service-cidr=10.43.0.0/16,2001:cafe:43::/112"
-          ];
+      k3s = let
+        serverFlagList = [
+          "--image-service-endpoint=unix:///run/nix-snapshotter/nix-snapshotter.sock"
+          "--snapshotter=overlayfs"
+          "--container-runtime-endpoint=unix:///run/containerd/containerd.sock"
+          "--tls-san=${config.networking.fqdn}"
+          "--disable=servicelb"
+          "--cluster-cidr=10.42.0.0/16,2001:cafe:42::/56"
+          "--service-cidr=10.43.0.0/16,2001:cafe:43::/112"
+        ];
 
-          serverFlags = builtins.concatStringsSep " " serverFlagList;
-        in
-        {
-          enable = true;
-          role = cfg.role;
-          tokenFile = config.sops.secrets."k3s/serverToken".path;
-          extraFlags = lib.mkIf (cfg.role == "server") (lib.mkForce serverFlags);
-          clusterInit = cfg.clusterInit;
-          serverAddr = lib.mkIf (! (cfg.serverAddr == null)) cfg.serverAddr;
-        };
+        serverFlags = builtins.concatStringsSep " " serverFlagList;
+      in {
+        enable = true;
+        role = cfg.role;
+        tokenFile = config.sops.secrets."k3s/serverToken".path;
+        extraFlags = lib.mkIf (cfg.role == "server") (lib.mkForce serverFlags);
+        clusterInit = cfg.clusterInit;
+        serverAddr = lib.mkIf (! (cfg.serverAddr == null)) cfg.serverAddr;
+      };
 
       # Required for Longhorn
       openiscsi = {
@@ -143,11 +146,14 @@ in
       k3s-bootstrap = lib.mkIf (cfg.role == "server") {
         text = (
           let
-            k3sBootstrapFile = (inputs.kubenix.evalModules.x86_64-linux {
-              module = import ./bootstrap.nix;
-            }).config.kubernetes.result;
-          in
-          ''
+            k3sBootstrapFile =
+              (inputs.kubenix.evalModules.x86_64-linux {
+                module = import ./bootstrap.nix;
+              })
+              .config
+              .kubernetes
+              .result;
+          in ''
             mkdir -p /var/lib/rancher/k3s/server/manifests
             ln -sf ${k3sBootstrapFile} /var/lib/rancher/k3s/server/manifests/k3s-bootstrap.json
           ''
@@ -166,18 +172,16 @@ in
       };
     };
 
-    sops.secrets =
-      let
-        keyPathBase = "/var/lib/rancher/k3s/server/tls";
-      in
-      {
-        "k3s/serverToken" = { };
-        "k3s/keys/clientCAKey".path = "${keyPathBase}/client-ca.key";
-        "k3s/keys/requestHeaderCAKey".path = "${keyPathBase}/request-header-ca.key";
-        "k3s/keys/serverCAKey".path = "${keyPathBase}/server-ca.key";
-        "k3s/keys/serviceKey".path = "${keyPathBase}/service.key";
-        "k3s/keys/etcd/peerCAKey".path = "${keyPathBase}/etcd/peer-ca.key";
-        "k3s/keys/etcd/serverCAKey".path = "${keyPathBase}/etcd/server-ca.key";
-      };
+    sops.secrets = let
+      keyPathBase = "/var/lib/rancher/k3s/server/tls";
+    in {
+      "k3s/serverToken" = {};
+      "k3s/keys/clientCAKey".path = "${keyPathBase}/client-ca.key";
+      "k3s/keys/requestHeaderCAKey".path = "${keyPathBase}/request-header-ca.key";
+      "k3s/keys/serverCAKey".path = "${keyPathBase}/server-ca.key";
+      "k3s/keys/serviceKey".path = "${keyPathBase}/service.key";
+      "k3s/keys/etcd/peerCAKey".path = "${keyPathBase}/etcd/peer-ca.key";
+      "k3s/keys/etcd/serverCAKey".path = "${keyPathBase}/etcd/server-ca.key";
+    };
   };
 }
diff --git a/modules/monitoring/default.nix b/modules/monitoring/default.nix
index 2d6560d..a67b12e 100644
--- a/modules/monitoring/default.nix
+++ b/modules/monitoring/default.nix
@@ -1,8 +1,11 @@
-{ lib, config, machines, ... }:
-let
-  cfg = config.lab.monitoring;
-in
 {
+  lib,
+  config,
+  machines,
+  ...
+}: let
+  cfg = config.lab.monitoring;
+in {
   options = {
     lab.monitoring = {
       enable = lib.mkOption {
@@ -18,8 +21,9 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    networking.firewall.allowedTCPPorts = [ config.services.prometheus.exporters.node.port ]
-      ++ lib.lists.optionals cfg.server.enable [ 80 ];
+    networking.firewall.allowedTCPPorts =
+      [config.services.prometheus.exporters.node.port]
+      ++ lib.lists.optionals cfg.server.enable [80];
 
     services.prometheus = {
       enable = cfg.server.enable;
@@ -32,12 +36,15 @@ in
 
       scrapeConfigs = lib.mkIf cfg.server.enable (
         let
-          generated = lib.attrsets.mapAttrsToList
+          generated =
+            lib.attrsets.mapAttrsToList
             (name: machine: {
               job_name = name;
-              static_configs = [{
-                targets = [ "${name}.dmz:${toString config.services.prometheus.exporters.node.port}" ];
-              }];
+              static_configs = [
+                {
+                  targets = ["${name}.dmz:${toString config.services.prometheus.exporters.node.port}"];
+                }
+              ];
             })
             machines;
 
@@ -53,12 +60,14 @@ in
               password = "admin";
             };
 
-            static_configs = [{
-              targets = [ "pikvm.dmz" ];
-            }];
+            static_configs = [
+              {
+                targets = ["pikvm.dmz"];
+              }
+            ];
           };
         in
-        generated ++ [ pikvm ]
+          generated ++ [pikvm]
       );
     };
 
diff --git a/modules/networking/default.nix b/modules/networking/default.nix
index df36440..0f235cc 100644
--- a/modules/networking/default.nix
+++ b/modules/networking/default.nix
@@ -1,4 +1,8 @@
-{ lib, machine, ... }: {
+{
+  lib,
+  machine,
+  ...
+}: {
   config = {
     networking = {
       domain = "dmz";
diff --git a/modules/storage.nix b/modules/storage.nix
index 670cb7f..d9e5529 100644
--- a/modules/storage.nix
+++ b/modules/storage.nix
@@ -1,5 +1,8 @@
-{ lib, config, ... }:
-let
+{
+  lib,
+  config,
+  ...
+}: let
   cfg = config.lab.storage;
   modules = [
     {
@@ -7,7 +10,7 @@ let
         fileSystems."/" = {
           device = "/dev/disk/by-label/NIXOS_SD";
           fsType = "ext4";
-          options = [ "noatime" ];
+          options = ["noatime"];
         };
       };
     }
@@ -87,7 +90,7 @@ let
                     type = "filesystem";
                     format = "ext4";
                     mountpoint = "/";
-                    mountOptions = [ "defaults" ];
+                    mountOptions = ["defaults"];
                   };
                 };
 
@@ -145,7 +148,7 @@ let
                     type = "filesystem";
                     format = "ext4";
                     mountpoint = "/";
-                    mountOptions = [ "defaults" ];
+                    mountOptions = ["defaults"];
                   };
                 };
               };
@@ -155,8 +158,7 @@ let
       };
     }
   ];
-in
-{
+in {
   imports = modules;
 
   options.lab.storage = {
diff --git a/modules/tailscale.nix b/modules/tailscale.nix
index d50408e..d24c4d7 100644
--- a/modules/tailscale.nix
+++ b/modules/tailscale.nix
@@ -1,8 +1,10 @@
-{ lib, config, ... }:
-let
-  cfg = config.lab.tailscale;
-in
 {
+  lib,
+  config,
+  ...
+}: let
+  cfg = config.lab.tailscale;
+in {
   options = {
     lab.tailscale = {
       enable = lib.mkEnableOption "tailscale";
@@ -21,15 +23,17 @@ in
       useRoutingFeatures = "server";
       openFirewall = true;
 
-      extraUpFlags = [
-        "--accept-dns=false"
-        "--hostname=${config.networking.hostName}"
-      ] ++ lib.lists.optional cfg.advertiseExitNode "--advertise-exit-node"
-      ++ lib.lists.optional cfg.advertiseExitNode "--advertise-routes=192.168.30.0/24";
+      extraUpFlags =
+        [
+          "--accept-dns=false"
+          "--hostname=${config.networking.hostName}"
+        ]
+        ++ lib.lists.optional cfg.advertiseExitNode "--advertise-exit-node"
+        ++ lib.lists.optional cfg.advertiseExitNode "--advertise-routes=192.168.30.0/24";
     };
 
-    sops.secrets."tailscale/authKey" = { };
+    sops.secrets."tailscale/authKey" = {};
 
-    systemd.network.wait-online.ignoredInterfaces = [ "tailscale0" ];
+    systemd.network.wait-online.ignoredInterfaces = ["tailscale0"];
   };
 }
diff --git a/nixos.nix b/nixos.nix
index 21c0023..4d2d0ad 100644
--- a/nixos.nix
+++ b/nixos.nix
@@ -1,23 +1,26 @@
-{ self, nixpkgs, ... }@inputs:
-let
+{
+  self,
+  nixpkgs,
+  ...
+} @ inputs: let
   deployArch = "x86_64-linux";
   machines = self.machines.${deployArch};
   mkNixosSystems = systemDef:
     builtins.mapAttrs
-      (name: machine:
+    (
+      name: machine:
         nixpkgs.lib.nixosSystem (systemDef name machine)
-      )
-      machines;
-in
-{
+    )
+    machines;
+in {
   nixosConfigurations = mkNixosSystems (name: machine: {
     system = machine.arch;
 
-    specialArgs = { inherit self inputs machine machines; };
+    specialArgs = {inherit self inputs machine machines;};
 
     modules = [
       "${self}/modules"
-      { networking.hostName = name; }
+      {networking.hostName = name;}
     ];
   });
 }
diff --git a/scripts/default.nix b/scripts/default.nix
index e1ffbbc..5386881 100644
--- a/scripts/default.nix
+++ b/scripts/default.nix
@@ -1,23 +1,31 @@
-{ nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system:
-let
+{
+  nixpkgs,
+  flake-utils,
+  ...
+}:
+flake-utils.lib.eachDefaultSystem (system: let
   pkgs = nixpkgs.legacyPackages.${system};
-  createScript = { name, runtimeInputs, scriptPath, extraWrapperFlags ? "", ... }:
-    let
-      script = (pkgs.writeScriptBin name (builtins.readFile scriptPath)).overrideAttrs (old: {
-        buildCommand = "${old.buildCommand}\n patchShebangs $out";
-      });
-    in
+  createScript = {
+    name,
+    runtimeInputs,
+    scriptPath,
+    extraWrapperFlags ? "",
+    ...
+  }: let
+    script = (pkgs.writeScriptBin name (builtins.readFile scriptPath)).overrideAttrs (old: {
+      buildCommand = "${old.buildCommand}\n patchShebangs $out";
+    });
+  in
     pkgs.symlinkJoin {
       inherit name;
-      paths = [ script ] ++ runtimeInputs;
-      buildInputs = [ pkgs.makeWrapper ];
+      paths = [script] ++ runtimeInputs;
+      buildInputs = [pkgs.makeWrapper];
       postBuild = "wrapProgram $out/bin/${name} --set PATH $out/bin ${extraWrapperFlags}";
     };
-in
-{
+in {
   packages.bootstrap = createScript {
     name = "bootstrap";
-    runtimeInputs = with pkgs; [ sops coreutils nixos-anywhere ];
+    runtimeInputs = with pkgs; [sops coreutils nixos-anywhere];
     scriptPath = ./bootstrap.sh;
   };
 })
diff --git a/shell.nix b/shell.nix
index 67e7b03..072adef 100644
--- a/shell.nix
+++ b/shell.nix
@@ -1,9 +1,12 @@
-{ flake-utils, nixpkgs, ... }: flake-utils.lib.eachDefaultSystem (system:
-let
-  pkgs = nixpkgs.legacyPackages.${system};
-in
 {
+  flake-utils,
+  nixpkgs,
+  ...
+}:
+flake-utils.lib.eachDefaultSystem (system: let
+  pkgs = nixpkgs.legacyPackages.${system};
+in {
   devShells.default = pkgs.mkShell {
-    buildInputs = with pkgs; [ ansible ];
+    buildInputs = with pkgs; [ansible];
   };
 })
diff --git a/utils/default.nix b/utils/default.nix
index 297fc3c..e73e360 100644
--- a/utils/default.nix
+++ b/utils/default.nix
@@ -1,14 +1,14 @@
-{ nixpkgs, flake-utils, ... }:
-
-let
-  systemAttrs = flake-utils.lib.eachDefaultSystem (system:
-    let
-      pkgs = nixpkgs.legacypackages.${system};
-      lib = pkgs.lib;
-    in
-    {
-      net = import ./net.nix lib;
-    });
+{
+  nixpkgs,
+  flake-utils,
+  ...
+}: let
+  systemAttrs = flake-utils.lib.eachDefaultSystem (system: let
+    pkgs = nixpkgs.legacypackages.${system};
+    lib = pkgs.lib;
+  in {
+    net = import ./net.nix lib;
+  });
 
   nonSystemAttrs = {
     globals = import ./globals.nix;
@@ -16,4 +16,4 @@ let
 
   allAttrs = systemAttrs // nonSystemAttrs;
 in
-allAttrs
+  allAttrs
diff --git a/utils/net.nix b/utils/net.nix
index 9f5b0e5..d5b15a1 100644
--- a/utils/net.nix
+++ b/utils/net.nix
@@ -1,367 +1,347 @@
 # IP address arithmetic and validation in Nix by @duairc:
 # https://gist.github.com/duairc/5c9bb3c922e5d501a1edb9e7b3b845ba
-
-lib:
-
-let
-
-  net = {
-    ip = {
-
-      # add :: (ip | mac | integer) -> ip -> ip
-      #
-      # Examples:
-      #
-      # Adding integer to IPv4:
-      # > net.ip.add 100 "10.0.0.1"
-      # "10.0.0.101"
-      #
-      # Adding IPv4 to IPv4:
-      # > net.ip.add "127.0.0.1" "10.0.0.1"
-      # "137.0.0.2"
-      #
-      # Adding IPv6 to IPv4:
-      # > net.ip.add "::cafe:beef" "10.0.0.1"
-      # "212.254.186.191"
-      #
-      # Adding MAC to IPv4 (overflows):
-      # > net.ip.add "fe:ed:fa:ce:f0:0d" "10.0.0.1"
-      # "4.206.240.14"
-      #
-      # Adding integer to IPv6:
-      # > net.ip.add 100 "dead:cafe:beef::"
-      # "dead:cafe:beef::64"
-      #
-      # Adding IPv4 to to IPv6:
-      # > net.ip.add "127.0.0.1" "dead:cafe:beef::"
-      # "dead:cafe:beef::7f00:1"
-      #
-      # Adding MAC to IPv6:
-      # > net.ip.add "fe:ed:fa:ce:f0:0d" "dead:cafe:beef::"
-      # "dead:cafe:beef::feed:face:f00d"
-      add = delta: ip:
-        let
+lib: let
+  net =
+    {
+      ip = {
+        # add :: (ip | mac | integer) -> ip -> ip
+        #
+        # Examples:
+        #
+        # Adding integer to IPv4:
+        # > net.ip.add 100 "10.0.0.1"
+        # "10.0.0.101"
+        #
+        # Adding IPv4 to IPv4:
+        # > net.ip.add "127.0.0.1" "10.0.0.1"
+        # "137.0.0.2"
+        #
+        # Adding IPv6 to IPv4:
+        # > net.ip.add "::cafe:beef" "10.0.0.1"
+        # "212.254.186.191"
+        #
+        # Adding MAC to IPv4 (overflows):
+        # > net.ip.add "fe:ed:fa:ce:f0:0d" "10.0.0.1"
+        # "4.206.240.14"
+        #
+        # Adding integer to IPv6:
+        # > net.ip.add 100 "dead:cafe:beef::"
+        # "dead:cafe:beef::64"
+        #
+        # Adding IPv4 to to IPv6:
+        # > net.ip.add "127.0.0.1" "dead:cafe:beef::"
+        # "dead:cafe:beef::7f00:1"
+        #
+        # Adding MAC to IPv6:
+        # > net.ip.add "fe:ed:fa:ce:f0:0d" "dead:cafe:beef::"
+        # "dead:cafe:beef::feed:face:f00d"
+        add = delta: ip: let
           function = "net.ip.add";
           delta' = typechecks.numeric function "delta" delta;
           ip' = typechecks.ip function "ip" ip;
         in
-        builders.ip (implementations.ip.add delta' ip');
+          builders.ip (implementations.ip.add delta' ip');
 
-      # diff :: ip -> ip -> (integer | ipv6)
-      #
-      # net.ip.diff is the reverse of net.ip.add:
-      #
-      # net.ip.diff (net.ip.add a b) a = b
-      # net.ip.diff (net.ip.add a b) b = a
-      #
-      # The difference between net.ip.diff and net.ip.subtract is that
-      # net.ip.diff will try its best to return an integer (falling back
-      # to an IPv6 if the result is too big to fit in an integer). This is
-      # useful if you have two hosts that you know are on the same network
-      # and you just want to calculate the offset between them — a result
-      # like "0.0.0.10" is not very useful (which is what you would get
-      # from net.ip.subtract).
-      diff = minuend: subtrahend:
-        let
+        # diff :: ip -> ip -> (integer | ipv6)
+        #
+        # net.ip.diff is the reverse of net.ip.add:
+        #
+        # net.ip.diff (net.ip.add a b) a = b
+        # net.ip.diff (net.ip.add a b) b = a
+        #
+        # The difference between net.ip.diff and net.ip.subtract is that
+        # net.ip.diff will try its best to return an integer (falling back
+        # to an IPv6 if the result is too big to fit in an integer). This is
+        # useful if you have two hosts that you know are on the same network
+        # and you just want to calculate the offset between them — a result
+        # like "0.0.0.10" is not very useful (which is what you would get
+        # from net.ip.subtract).
+        diff = minuend: subtrahend: let
           function = "net.ip.diff";
           minuend' = typechecks.ip function "minuend" minuend;
           subtrahend' = typechecks.ip function "subtrahend" subtrahend;
           result = implementations.ip.diff minuend' subtrahend';
         in
-        if result ? ipv6
-        then builders.ipv6 result
-        else result;
+          if result ? ipv6
+          then builders.ipv6 result
+          else result;
 
-      # subtract :: (ip | mac | integer) -> ip -> ip
-      #
-      # net.ip.subtract is also the reverse of net.ip.add:
-      #
-      # net.ip.subtract a (net.ip.add a b) = b
-      # net.ip.subtract b (net.ip.add a b) = a
-      #
-      # The difference between net.ip.subtract and net.ip.diff is that
-      # net.ip.subtract will always return the same type as its "ip"
-      # parameter. Its implementation takes the "delta" parameter,
-      # coerces it to be the same type as the "ip" paramter, negates it
-      # (using two's complement), and then adds it to "ip".
-      subtract = delta: ip:
-        let
+        # subtract :: (ip | mac | integer) -> ip -> ip
+        #
+        # net.ip.subtract is also the reverse of net.ip.add:
+        #
+        # net.ip.subtract a (net.ip.add a b) = b
+        # net.ip.subtract b (net.ip.add a b) = a
+        #
+        # The difference between net.ip.subtract and net.ip.diff is that
+        # net.ip.subtract will always return the same type as its "ip"
+        # parameter. Its implementation takes the "delta" parameter,
+        # coerces it to be the same type as the "ip" paramter, negates it
+        # (using two's complement), and then adds it to "ip".
+        subtract = delta: ip: let
           function = "net.ip.subtract";
           delta' = typechecks.numeric function "delta" delta;
           ip' = typechecks.ip function "ip" ip;
         in
-        builders.ip (implementations.ip.subtract delta' ip');
-    };
+          builders.ip (implementations.ip.subtract delta' ip');
+      };
 
-    mac = {
-
-      # add :: (ip | mac | integer) -> mac -> mac
-      #
-      # Examples:
-      #
-      # Adding integer to MAC:
-      # > net.mac.add 100 "fe:ed:fa:ce:f0:0d"
-      # "fe:ed:fa:ce:f0:71"
-      #
-      # Adding IPv4 to MAC:
-      # > net.mac.add "127.0.0.1" "fe:ed:fa:ce:f0:0d"
-      # "fe:ee:79:ce:f0:0e"
-      #
-      # Adding IPv6 to MAC:
-      # > net.mac.add "::cafe:beef" "fe:ed:fa:ce:f0:0d"
-      # "fe:ee:c5:cd:aa:cb
-      #
-      # Adding MAC to MAC:
-      # > net.mac.add "fe:ed:fa:00:00:00" "00:00:00:ce:f0:0d"
-      # "fe:ed:fa:ce:f0:0d"
-      add = delta: mac:
-        let
+      mac = {
+        # add :: (ip | mac | integer) -> mac -> mac
+        #
+        # Examples:
+        #
+        # Adding integer to MAC:
+        # > net.mac.add 100 "fe:ed:fa:ce:f0:0d"
+        # "fe:ed:fa:ce:f0:71"
+        #
+        # Adding IPv4 to MAC:
+        # > net.mac.add "127.0.0.1" "fe:ed:fa:ce:f0:0d"
+        # "fe:ee:79:ce:f0:0e"
+        #
+        # Adding IPv6 to MAC:
+        # > net.mac.add "::cafe:beef" "fe:ed:fa:ce:f0:0d"
+        # "fe:ee:c5:cd:aa:cb
+        #
+        # Adding MAC to MAC:
+        # > net.mac.add "fe:ed:fa:00:00:00" "00:00:00:ce:f0:0d"
+        # "fe:ed:fa:ce:f0:0d"
+        add = delta: mac: let
           function = "net.mac.add";
           delta' = typechecks.numeric function "delta" delta;
           mac' = typechecks.mac function "mac" mac;
         in
-        builders.mac (implementations.mac.add delta' mac');
+          builders.mac (implementations.mac.add delta' mac');
 
-      # diff :: mac -> mac -> integer
-      #
-      # net.mac.diff is the reverse of net.mac.add:
-      #
-      # net.mac.diff (net.mac.add a b) a = b
-      # net.mac.diff (net.mac.add a b) b = a
-      #
-      # The difference between net.mac.diff and net.mac.subtract is that
-      # net.mac.diff will always return an integer.
-      diff = minuend: subtrahend:
-        let
+        # diff :: mac -> mac -> integer
+        #
+        # net.mac.diff is the reverse of net.mac.add:
+        #
+        # net.mac.diff (net.mac.add a b) a = b
+        # net.mac.diff (net.mac.add a b) b = a
+        #
+        # The difference between net.mac.diff and net.mac.subtract is that
+        # net.mac.diff will always return an integer.
+        diff = minuend: subtrahend: let
           function = "net.mac.diff";
           minuend' = typechecks.mac function "minuend" minuend;
           subtrahend' = typechecks.mac function "subtrahend" subtrahend;
         in
-        implementations.mac.diff minuend' subtrahend';
+          implementations.mac.diff minuend' subtrahend';
 
-      # subtract :: (ip | mac | integer) -> mac -> mac
-      #
-      # net.mac.subtract is also the reverse of net.ip.add:
-      #
-      # net.mac.subtract a (net.mac.add a b) = b
-      # net.mac.subtract b (net.mac.add a b) = a
-      #
-      # The difference between net.mac.subtract and net.mac.diff is that
-      # net.mac.subtract will always return a MAC address.
-      subtract = delta: mac:
-        let
+        # subtract :: (ip | mac | integer) -> mac -> mac
+        #
+        # net.mac.subtract is also the reverse of net.ip.add:
+        #
+        # net.mac.subtract a (net.mac.add a b) = b
+        # net.mac.subtract b (net.mac.add a b) = a
+        #
+        # The difference between net.mac.subtract and net.mac.diff is that
+        # net.mac.subtract will always return a MAC address.
+        subtract = delta: mac: let
           function = "net.mac.subtract";
           delta' = typechecks.numeric function "delta" delta;
           mac' = typechecks.mac function "mac" mac;
         in
-        builders.mac (implementations.mac.subtract delta' mac');
-    };
+          builders.mac (implementations.mac.subtract delta' mac');
+      };
 
-    cidr = {
-      # add :: (ip | mac | integer) -> cidr -> cidr
-      #
-      # > net.cidr.add 2 "127.0.0.0/8"
-      # "129.0.0.0/8"
-      #
-      # > net.cidr.add (-2) "127.0.0.0/8"
-      # "125.0.0.0/8"
-      add = delta: cidr:
-        let
+      cidr = {
+        # add :: (ip | mac | integer) -> cidr -> cidr
+        #
+        # > net.cidr.add 2 "127.0.0.0/8"
+        # "129.0.0.0/8"
+        #
+        # > net.cidr.add (-2) "127.0.0.0/8"
+        # "125.0.0.0/8"
+        add = delta: cidr: let
           function = "net.cidr.add";
           delta' = typechecks.numeric function "delta" delta;
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        builders.cidr (implementations.cidr.add delta' cidr');
+          builders.cidr (implementations.cidr.add delta' cidr');
 
-      # child :: cidr -> cidr -> bool
-      #
-      # > net.cidr.child "10.10.10.0/24" "10.0.0.0/8"
-      # true
-      #
-      # > net.cidr.child "127.0.0.0/8" "10.0.0.0/8"
-      # false
-      child = subcidr: cidr:
-        let
+        # child :: cidr -> cidr -> bool
+        #
+        # > net.cidr.child "10.10.10.0/24" "10.0.0.0/8"
+        # true
+        #
+        # > net.cidr.child "127.0.0.0/8" "10.0.0.0/8"
+        # false
+        child = subcidr: cidr: let
           function = "net.cidr.child";
           subcidr' = typechecks.cidr function "subcidr" subcidr;
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        implementations.cidr.child subcidr' cidr';
+          implementations.cidr.child subcidr' cidr';
 
-      # contains :: ip -> cidr -> bool
-      #
-      # > net.cidr.contains "127.0.0.1" "127.0.0.0/8"
-      # true
-      #
-      # > net.cidr.contains "127.0.0.1" "192.168.0.0/16"
-      # false
-      contains = ip: cidr:
-        let
+        # contains :: ip -> cidr -> bool
+        #
+        # > net.cidr.contains "127.0.0.1" "127.0.0.0/8"
+        # true
+        #
+        # > net.cidr.contains "127.0.0.1" "192.168.0.0/16"
+        # false
+        contains = ip: cidr: let
           function = "net.cidr.contains";
           ip' = typechecks.ip function "ip" ip;
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        implementations.cidr.contains ip' cidr';
+          implementations.cidr.contains ip' cidr';
 
-      # capacity :: cidr -> integer
-      #
-      # > net.cidr.capacity "172.16.0.0/12"
-      # 1048576
-      #
-      # > net.cidr.capacity "dead:cafe:beef::/96"
-      # 4294967296
-      #
-      # > net.cidr.capacity "dead:cafe:beef::/48" (saturates to maxBound)
-      # 9223372036854775807
-      capacity = cidr:
-        let
+        # capacity :: cidr -> integer
+        #
+        # > net.cidr.capacity "172.16.0.0/12"
+        # 1048576
+        #
+        # > net.cidr.capacity "dead:cafe:beef::/96"
+        # 4294967296
+        #
+        # > net.cidr.capacity "dead:cafe:beef::/48" (saturates to maxBound)
+        # 9223372036854775807
+        capacity = cidr: let
           function = "net.cidr.capacity";
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        implementations.cidr.capacity cidr';
+          implementations.cidr.capacity cidr';
 
-      # host :: (ip | mac | integer) -> cidr -> ip
-      #
-      # > net.cidr.host 10000 "10.0.0.0/8"
-      # 10.0.39.16
-      #
-      # > net.cidr.host 10000 "dead:cafe:beef::/64"
-      # "dead:cafe:beef::2710"
-      #
-      # net.cidr.host "127.0.0.1" "dead:cafe:beef::/48"
-      # > "dead:cafe:beef::7f00:1"
-      #
-      # Inpsired by:
-      # https://www.terraform.io/docs/configuration/functions/cidrhost.html
-      host = hostnum: cidr:
-        let
+        # host :: (ip | mac | integer) -> cidr -> ip
+        #
+        # > net.cidr.host 10000 "10.0.0.0/8"
+        # 10.0.39.16
+        #
+        # > net.cidr.host 10000 "dead:cafe:beef::/64"
+        # "dead:cafe:beef::2710"
+        #
+        # net.cidr.host "127.0.0.1" "dead:cafe:beef::/48"
+        # > "dead:cafe:beef::7f00:1"
+        #
+        # Inpsired by:
+        # https://www.terraform.io/docs/configuration/functions/cidrhost.html
+        host = hostnum: cidr: let
           function = "net.cidr.host";
           hostnum' = typechecks.numeric function "hostnum" hostnum;
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        builders.ip (implementations.cidr.host hostnum' cidr');
+          builders.ip (implementations.cidr.host hostnum' cidr');
 
-      # length :: cidr -> integer
-      #
-      # > net.cidr.prefix "127.0.0.0/8"
-      # 8
-      #
-      # > net.cidr.prefix "dead:cafe:beef::/48"
-      # 48
-      length = cidr:
-        let
+        # length :: cidr -> integer
+        #
+        # > net.cidr.prefix "127.0.0.0/8"
+        # 8
+        #
+        # > net.cidr.prefix "dead:cafe:beef::/48"
+        # 48
+        length = cidr: let
           function = "net.cidr.length";
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        implementations.cidr.length cidr';
+          implementations.cidr.length cidr';
 
-      # make :: integer -> ip -> cidr
-      #
-      # > net.cidr.make 24 "192.168.0.150"
-      # "192.168.0.0/24"
-      #
-      # > net.cidr.make 40 "dead:cafe:beef::feed:face:f00d"
-      # "dead:cafe:be00::/40"
-      make = length: base:
-        let
+        # make :: integer -> ip -> cidr
+        #
+        # > net.cidr.make 24 "192.168.0.150"
+        # "192.168.0.0/24"
+        #
+        # > net.cidr.make 40 "dead:cafe:beef::feed:face:f00d"
+        # "dead:cafe:be00::/40"
+        make = length: base: let
           function = "net.cidr.make";
           length' = typechecks.int function "length" length;
           base' = typechecks.ip function "base" base;
         in
-        builders.cidr (implementations.cidr.make length' base');
+          builders.cidr (implementations.cidr.make length' base');
 
-      # netmask :: cidr -> ip
-      #
-      # > net.cidr.netmask "192.168.0.0/24"
-      # "255.255.255.0"
-      #
-      # > net.cidr.netmask "dead:cafe:beef::/64"
-      # "ffff:ffff:ffff:ffff::"
-      netmask = cidr:
-        let
+        # netmask :: cidr -> ip
+        #
+        # > net.cidr.netmask "192.168.0.0/24"
+        # "255.255.255.0"
+        #
+        # > net.cidr.netmask "dead:cafe:beef::/64"
+        # "ffff:ffff:ffff:ffff::"
+        netmask = cidr: let
           function = "net.cidr.netmask";
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        builders.ip (implementations.cidr.netmask cidr');
+          builders.ip (implementations.cidr.netmask cidr');
 
-      # size :: cidr -> integer
-      #
-      # > net.cidr.prefix "127.0.0.0/8"
-      # 24
-      #
-      # > net.cidr.prefix "dead:cafe:beef::/48"
-      # 80
-      size = cidr:
-        let
+        # size :: cidr -> integer
+        #
+        # > net.cidr.prefix "127.0.0.0/8"
+        # 24
+        #
+        # > net.cidr.prefix "dead:cafe:beef::/48"
+        # 80
+        size = cidr: let
           function = "net.cidr.size";
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        implementations.cidr.size cidr';
+          implementations.cidr.size cidr';
 
-      # subnet :: integer -> (ip | mac | integer) -> cidr -> cidr
-      #
-      # > net.cidr.subnet 4 2 "172.16.0.0/12"
-      # "172.18.0.0/16"
-      #
-      # > net.cidr.subnet 4 15 "10.1.2.0/24"
-      # "10.1.2.240/28"
-      #
-      # > net.cidr.subnet 16 162 "fd00:fd12:3456:7890::/56"
-      # "fd00:fd12:3456:7800:a200::/72"
-      #
-      # Inspired by:
-      # https://www.terraform.io/docs/configuration/functions/cidrsubnet.html
-      subnet = length: netnum: cidr:
-        let
+        # subnet :: integer -> (ip | mac | integer) -> cidr -> cidr
+        #
+        # > net.cidr.subnet 4 2 "172.16.0.0/12"
+        # "172.18.0.0/16"
+        #
+        # > net.cidr.subnet 4 15 "10.1.2.0/24"
+        # "10.1.2.240/28"
+        #
+        # > net.cidr.subnet 16 162 "fd00:fd12:3456:7890::/56"
+        # "fd00:fd12:3456:7800:a200::/72"
+        #
+        # Inspired by:
+        # https://www.terraform.io/docs/configuration/functions/cidrsubnet.html
+        subnet = length: netnum: cidr: let
           function = "net.cidr.subnet";
           length' = typechecks.int function "length" length;
           netnum' = typechecks.numeric function "netnum" netnum;
           cidr' = typechecks.cidr function "cidr" cidr;
         in
-        builders.cidr (implementations.cidr.subnet length' netnum' cidr');
-
-    };
-  } // ({
-    types =
-      let
-
-        mkParsedOptionType = { name, description, parser, builder }:
-          let
-            normalize = def: def // {
+          builders.cidr (implementations.cidr.subnet length' netnum' cidr');
+      };
+    }
+    // {
+      types = let
+        mkParsedOptionType = {
+          name,
+          description,
+          parser,
+          builder,
+        }: let
+          normalize = def:
+            def
+            // {
               value = builder (parser def.value);
             };
-          in
+        in
           lib.mkOptionType {
             inherit name description;
             check = x: builtins.isString x && parser x != null;
             merge = loc: defs: lib.mergeEqualOption loc (map normalize defs);
           };
 
-        dependent-ip = type: cidr:
-          let
-            cidrs =
-              if builtins.isList cidr
-              then cidr
-              else [ cidr ];
-          in
-          lib.types.addCheck type (i: lib.any (net.cidr.contains i) cidrs) // {
+        dependent-ip = type: cidr: let
+          cidrs =
+            if builtins.isList cidr
+            then cidr
+            else [cidr];
+        in
+          lib.types.addCheck type (i: lib.any (net.cidr.contains i) cidrs)
+          // {
             description = type.description + " in ${builtins.concatStringsSep " or " cidrs}";
           };
 
-        dependent-cidr = type: cidr:
-          let
-            cidrs =
-              if builtins.isList cidr
-              then cidr
-              else [ cidr ];
-          in
-          lib.types.addCheck type (i: lib.any (net.cidr.child i) cidrs) // {
+        dependent-cidr = type: cidr: let
+          cidrs =
+            if builtins.isList cidr
+            then cidr
+            else [cidr];
+        in
+          lib.types.addCheck type (i: lib.any (net.cidr.child i) cidrs)
+          // {
             description = type.description + " in ${builtins.concatStringsSep " or " cidrs}";
           };
-
-      in
-      rec {
-
+      in rec {
         ip = mkParsedOptionType {
           name = "ip";
           description = "IPv4 or IPv6 address";
@@ -422,46 +402,44 @@ let
           parser = parsers.mac;
           builder = builders.mac;
         };
-
       };
-  }
-  );
+    };
 
   list = {
-    cons = a: b: [ a ] ++ b;
+    cons = a: b: [a] ++ b;
   };
 
-  bit =
-    let
-      shift = n: x:
-        if n < 0
-        then x * math.pow 2 (-n)
-        else
-          let
-            safeDiv = n: d: if d == 0 then 0 else n / d;
-            d = math.pow 2 n;
-          in
-          if x < 0
-          then not (safeDiv (not x) d)
-          else safeDiv x d;
+  bit = let
+    shift = n: x:
+      if n < 0
+      then x * math.pow 2 (-n)
+      else let
+        safeDiv = n: d:
+          if d == 0
+          then 0
+          else n / d;
+        d = math.pow 2 n;
+      in
+        if x < 0
+        then not (safeDiv (not x) d)
+        else safeDiv x d;
 
-      left = n: shift (-n);
+    left = n: shift (-n);
 
-      right = shift;
+    right = shift;
 
-      and = builtins.bitAnd;
+    and = builtins.bitAnd;
 
-      or = builtins.bitOr;
+    or = builtins.bitOr;
 
-      xor = builtins.bitXor;
+    xor = builtins.bitXor;
 
-      not = xor (-1);
+    not = xor (-1);
 
-      mask = n: and (left n 1 - 1);
-    in
-    {
-      inherit left right and or xor not mask;
-    };
+    mask = n: and (left n 1 - 1);
+  in {
+    inherit left right and or xor not mask;
+  };
 
   math = rec {
     max = a: b:
@@ -484,89 +462,88 @@ let
       else pow (x * x) (n / 2);
   };
 
-  parsers =
-    let
+  parsers = let
+    # fmap :: (a -> b) -> parser a -> parser b
+    fmap = f: ma: bind ma (a: pure (f a));
 
-      # fmap :: (a -> b) -> parser a -> parser b
-      fmap = f: ma: bind ma (a: pure (f a));
+    # pure :: a -> parser a
+    pure = a: string: {
+      leftovers = string;
+      result = a;
+    };
 
-      # pure :: a -> parser a
-      pure = a: string: {
-        leftovers = string;
-        result = a;
+    # liftA2 :: (a -> b -> c) -> parser a -> parser b -> parser c
+    liftA2 = f: ma: mb: bind ma (a: bind mb (b: pure (f a b)));
+    liftA3 = f: a: b: ap (liftA2 f a b);
+    liftA4 = f: a: b: c: ap (liftA3 f a b c);
+    liftA5 = f: a: b: c: d: ap (liftA4 f a b c d);
+    liftA6 = f: a: b: c: d: e: ap (liftA5 f a b c d e);
+
+    # ap :: parser (a -> b) -> parser a -> parser b
+    ap = liftA2 (a: a);
+
+    # then_ :: parser a -> parser b -> parser b
+    then_ = liftA2 (a: b: b);
+
+    # empty :: parser a
+    empty = string: null;
+
+    # alt :: parser a -> parser a -> parser a
+    alt = left: right: string: let
+      result = left string;
+    in
+      if builtins.isNull result
+      then right string
+      else result;
+
+    # guard :: bool -> parser {}
+    guard = condition:
+      if condition
+      then pure {}
+      else empty;
+
+    # mfilter :: (a -> bool) -> parser a -> parser a
+    mfilter = f: parser: bind parser (a: then_ (guard (f a)) (pure a));
+
+    # some :: parser a -> parser [a]
+    some = v: liftA2 list.cons v (many v);
+
+    # many :: parser a -> parser [a]
+    many = v: alt (some v) (pure []);
+
+    # bind :: parser a -> (a -> parser b) -> parser b
+    bind = parser: f: string: let
+      a = parser string;
+    in
+      if builtins.isNull a
+      then null
+      else f a.result a.leftovers;
+
+    # run :: parser a -> string -> maybe a
+    run = parser: string: let
+      result = parser string;
+    in
+      if builtins.isNull result || result.leftovers != ""
+      then null
+      else result.result;
+
+    next = string:
+      if string == ""
+      then null
+      else {
+        leftovers = builtins.substring 1 (-1) string;
+        result = builtins.substring 0 1 string;
       };
 
-      # liftA2 :: (a -> b -> c) -> parser a -> parser b -> parser c
-      liftA2 = f: ma: mb: bind ma (a: bind mb (b: pure (f a b)));
-      liftA3 = f: a: b: ap (liftA2 f a b);
-      liftA4 = f: a: b: c: ap (liftA3 f a b c);
-      liftA5 = f: a: b: c: d: ap (liftA4 f a b c d);
-      liftA6 = f: a: b: c: d: e: ap (liftA5 f a b c d e);
-
-      # ap :: parser (a -> b) -> parser a -> parser b
-      ap = liftA2 (a: a);
-
-      # then_ :: parser a -> parser b -> parser b
-      then_ = liftA2 (a: b: b);
-
-      # empty :: parser a
-      empty = string: null;
-
-      # alt :: parser a -> parser a -> parser a
-      alt = left: right: string:
-        let
-          result = left string;
-        in
-        if builtins.isNull result
-        then right string
-        else result;
-
-      # guard :: bool -> parser {}
-      guard = condition: if condition then pure { } else empty;
-
-      # mfilter :: (a -> bool) -> parser a -> parser a
-      mfilter = f: parser: bind parser (a: then_ (guard (f a)) (pure a));
-
-      # some :: parser a -> parser [a]
-      some = v: liftA2 list.cons v (many v);
-
-      # many :: parser a -> parser [a]
-      many = v: alt (some v) (pure [ ]);
-
-      # bind :: parser a -> (a -> parser b) -> parser b
-      bind = parser: f: string:
-        let
-          a = parser string;
-        in
-        if builtins.isNull a
-        then null
-        else f a.result a.leftovers;
-
-      # run :: parser a -> string -> maybe a
-      run = parser: string:
-        let
-          result = parser string;
-        in
-        if builtins.isNull result || result.leftovers != ""
-        then null
-        else result.result;
-
-      next = string:
-        if string == ""
-        then null
-        else {
-          leftovers = builtins.substring 1 (-1) string;
-          result = builtins.substring 0 1 string;
-        };
-
-      # Count how many characters were consumed by a parser
-      count = parser: string:
-        let
-          result = parser string;
-        in
-        if builtins.isNull result
-        then null
-        else result // {
+    # Count how many characters were consumed by a parser
+    count = parser: string: let
+      result = parser string;
+    in
+      if builtins.isNull result
+      then null
+      else
+        result
+        // {
           result = {
             inherit (result) result;
             count = with result;
@@ -574,46 +551,49 @@ let
           };
         };
 
-      # Limit the parser to n characters at most
-      limit = n: parser:
-        fmap (a: a.result) (mfilter (a: a.count <= n) (count parser));
+    # Limit the parser to n characters at most
+    limit = n: parser:
+      fmap (a: a.result) (mfilter (a: a.count <= n) (count parser));
 
-      # Ensure the parser consumes exactly n characters
-      exactly = n: parser:
-        fmap (a: a.result) (mfilter (a: a.count == n) (count parser));
+    # Ensure the parser consumes exactly n characters
+    exactly = n: parser:
+      fmap (a: a.result) (mfilter (a: a.count == n) (count parser));
 
-      char = c: bind next (c': guard (c == c'));
+    char = c: bind next (c': guard (c == c'));
 
-      string = css:
-        if css == ""
-        then pure { }
-        else
-          let
-            c = builtins.substring 0 1 css;
-            cs = builtins.substring 1 (-1) css;
-          in
-          then_ (char c) (string cs);
+    string = css:
+      if css == ""
+      then pure {}
+      else let
+        c = builtins.substring 0 1 css;
+        cs = builtins.substring 1 (-1) css;
+      in
+        then_ (char c) (string cs);
 
-      digit = set: bind next (
-        c: then_
+    digit = set:
+      bind next (
+        c:
+          then_
           (guard (builtins.hasAttr c set))
           (pure (builtins.getAttr c set))
       );
 
-      decimalDigits = {
-        "0" = 0;
-        "1" = 1;
-        "2" = 2;
-        "3" = 3;
-        "4" = 4;
-        "5" = 5;
-        "6" = 6;
-        "7" = 7;
-        "8" = 8;
-        "9" = 9;
-      };
+    decimalDigits = {
+      "0" = 0;
+      "1" = 1;
+      "2" = 2;
+      "3" = 3;
+      "4" = 4;
+      "5" = 5;
+      "6" = 6;
+      "7" = 7;
+      "8" = 8;
+      "9" = 9;
+    };
 
-      hexadecimalDigits = decimalDigits // {
+    hexadecimalDigits =
+      decimalDigits
+      // {
         "a" = 10;
         "b" = 11;
         "c" = 12;
@@ -628,328 +608,293 @@ let
         "F" = 15;
       };
 
-      fromDecimalDigits = builtins.foldl' (a: c: a * 10 + c) 0;
-      fromHexadecimalDigits = builtins.foldl' (a: bit.or (bit.left 4 a)) 0;
+    fromDecimalDigits = builtins.foldl' (a: c: a * 10 + c) 0;
+    fromHexadecimalDigits = builtins.foldl' (a: bit.or (bit.left 4 a)) 0;
 
-      # disallow leading zeros
-      decimal = bind (digit decimalDigits) (
-        n:
+    # disallow leading zeros
+    decimal = bind (digit decimalDigits) (
+      n:
         if n == 0
         then pure 0
         else
           fmap
-            (ns: fromDecimalDigits (list.cons n ns))
-            (many (digit decimalDigits))
-      );
+          (ns: fromDecimalDigits (list.cons n ns))
+          (many (digit decimalDigits))
+    );
 
-      hexadecimal = fmap fromHexadecimalDigits (some (digit hexadecimalDigits));
+    hexadecimal = fmap fromHexadecimalDigits (some (digit hexadecimalDigits));
 
-      ipv4 =
-        let
-          dot = char ".";
+    ipv4 = let
+      dot = char ".";
 
-          octet = mfilter (n: n < 256) decimal;
+      octet = mfilter (n: n < 256) decimal;
 
-          octet' = then_ dot octet;
+      octet' = then_ dot octet;
 
-          fromOctets = a: b: c: d: {
-            ipv4 = bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 a) b)) c)) d;
+      fromOctets = a: b: c: d: {
+        ipv4 = bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 a) b)) c)) d;
+      };
+    in
+      liftA4 fromOctets octet octet' octet' octet';
+
+    # This is more or less a literal translation of
+    # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#parser
+    ipv6 = let
+      colon = char ":";
+
+      hextet = limit 4 hexadecimal;
+
+      fromHextets = hextets:
+        if builtins.length hextets != 8
+        then empty
+        else let
+          a = builtins.elemAt hextets 0;
+          b = builtins.elemAt hextets 1;
+          c = builtins.elemAt hextets 2;
+          d = builtins.elemAt hextets 3;
+          e = builtins.elemAt hextets 4;
+          f = builtins.elemAt hextets 5;
+          g = builtins.elemAt hextets 6;
+          h = builtins.elemAt hextets 7;
+        in
+          pure {
+            ipv6 = {
+              a = bit.or (bit.left 16 a) b;
+              b = bit.or (bit.left 16 c) d;
+              c = bit.or (bit.left 16 e) f;
+              d = bit.or (bit.left 16 g) h;
+            };
           };
-        in
-        liftA4 fromOctets octet octet' octet' octet';
 
-      # This is more or less a literal translation of
-      # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#parser
-      ipv6 =
-        let
-          colon = char ":";
+      ipv4' =
+        fmap
+        (
+          address: let
+            upper = bit.right 16 address.ipv4;
+            lower = bit.mask 16 address.ipv4;
+          in [upper lower]
+        )
+        ipv4;
 
-          hextet = limit 4 hexadecimal;
-
-          fromHextets = hextets:
-            if builtins.length hextets != 8
-            then empty
-            else
-              let
-                a = builtins.elemAt hextets 0;
-                b = builtins.elemAt hextets 1;
-                c = builtins.elemAt hextets 2;
-                d = builtins.elemAt hextets 3;
-                e = builtins.elemAt hextets 4;
-                f = builtins.elemAt hextets 5;
-                g = builtins.elemAt hextets 6;
-                h = builtins.elemAt hextets 7;
-              in
-              pure {
-                ipv6 = {
-                  a = bit.or (bit.left 16 a) b;
-                  b = bit.or (bit.left 16 c) d;
-                  c = bit.or (bit.left 16 e) f;
-                  d = bit.or (bit.left 16 g) h;
-                };
-              };
-
-          ipv4' = fmap
+      part = n: let
+        n' = n + 1;
+        hex =
+          liftA2 list.cons hextet
+          (
+            then_ colon
             (
-              address:
-              let
-                upper = bit.right 16 address.ipv4;
-                lower = bit.mask 16 address.ipv4;
-              in
-              [ upper lower ]
+              alt
+              (then_ colon (doubleColon n'))
+              (part n')
             )
-            ipv4;
+          );
+      in
+        if n == 7
+        then fmap (a: [a]) hextet
+        else if n == 6
+        then alt ipv4' hex
+        else hex;
 
-          part = n:
-            let
-              n' = n + 1;
-              hex = liftA2 list.cons hextet
-                (
-                  then_ colon
-                    (
-                      alt
-                        (then_ colon (doubleColon n'))
-                        (part n')
-                    )
-                );
-            in
-            if n == 7
-            then fmap (a: [ a ]) hextet
-            else
-              if n == 6
-              then alt ipv4' hex
-              else hex;
+      doubleColon = n:
+        bind (alt afterDoubleColon (pure [])) (
+          rest: let
+            missing = 8 - n - builtins.length rest;
+          in
+            if missing < 0
+            then empty
+            else pure (builtins.genList (_: 0) missing ++ rest)
+        );
 
-          doubleColon = n:
-            bind (alt afterDoubleColon (pure [ ])) (
-              rest:
-              let
-                missing = 8 - n - builtins.length rest;
-              in
-              if missing < 0
-              then empty
-              else pure (builtins.genList (_: 0) missing ++ rest)
-            );
-
-          afterDoubleColon =
-            alt ipv4'
-              (
-                liftA2 list.cons hextet
-                  (
-                    alt
-                      (then_ colon afterDoubleColon)
-                      (pure [ ])
-                  )
-              );
-
-        in
-        bind
+      afterDoubleColon =
+        alt ipv4'
+        (
+          liftA2 list.cons hextet
           (
             alt
-              (
-                then_
-                  (string "::")
-                  (doubleColon 0)
-              )
-              (part 0)
+            (then_ colon afterDoubleColon)
+            (pure [])
           )
-          fromHextets;
-
-      cidrv4 =
-        liftA2
-          (base: length: implementations.cidr.make length base)
-          ipv4
-          (then_ (char "/") (mfilter (n: n <= 32) decimal));
-
-      cidrv6 =
-        liftA2
-          (base: length: implementations.cidr.make length base)
-          ipv6
-          (then_ (char "/") (mfilter (n: n <= 128) decimal));
-
-      mac =
-        let
-          colon = char ":";
-
-          octet = exactly 2 hexadecimal;
-
-          octet' = then_ colon octet;
-
-          fromOctets = a: b: c: d: e: f: {
-            mac = bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 a) b)) c)) d)) e)) f;
-          };
-        in
-        liftA6 fromOctets octet octet' octet' octet' octet' octet';
-
+        );
     in
-    {
-      ipv4 = run ipv4;
-      ipv6 = run ipv6;
-      ip = run (alt ipv4 ipv6);
-      cidrv4 = run cidrv4;
-      cidrv6 = run cidrv6;
-      cidr = run (alt cidrv4 cidrv6);
-      mac = run mac;
-      numeric = run (alt (alt ipv4 ipv6) mac);
-    };
+      bind
+      (
+        alt
+        (
+          then_
+          (string "::")
+          (doubleColon 0)
+        )
+        (part 0)
+      )
+      fromHextets;
 
-  builders =
-    let
+    cidrv4 =
+      liftA2
+      (base: length: implementations.cidr.make length base)
+      ipv4
+      (then_ (char "/") (mfilter (n: n <= 32) decimal));
 
-      ipv4 = address:
-        let
-          abcd = address.ipv4;
-          abc = bit.right 8 abcd;
-          ab = bit.right 8 abc;
-          a = bit.right 8 ab;
-          b = bit.mask 8 ab;
-          c = bit.mask 8 abc;
-          d = bit.mask 8 abcd;
-        in
-        builtins.concatStringsSep "." (map toString [ a b c d ]);
+    cidrv6 =
+      liftA2
+      (base: length: implementations.cidr.make length base)
+      ipv6
+      (then_ (char "/") (mfilter (n: n <= 128) decimal));
 
-      # This is more or less a literal translation of
-      # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#encode
-      ipv6 = address:
-        let
+    mac = let
+      colon = char ":";
 
-          digits = "0123456789abcdef";
+      octet = exactly 2 hexadecimal;
 
-          toHexString = n:
-            let
-              rest = bit.right 4 n;
-              current = bit.mask 4 n;
-              prefix =
-                if rest == 0
-                then ""
-                else toHexString rest;
-            in
-            "${prefix}${builtins.substring current 1 digits}";
-
-        in
-        if (with address.ipv6; a == 0 && b == 0 && c == 0 && d > 65535)
-        then "::${ipv4 { ipv4 = address.ipv6.d; }}"
-        else
-          if (with address.ipv6; a == 0 && b == 0 && c == 65535)
-          then "::ffff:${ipv4 { ipv4 = address.ipv6.d; }}"
-          else
-            let
-
-              a = bit.right 16 address.ipv6.a;
-              b = bit.mask 16 address.ipv6.a;
-              c = bit.right 16 address.ipv6.b;
-              d = bit.mask 16 address.ipv6.b;
-              e = bit.right 16 address.ipv6.c;
-              f = bit.mask 16 address.ipv6.c;
-              g = bit.right 16 address.ipv6.d;
-              h = bit.mask 16 address.ipv6.d;
-
-              hextets = [ a b c d e f g h ];
-
-              # calculate the position and size of the longest sequence of
-              # zeroes within the list of hextets
-              longest =
-                let
-                  go = i: current: best:
-                    if i < builtins.length hextets
-                    then
-                      let
-                        n = builtins.elemAt hextets i;
-
-                        current' =
-                          if n == 0
-                          then
-                            if builtins.isNull current
-                            then {
-                              size = 1;
-                              position = i;
-                            }
-                            else current // {
-                              size = current.size + 1;
-                            }
-                          else null;
-
-                        best' =
-                          if n == 0
-                          then
-                            if builtins.isNull best
-                            then current'
-                            else
-                              if current'.size > best.size
-                              then current'
-                              else best
-                          else best;
-                      in
-                      go (i + 1) current' best'
-                    else best;
-                in
-                go 0 null null;
-
-              format = hextets:
-                builtins.concatStringsSep ":" (map toHexString hextets);
-            in
-            if builtins.isNull longest
-            then format hextets
-            else
-              let
-                sublist = i: length: xs:
-                  map
-                    (builtins.elemAt xs)
-                    (builtins.genList (x: x + i) length);
-
-                end = longest.position + longest.size;
-
-                before = sublist 0 longest.position hextets;
-
-                after = sublist end (builtins.length hextets - end) hextets;
-              in
-              "${format before}::${format after}";
-
-      ip = address:
-        if address ? ipv4
-        then ipv4 address
-        else ipv6 address;
-
-      cidrv4 = cidr:
-        "${ipv4 cidr.base}/${toString cidr.length}";
-
-      cidrv6 = cidr:
-        "${ipv6 cidr.base}/${toString cidr.length}";
-
-      cidr = cidr:
-        "${ip cidr.base}/${toString cidr.length}";
-
-      mac = address:
-        let
-          digits = "0123456789abcdef";
-          octet = n:
-            let
-              upper = bit.right 4 n;
-              lower = bit.mask 4 n;
-            in
-            "${builtins.substring upper 1 digits}${builtins.substring lower 1 digits}";
-        in
-        let
-          a = bit.mask 8 (bit.right 40 address.mac);
-          b = bit.mask 8 (bit.right 32 address.mac);
-          c = bit.mask 8 (bit.right 24 address.mac);
-          d = bit.mask 8 (bit.right 16 address.mac);
-          e = bit.mask 8 (bit.right 8 address.mac);
-          f = bit.mask 8 (bit.right 0 address.mac);
-        in
-        "${octet a}:${octet b}:${octet c}:${octet d}:${octet e}:${octet f}";
+      octet' = then_ colon octet;
 
+      fromOctets = a: b: c: d: e: f: {
+        mac = bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 (bit.or (bit.left 8 a) b)) c)) d)) e)) f;
+      };
     in
-    {
-      inherit ipv4 ipv6 ip cidrv4 cidrv6 cidr mac;
-    };
+      liftA6 fromOctets octet octet' octet' octet' octet' octet';
+  in {
+    ipv4 = run ipv4;
+    ipv6 = run ipv6;
+    ip = run (alt ipv4 ipv6);
+    cidrv4 = run cidrv4;
+    cidrv6 = run cidrv6;
+    cidr = run (alt cidrv4 cidrv6);
+    mac = run mac;
+    numeric = run (alt (alt ipv4 ipv6) mac);
+  };
+
+  builders = let
+    ipv4 = address: let
+      abcd = address.ipv4;
+      abc = bit.right 8 abcd;
+      ab = bit.right 8 abc;
+      a = bit.right 8 ab;
+      b = bit.mask 8 ab;
+      c = bit.mask 8 abc;
+      d = bit.mask 8 abcd;
+    in
+      builtins.concatStringsSep "." (map toString [a b c d]);
+
+    # This is more or less a literal translation of
+    # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#encode
+    ipv6 = address: let
+      digits = "0123456789abcdef";
+
+      toHexString = n: let
+        rest = bit.right 4 n;
+        current = bit.mask 4 n;
+        prefix =
+          if rest == 0
+          then ""
+          else toHexString rest;
+      in "${prefix}${builtins.substring current 1 digits}";
+    in
+      if (with address.ipv6; a == 0 && b == 0 && c == 0 && d > 65535)
+      then "::${ipv4 {ipv4 = address.ipv6.d;}}"
+      else if (with address.ipv6; a == 0 && b == 0 && c == 65535)
+      then "::ffff:${ipv4 {ipv4 = address.ipv6.d;}}"
+      else let
+        a = bit.right 16 address.ipv6.a;
+        b = bit.mask 16 address.ipv6.a;
+        c = bit.right 16 address.ipv6.b;
+        d = bit.mask 16 address.ipv6.b;
+        e = bit.right 16 address.ipv6.c;
+        f = bit.mask 16 address.ipv6.c;
+        g = bit.right 16 address.ipv6.d;
+        h = bit.mask 16 address.ipv6.d;
+
+        hextets = [a b c d e f g h];
+
+        # calculate the position and size of the longest sequence of
+        # zeroes within the list of hextets
+        longest = let
+          go = i: current: best:
+            if i < builtins.length hextets
+            then let
+              n = builtins.elemAt hextets i;
+
+              current' =
+                if n == 0
+                then
+                  if builtins.isNull current
+                  then {
+                    size = 1;
+                    position = i;
+                  }
+                  else
+                    current
+                    // {
+                      size = current.size + 1;
+                    }
+                else null;
+
+              best' =
+                if n == 0
+                then
+                  if builtins.isNull best
+                  then current'
+                  else if current'.size > best.size
+                  then current'
+                  else best
+                else best;
+            in
+              go (i + 1) current' best'
+            else best;
+        in
+          go 0 null null;
+
+        format = hextets:
+          builtins.concatStringsSep ":" (map toHexString hextets);
+      in
+        if builtins.isNull longest
+        then format hextets
+        else let
+          sublist = i: length: xs:
+            map
+            (builtins.elemAt xs)
+            (builtins.genList (x: x + i) length);
+
+          end = longest.position + longest.size;
+
+          before = sublist 0 longest.position hextets;
+
+          after = sublist end (builtins.length hextets - end) hextets;
+        in "${format before}::${format after}";
+
+    ip = address:
+      if address ? ipv4
+      then ipv4 address
+      else ipv6 address;
+
+    cidrv4 = cidr: "${ipv4 cidr.base}/${toString cidr.length}";
+
+    cidrv6 = cidr: "${ipv6 cidr.base}/${toString cidr.length}";
+
+    cidr = cidr: "${ip cidr.base}/${toString cidr.length}";
+
+    mac = address: let
+      digits = "0123456789abcdef";
+      octet = n: let
+        upper = bit.right 4 n;
+        lower = bit.mask 4 n;
+      in "${builtins.substring upper 1 digits}${builtins.substring lower 1 digits}";
+    in let
+      a = bit.mask 8 (bit.right 40 address.mac);
+      b = bit.mask 8 (bit.right 32 address.mac);
+      c = bit.mask 8 (bit.right 24 address.mac);
+      d = bit.mask 8 (bit.right 16 address.mac);
+      e = bit.mask 8 (bit.right 8 address.mac);
+      f = bit.mask 8 (bit.right 0 address.mac);
+    in "${octet a}:${octet b}:${octet c}:${octet d}:${octet e}:${octet f}";
+  in {
+    inherit ipv4 ipv6 ip cidrv4 cidrv6 cidr mac;
+  };
 
   arithmetic = rec {
     # or :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer)
-    or = a_: b:
-      let
-        a = coerce b a_;
-      in
+    or = a_: b: let
+      a = coerce b a_;
+    in
       if a ? ipv6
       then {
         ipv6 = {
@@ -970,10 +915,9 @@ let
       else bit.or a b;
 
     # and :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer)
-    and = a_: b:
-      let
-        a = coerce b a_;
-      in
+    and = a_: b: let
+      a = coerce b a_;
+    in
       if a ? ipv6
       then {
         ipv6 = {
@@ -1015,33 +959,29 @@ let
       else bit.not a;
 
     # add :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer)
-    add =
-      let
-        split = a: {
-          fst = bit.mask 32 (bit.right 32 a);
-          snd = bit.mask 32 a;
-        };
+    add = let
+      split = a: {
+        fst = bit.mask 32 (bit.right 32 a);
+        snd = bit.mask 32 a;
+      };
+    in
+      a_: b: let
+        a = coerce b a_;
       in
-      a_: b:
-        let
-          a = coerce b a_;
-        in
         if a ? ipv6
-        then
-          let
-            a' = split (a.ipv6.a + b.ipv6.a + b'.fst);
-            b' = split (a.ipv6.b + b.ipv6.b + c'.fst);
-            c' = split (a.ipv6.c + b.ipv6.c + d'.fst);
-            d' = split (a.ipv6.d + b.ipv6.d);
-          in
-          {
-            ipv6 = {
-              a = a'.snd;
-              b = b'.snd;
-              c = c'.snd;
-              d = d'.snd;
-            };
-          }
+        then let
+          a' = split (a.ipv6.a + b.ipv6.a + b'.fst);
+          b' = split (a.ipv6.b + b.ipv6.b + c'.fst);
+          c' = split (a.ipv6.c + b.ipv6.c + d'.fst);
+          d' = split (a.ipv6.d + b.ipv6.d);
+        in {
+          ipv6 = {
+            a = a'.snd;
+            b = b'.snd;
+            c = c'.snd;
+            d = d'.snd;
+          };
+        }
         else if a ? ipv4
         then {
           ipv4 = bit.mask 32 (a.ipv4 + b.ipv4);
@@ -1056,12 +996,11 @@ let
     subtract = a: b: add (add 1 (not (coerce b a))) b;
 
     # diff :: (ip | mac | integer) -> (ip | mac | integer) -> (ipv6 | integer)
-    diff = a: b:
-      let
-        toIPv6 = coerce ({ ipv6.a = 0; });
-        result = (subtract b (toIPv6 a)).ipv6;
-        max32 = bit.left 32 1 - 1;
-      in
+    diff = a: b: let
+      toIPv6 = coerce {ipv6.a = 0;};
+      result = (subtract b (toIPv6 a)).ipv6;
+      max32 = bit.left 32 1 - 1;
+    in
       if result.a == 0 && result.b == 0 && bit.right 31 result.c == 0 || result.a == max32 && result.b == max32 && bit.right 31 result.c == 1
       then bit.or (bit.left 32 result.c) result.d
       else {
@@ -1072,36 +1011,33 @@ let
     left = i: right (-i);
 
     # right :: integer -> (ip | mac | integer) -> (ip | mac | integer)
-    right =
-      let
-        step = i: x: {
-          _1 = bit.mask 32 (bit.right (i + 96) x);
-          _2 = bit.mask 32 (bit.right (i + 64) x);
-          _3 = bit.mask 32 (bit.right (i + 32) x);
-          _4 = bit.mask 32 (bit.right i x);
-          _5 = bit.mask 32 (bit.right (i - 32) x);
-          _6 = bit.mask 32 (bit.right (i - 64) x);
-          _7 = bit.mask 32 (bit.right (i - 96) x);
-        };
-        ors = builtins.foldl' bit.or 0;
-      in
+    right = let
+      step = i: x: {
+        _1 = bit.mask 32 (bit.right (i + 96) x);
+        _2 = bit.mask 32 (bit.right (i + 64) x);
+        _3 = bit.mask 32 (bit.right (i + 32) x);
+        _4 = bit.mask 32 (bit.right i x);
+        _5 = bit.mask 32 (bit.right (i - 32) x);
+        _6 = bit.mask 32 (bit.right (i - 64) x);
+        _7 = bit.mask 32 (bit.right (i - 96) x);
+      };
+      ors = builtins.foldl' bit.or 0;
+    in
       i: x:
         if x ? ipv6
-        then
-          let
-            a' = step i x.ipv6.a;
-            b' = step i x.ipv6.b;
-            c' = step i x.ipv6.c;
-            d' = step i x.ipv6.d;
-          in
-          {
-            ipv6 = {
-              a = ors [ a'._4 b'._3 c'._2 d'._1 ];
-              b = ors [ a'._5 b'._4 c'._3 d'._2 ];
-              c = ors [ a'._6 b'._5 c'._4 d'._3 ];
-              d = ors [ a'._7 b'._6 c'._5 d'._4 ];
-            };
-          }
+        then let
+          a' = step i x.ipv6.a;
+          b' = step i x.ipv6.b;
+          c' = step i x.ipv6.c;
+          d' = step i x.ipv6.d;
+        in {
+          ipv6 = {
+            a = ors [a'._4 b'._3 c'._2 d'._1];
+            b = ors [a'._5 b'._4 c'._3 d'._2];
+            c = ors [a'._6 b'._5 c'._4 d'._3];
+            d = ors [a'._7 b'._6 c'._5 d'._4];
+          };
+        }
         else if x ? ipv4
         then {
           ipv4 = bit.mask 32 (bit.right i x.ipv4);
@@ -1180,21 +1116,20 @@ let
         else {
           mac = bit.mask 48 value;
         }
-      else
-        if value ? ipv6
-        then
-          builtins.foldl' bit.or 0
-            [
-              (bit.left 96 value.ipv6.a)
-              (bit.left 64 value.ipv6.b)
-              (bit.left 32 value.ipv6.c)
-              value.ipv6.d
-            ]
-        else if value ? ipv4
-        then value.ipv4
-        else if value ? mac
-        then value.mac
-        else value;
+      else if value ? ipv6
+      then
+        builtins.foldl' bit.or 0
+        [
+          (bit.left 96 value.ipv6.a)
+          (bit.left 64 value.ipv6.b)
+          (bit.left 32 value.ipv6.c)
+          value.ipv6.d
+        ]
+      else if value ? ipv4
+      then value.ipv4
+      else if value ? mac
+      then value.mac
+      else value;
   };
 
   implementations = {
@@ -1222,20 +1157,17 @@ let
 
     cidr = rec {
       # add :: (ip | mac | integer) -> cidr -> cidr
-      add = delta: cidr:
-        let
-          size' = size cidr;
-        in
-        {
-          base = arithmetic.left size' (arithmetic.add delta (arithmetic.right size' cidr.base));
-          inherit (cidr) length;
-        };
+      add = delta: cidr: let
+        size' = size cidr;
+      in {
+        base = arithmetic.left size' (arithmetic.add delta (arithmetic.right size' cidr.base));
+        inherit (cidr) length;
+      };
 
       # capacity :: cidr -> integer
-      capacity = cidr:
-        let
-          size' = size cidr;
-        in
+      capacity = cidr: let
+        size' = size cidr;
+      in
         if size' > 62
         then 9223372036854775807 # maxBound to prevent overflow
         else bit.left size' 1;
@@ -1248,10 +1180,9 @@ let
       contains = ip: cidr: host 0 (make cidr.length ip) == host 0 cidr;
 
       # host :: (ip | mac | integer) -> cidr -> ip
-      host = index: cidr:
-        let
-          index' = arithmetic.coerce cidr.base index;
-        in
+      host = index: cidr: let
+        index' = arithmetic.coerce cidr.base index;
+      in
         arithmetic.or (arithmetic.shadow cidr.length index') cidr.base;
 
       # length :: cidr -> integer
@@ -1261,63 +1192,71 @@ let
       netmask = cidr: arithmetic.coshadow cidr.length (arithmetic.coerce cidr.base (-1));
 
       # size :: cidr -> integer
-      size = cidr: (if cidr.base ? ipv6 then 128 else 32) - cidr.length;
+      size = cidr:
+        (
+          if cidr.base ? ipv6
+          then 128
+          else 32
+        )
+        - cidr.length;
 
       # subnet :: integer -> (ip | mac | integer) -> cidr -> cidr
-      subnet = length: index: cidr:
-        let
-          length' = cidr.length + length;
-          index' = arithmetic.coerce cidr.base index;
-          size = (if cidr.base ? ipv6 then 128 else 32) - length';
-        in
+      subnet = length: index: cidr: let
+        length' = cidr.length + length;
+        index' = arithmetic.coerce cidr.base index;
+        size =
+          (
+            if cidr.base ? ipv6
+            then 128
+            else 32
+          )
+          - length';
+      in
         make length' (host (arithmetic.left size index') cidr);
 
       # make :: integer -> ip -> cidr
-      make = length: base:
-        let
-          length' = math.clamp 0 (if base ? ipv6 then 128 else 32) length;
-        in
-        {
-          base = arithmetic.coshadow length' base;
-          length = length';
-        };
+      make = length: base: let
+        length' =
+          math.clamp 0 (
+            if base ? ipv6
+            then 128
+            else 32
+          )
+          length;
+      in {
+        base = arithmetic.coshadow length' base;
+        length = length';
+      };
     };
   };
 
-  typechecks =
-    let
-
-      fail = description: function: argument:
-        builtins.throw "${function}: ${argument} parameter must be ${description}";
-
-      meta = parser: description: function: argument: input:
-        let
-          error = fail description function argument;
-        in
-        if !builtins.isString input
-        then error
-        else
-          let
-            result = parser input;
-          in
-          if builtins.isNull result
-          then error
-          else result;
+  typechecks = let
+    fail = description: function: argument:
+      builtins.throw "${function}: ${argument} parameter must be ${description}";
 
+    meta = parser: description: function: argument: input: let
+      error = fail description function argument;
     in
-    {
-      int = function: argument: input:
-        if builtins.isInt input
-        then input
-        else fail "an integer" function argument;
-      ip = meta parsers.ip "an IPv4 or IPv6 address";
-      cidr = meta parsers.cidr "an IPv4 or IPv6 address range in CIDR notation";
-      mac = meta parsers.mac "a MAC address";
-      numeric = function: argument: input:
-        if builtins.isInt input
-        then input
-        else meta parsers.numeric "an integer or IPv4, IPv6 or MAC address" function argument input;
-    };
-
+      if !builtins.isString input
+      then error
+      else let
+        result = parser input;
+      in
+        if builtins.isNull result
+        then error
+        else result;
+  in {
+    int = function: argument: input:
+      if builtins.isInt input
+      then input
+      else fail "an integer" function argument;
+    ip = meta parsers.ip "an IPv4 or IPv6 address";
+    cidr = meta parsers.cidr "an IPv4 or IPv6 address range in CIDR notation";
+    mac = meta parsers.mac "a MAC address";
+    numeric = function: argument: input:
+      if builtins.isInt input
+      then input
+      else meta parsers.numeric "an integer or IPv4, IPv6 or MAC address" function argument input;
+  };
 in
-net
+  net