about summary refs log tree commit diff
path: root/modules
diff options
context:
space:
mode:
authorazahi <azat@bahawi.net>2024-11-10 01:08:38 +0300
committerazahi <azat@bahawi.net>2024-11-10 01:08:38 +0300
commit693768ee37098dbebb38c86e27044f2faa38348d (patch)
tree37c92a1c83cf22fa5e5a570baa8598ba6063c795 /modules
parent2024-10-29 (diff)
2024-11-10 HEAD master
Diffstat (limited to 'modules')
-rw-r--r--modules/android.nix5
-rw-r--r--modules/common/ark.nix15
-rw-r--r--modules/common/default.nix5
-rw-r--r--modules/common/documentation.nix3
-rw-r--r--modules/common/home-manager.nix5
-rw-r--r--modules/common/kernel.nix27
-rw-r--r--modules/common/locale.nix1
-rw-r--r--modules/common/networking.nix51
-rw-r--r--modules/common/nix.nix2
-rw-r--r--modules/common/shell/default.nix30
-rw-r--r--modules/common/systemd.nix9
-rw-r--r--modules/common/xdg.nix43
-rw-r--r--modules/curl.nix2
-rw-r--r--modules/emacs/doom/config.el102
-rw-r--r--modules/emacs/doom/init.el2
-rw-r--r--modules/emacs/doom/packages.el4
-rw-r--r--modules/firefox/addons.json10
-rw-r--r--modules/firefox/addons.nix42
-rw-r--r--modules/firefox/default.nix1
-rw-r--r--modules/games/gamemode.nix7
-rw-r--r--modules/games/minecraft.nix27
-rw-r--r--modules/games/steam-run.nix79
-rw-r--r--modules/git/default.nix386
-rw-r--r--modules/hyprland.nix143
-rw-r--r--modules/jackett.nix9
-rw-r--r--modules/openssh.nix33
-rw-r--r--modules/profiles/default.nix1
-rw-r--r--modules/profiles/dev/default.nix2
-rw-r--r--modules/profiles/headful.nix2
-rw-r--r--modules/profiles/headless.nix5
-rw-r--r--modules/searx.nix13
-rw-r--r--modules/vaultwarden.nix19
-rw-r--r--modules/wayland.nix14
33 files changed, 686 insertions, 413 deletions
diff --git a/modules/android.nix b/modules/android.nix
index 363bd6c..65710ca 100644
--- a/modules/android.nix
+++ b/modules/android.nix
@@ -1,12 +1,11 @@
 { config, lib, ... }:
-with lib;
 let
   cfg = config.nixfiles.modules.android;
 in
 {
-  options.nixfiles.modules.android.enable = mkEnableOption "support for Android devices";
+  options.nixfiles.modules.android.enable = lib.mkEnableOption "support for Android devices";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.adb.enable = true;
 
     my.extraGroups = [ "adbusers" ];
diff --git a/modules/common/ark.nix b/modules/common/ark.nix
index 1e43ef8..ba3056b 100644
--- a/modules/common/ark.nix
+++ b/modules/common/ark.nix
@@ -4,14 +4,13 @@
   lib,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.ark;
 in
 {
   imports = [
     inputs.impermanence.nixosModules.impermanence
-    (mkAliasOptionModule [ "ark" ] [
+    (lib.mkAliasOptionModule [ "ark" ] [
       "nixfiles"
       "modules"
       "ark"
@@ -20,16 +19,16 @@ in
 
   options.nixfiles.modules.ark =
     let
-      mkListOfAnythingOption = mkOption {
-        type = with types; listOf anything; # Assumed to be matching with the upstream type.
+      mkListOfAnythingOption = lib.mkOption {
+        type = with lib.types; listOf anything; # Assumed to be matching with the upstream type.
         default = [ ];
       };
     in
     {
-      enable = mkEnableOption "persistent storage support via impermanence";
+      enable = lib.mkEnableOption "persistent storage support via impermanence";
 
-      path = mkOption {
-        type = types.str;
+      path = lib.mkOption {
+        type = lib.types.str;
         default = "/ark";
       };
 
@@ -41,7 +40,7 @@ in
       # };
     };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.persistence.${cfg.path} = {
       hideMounts = true;
       enableDebugging = false;
diff --git a/modules/common/default.nix b/modules/common/default.nix
index ef9fb18..38094e7 100644
--- a/modules/common/default.nix
+++ b/modules/common/default.nix
@@ -1 +1,4 @@
-{ lib, ... }: with lib; { imports = attrValues (modulesIn ./.); }
+{ lib, ... }:
+{
+  imports = lib.attrValues (lib.modulesIn ./.);
+}
diff --git a/modules/common/documentation.nix b/modules/common/documentation.nix
index 33e767c..f9e0fcb 100644
--- a/modules/common/documentation.nix
+++ b/modules/common/documentation.nix
@@ -5,7 +5,6 @@
   this,
   ...
 }:
-with lib;
 {
   config = {
     hm.manual = {
@@ -34,7 +33,7 @@ with lib;
 
     environment.variables = {
       MANOPT = "--no-hyphenation";
-      MANPAGER = "${getExe pkgs.less} -+F";
+      MANPAGER = "${lib.getExe pkgs.less} -+F";
     };
   };
 }
diff --git a/modules/common/home-manager.nix b/modules/common/home-manager.nix
index f2fc8a8..f3e8143 100644
--- a/modules/common/home-manager.nix
+++ b/modules/common/home-manager.nix
@@ -4,14 +4,13 @@
   lib,
   ...
 }:
-with lib;
 {
   imports = [
     inputs.home-manager.nixosModule
-    (mkAliasOptionModule [ "hm" ] [
+    (lib.mkAliasOptionModule [ "hm" ] [
       "home-manager"
       "users"
-      my.username
+      lib.my.username
     ])
   ];
 
diff --git a/modules/common/kernel.nix b/modules/common/kernel.nix
index ddc4f62..f7e520a 100644
--- a/modules/common/kernel.nix
+++ b/modules/common/kernel.nix
@@ -1,29 +1,28 @@
 { lib, ... }:
-with lib;
 {
   boot.kernel.sysctl = {
-    "fs.file-max" = pow 2 17;
-    "fs.inotify.max_user_watches" = pow 2 19;
+    "fs.file-max" = lib.pow 2 17;
+    "fs.inotify.max_user_watches" = lib.pow 2 19;
     "fs.suid_dumpable" = 0;
     "kernel.core_uses_pid" = 1;
     "kernel.exec-shield" = 1;
     "kernel.kptr_restrict" = 1;
     "kernel.maps_protect" = 1;
-    "kernel.msgmax" = pow 2 16;
-    "kernel.msgmnb" = pow 2 16;
-    "kernel.pid_max" = pow 2 16;
+    "kernel.msgmax" = lib.pow 2 16;
+    "kernel.msgmnb" = lib.pow 2 16;
+    "kernel.pid_max" = lib.pow 2 16;
     "kernel.randomize_va_space" = 2;
-    "kernel.shmall" = pow 2 28;
-    "kernel.shmmax" = pow 2 28;
+    "kernel.shmall" = lib.pow 2 28;
+    "kernel.shmmax" = lib.pow 2 28;
     "kernel.sysrq" = 0;
-    "vm.dirty_background_bytes" = pow 2 22;
+    "vm.dirty_background_bytes" = lib.pow 2 22;
     "vm.dirty_background_ratio" = 5;
-    "vm.dirty_bytes" = pow 2 22;
+    "vm.dirty_bytes" = lib.pow 2 22;
     "vm.dirty_ratio" = 30;
-    "vm.min_free_kbytes" = pow 2 16;
-    "vm.mmap_min_addr" = pow 2 12;
-    "vm.overcommit_memory" = mkDefault 0;
-    "vm.overcommit_ratio" = mkDefault 50;
+    "vm.min_free_kbytes" = lib.pow 2 16;
+    "vm.mmap_min_addr" = lib.pow 2 12;
+    "vm.overcommit_memory" = lib.mkDefault 0;
+    "vm.overcommit_ratio" = lib.mkDefault 50;
     "vm.vfs_cache_pressure" = 50;
   };
 
diff --git a/modules/common/locale.nix b/modules/common/locale.nix
index 372b69b..acd1ecd 100644
--- a/modules/common/locale.nix
+++ b/modules/common/locale.nix
@@ -51,7 +51,6 @@ with lib;
       "caps:escape"
       "compose:menu"
       "grp:win_space_toggle"
-      "terminate:ctrl_alt_bksp"
     ];
   };
 }
diff --git a/modules/common/networking.nix b/modules/common/networking.nix
index f681deb..71df24a 100644
--- a/modules/common/networking.nix
+++ b/modules/common/networking.nix
@@ -5,31 +5,30 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.common.networking;
 in
 {
-  options.nixfiles.modules.common.networking.onlyDefault = mkEnableOption "custom networking settings";
+  options.nixfiles.modules.common.networking.onlyDefault = lib.mkEnableOption "custom networking settings";
 
-  config = mkIf (!cfg.onlyDefault) {
+  config = lib.mkIf (!cfg.onlyDefault) {
     ark.directories =
       with config.networking;
-      optional networkmanager.enable "/etc/NetworkManager/system-connections"
-      ++ optional wireless.iwd.enable "/var/lib/iwd";
+      lib.optional networkmanager.enable "/etc/NetworkManager/system-connections"
+      ++ lib.optional wireless.iwd.enable "/var/lib/iwd";
 
-    networking = mkMerge [
+    networking = lib.mkMerge [
       {
-        domain = my.domain.shire;
+        domain = lib.my.domain.shire;
 
         hostName = this.hostname;
-        hostId = substring 0 8 (builtins.hashString "md5" this.hostname);
+        hostId = lib.substring 0 8 (builtins.hashString "md5" this.hostname);
 
         # Remove default hostname mappings. This is required at least by the
         # current implementation of the monitoring module.
         hosts = {
-          "127.0.0.2" = mkForce [ ];
-          "::1" = mkForce [ ];
+          "127.0.0.2" = lib.mkForce [ ];
+          "::1" = lib.mkForce [ ];
         };
 
         # There's no way[1] to configure DNS server priority in
@@ -41,7 +40,7 @@ in
         #
         # [1]: https://askubuntu.com/questions/1116732/how-do-i-list-dns-server-order-in-systemd-resolve
         # [2]: https://github.com/systemd/systemd/issues/6076
-        nameservers = with my.configurations.manwe.wireguard; [
+        nameservers = with lib.my.configurations.manwe.wireguard; [
           ipv6.address
           ipv4.address
         ];
@@ -68,49 +67,53 @@ in
         let
           interface = "eth0"; # This assumes `usePredictableInterfaceNames` is false.
         in
-        mkIf (hasAttr "ipv4" this && hasAttr "ipv6" this) {
+        lib.mkIf (lib.hasAttr "ipv4" this && lib.hasAttr "ipv6" this) {
           usePredictableInterfaceNames = false; # NOTE This can break something!
           interfaces.${interface} = {
             ipv4.addresses =
               with this.ipv4;
-              optional (isString address && isInt prefixLength) { inherit address prefixLength; };
+              lib.optional (lib.isString address && lib.isInt prefixLength) {
+                inherit address prefixLength;
+              };
 
             ipv6.addresses =
               with this.ipv6;
-              optional (isString address && isInt prefixLength) { inherit address prefixLength; };
+              lib.optional (lib.isString address && lib.isInt prefixLength) {
+                inherit address prefixLength;
+              };
           };
           defaultGateway =
             with this.ipv4;
-            mkIf (isString gatewayAddress) {
+            lib.mkIf (lib.isString gatewayAddress) {
               inherit interface;
               address = gatewayAddress;
             };
           defaultGateway6 =
             with this.ipv6;
-            mkIf (isString gatewayAddress) {
+            lib.mkIf (lib.isString gatewayAddress) {
               inherit interface;
               address = gatewayAddress;
             };
         }
       )
-      (mkIf this.isHeadful {
-        interfaces.eth0.useDHCP = mkDefault true;
+      (lib.mkIf this.isHeadful {
+        interfaces.eth0.useDHCP = lib.mkDefault true;
 
         networkmanager = {
-          enable = mkDefault true;
+          enable = lib.mkDefault true;
           unmanaged = [
             "bridge"
             "ethernet"
             "loopback"
             "wireguard"
           ];
-          plugins = mkForce [ ];
+          plugins = lib.mkForce [ ];
           wifi.backend = "iwd";
         };
 
         wireless = {
           enable = false;
-          iwd.enable = mkDefault true;
+          iwd.enable = lib.mkDefault true;
           userControlled.enable = true;
           allowAuxiliaryImperativeNetworks = true;
         };
@@ -121,12 +124,12 @@ in
       llmnr = "false";
       dnsovertls = "opportunistic";
       dnssec = "allow-downgrade";
-      fallbackDns = dns.mkDoT dns.const.quad9.ecs;
+      fallbackDns = lib.dns.mkDoT lib.dns.const.quad9.ecs;
     };
 
     environment = {
-      shellAliases = listToAttrs (
-        map ({ name, value }: nameValuePair name "${pkgs.iproute2}/bin/${value}") [
+      shellAliases = lib.listToAttrs (
+        map ({ name, value }: lib.nameValuePair name "${pkgs.iproute2}/bin/${value}") [
           {
             name = "bridge";
             value = "bridge -color=always";
diff --git a/modules/common/nix.nix b/modules/common/nix.nix
index 58d572f..6a75e85 100644
--- a/modules/common/nix.nix
+++ b/modules/common/nix.nix
@@ -95,6 +95,8 @@ in
       overlays = [ inputs.self.overlays.default ];
     };
 
+    programs.nh.enable = this.isHeadful;
+
     environment = {
       defaultPackages = [ ];
       systemPackages =
diff --git a/modules/common/shell/default.nix b/modules/common/shell/default.nix
index 4ae41d8..cacb411 100644
--- a/modules/common/shell/default.nix
+++ b/modules/common/shell/default.nix
@@ -5,14 +5,13 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.common.shell;
 in
 {
-  options.nixfiles.modules.common.shell.aliases = mkOption {
+  options.nixfiles.modules.common.shell.aliases = lib.mkOption {
     description = "An attribute set of shell aliases.";
-    type = with types; attrsOf str;
+    type = with lib.types; attrsOf str;
     default = { };
   };
 
@@ -24,8 +23,8 @@ in
 
           initExtra =
             let
-              aliasCompletions = concatStringsSep "\n" (
-                mapAttrsToList (name: _: "complete -F _complete_alias ${name}") cfg.aliases
+              aliasCompletions = lib.concatStringsSep "\n" (
+                lib.mapAttrsToList (name: _: "complete -F _complete_alias ${name}") cfg.aliases
               );
             in
             ''
@@ -45,7 +44,7 @@ in
 
               source "${./functions.bash}"
 
-              source "${getExe' pkgs.complete-alias "complete_alias"}"
+              source "${lib.getExe' pkgs.complete-alias "complete_alias"}"
               ${aliasCompletions}
 
               # https://github.com/garabik/grc?tab=readme-ov-file#bash
@@ -73,19 +72,18 @@ in
           ];
 
           shellAliases =
-            listToAttrs (
+            lib.listToAttrs (
               map
                 (
                   { name, value }:
-                  nameValuePair name (
-                    with pkgs;
+                  lib.nameValuePair name (
                     let
                       pkg =
                         if this.isHeadful then
                           (pkgs.coreutils.overrideAttrs (
                             _: super: {
                               patches = (super.patches or [ ]) ++ [
-                                (fetchpatch {
+                                (pkgs.fetchpatch {
                                   url = "https://raw.githubusercontent.com/jarun/advcpmv/1e2b1c6b74fa0974896bf94604279a3f74b37a63/advcpmv-0.9-9.5.patch";
                                   hash = "sha256-LRfb4heZlAUKiXl/hC/HgoqeGMxCt8ruBYZUrbzSH+Y=";
                                 })
@@ -93,24 +91,24 @@ in
                             }
                           ))
                         else
-                          coreutils;
+                          pkgs.coreutils;
                     in
-                    "${getExe' pkg "coreutils"} --coreutils-prog=${value}"
+                    "${lib.getExe' pkg "coreutils"} --coreutils-prog=${value}"
                   )
                 )
                 (
                   let
                     mkAlias =
                       {
-                        name ? head command,
+                        name ? lib.head command,
                         command,
                       }:
                       {
                         inherit name;
-                        value = concatStringsSep " " command;
+                        value = lib.concatStringsSep " " command;
                       };
 
-                    progressBar = optionalString this.isHeadful "--progress-bar";
+                    progressBar = lib.optionalString this.isHeadful "--progress-bar";
                   in
                   [
                     (mkAlias {
@@ -171,7 +169,7 @@ in
                   ]
                 )
             )
-            // (genAttrs [
+            // (lib.genAttrs [
               "grep"
               "egrep"
               "fgrep"
diff --git a/modules/common/systemd.nix b/modules/common/systemd.nix
index f832518..996096e 100644
--- a/modules/common/systemd.nix
+++ b/modules/common/systemd.nix
@@ -1,5 +1,6 @@
 {
   config,
+  lib,
   ...
 }:
 {
@@ -35,8 +36,16 @@
       user = {
         inherit extraConfig;
       };
+
+      suppressedSystemUnits = lib.optionals config.nixfiles.modules.ark.enable [
+        "systemd-machine-id-commit.service"
+      ];
     };
 
+  boot.initrd.systemd.suppressedUnits = lib.optionals config.nixfiles.modules.ark.enable [
+    "systemd-machine-id-commit.service"
+  ];
+
   environment.variables = {
     SYSTEMD_PAGERSECURE = "1";
     SYSTEMD_PAGER = "less";
diff --git a/modules/common/xdg.nix b/modules/common/xdg.nix
index 0b807b7..df7d624 100644
--- a/modules/common/xdg.nix
+++ b/modules/common/xdg.nix
@@ -4,7 +4,6 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.common.xdg;
 in
@@ -20,44 +19,44 @@ in
       ];
     in
     [
-      (mkAliasOptionModule [
+      (lib.mkAliasOptionModule [
         "dirs"
         "cache"
       ] (withBase "cacheHome"))
-      (mkAliasOptionModule [
+      (lib.mkAliasOptionModule [
         "dirs"
         "config"
       ] (withBase "configHome"))
-      (mkAliasOptionModule [
+      (lib.mkAliasOptionModule [
         "dirs"
         "data"
       ] (withBase "dataHome"))
-      (mkAliasOptionModule [
+      (lib.mkAliasOptionModule [
         "dirs"
         "state"
       ] (withBase "stateHome"))
-      (mkAliasOptionModule [ "userDirs" ] (withBase "userDirs"))
+      (lib.mkAliasOptionModule [ "userDirs" ] (withBase "userDirs"))
     ];
 
   options.nixfiles.modules.common.xdg = {
-    cacheHome = mkOption {
-      type = types.str;
+    cacheHome = lib.mkOption {
+      type = lib.types.str;
       default = "${config.hm.home.homeDirectory}/.cache";
     };
-    configHome = mkOption {
-      type = types.str;
+    configHome = lib.mkOption {
+      type = lib.types.str;
       default = "${config.hm.home.homeDirectory}/.config";
     };
-    dataHome = mkOption {
-      type = types.str;
+    dataHome = lib.mkOption {
+      type = lib.types.str;
       default = "${config.hm.home.homeDirectory}/.local/share";
     };
-    stateHome = mkOption {
-      type = types.str;
+    stateHome = lib.mkOption {
+      type = lib.types.str;
       default = "${config.hm.home.homeDirectory}/.local/state";
     };
-    userDirs = mkOption {
-      type = types.attrs;
+    userDirs = lib.mkOption {
+      type = lib.types.attrs;
       default =
         let
           inherit (config.my) home;
@@ -76,9 +75,9 @@ in
           videos = tmp;
         };
     };
-    defaultApplications = mkOption {
+    defaultApplications = lib.mkOption {
       description = "Default applications.";
-      type = with types; attrsOf (listOf str);
+      type = with lib.types; attrsOf (listOf str);
       default = { };
     };
   };
@@ -89,7 +88,7 @@ in
       sounds.enable = this.isHeadful;
     };
 
-    hm.xdg = mkMerge [
+    hm.xdg = lib.mkMerge [
       (with cfg; {
         enable = true;
 
@@ -99,11 +98,11 @@ in
         inherit stateHome;
         inherit userDirs;
       })
-      (mkIf this.isHeadful {
+      (lib.mkIf this.isHeadful {
         mimeApps = {
           enable = true;
-          defaultApplications = mkMerge (
-            mapAttrsToList (n: v: genAttrs v (_: [ "${n}.desktop" ])) cfg.defaultApplications
+          defaultApplications = lib.mkMerge (
+            lib.mapAttrsToList (n: v: lib.genAttrs v (_: [ "${n}.desktop" ])) cfg.defaultApplications
           );
         };
       })
diff --git a/modules/curl.nix b/modules/curl.nix
index 6895262..3c318fc 100644
--- a/modules/curl.nix
+++ b/modules/curl.nix
@@ -20,7 +20,7 @@ in
     '';
 
     environment.systemPackages = with pkgs; [
-      curl
+      curlHTTP3
       (writeShellScriptBin "0x0" ''
         url="https://0x0.st"
         form="file=@"
diff --git a/modules/emacs/doom/config.el b/modules/emacs/doom/config.el
index 85fe4a9..464a8b2 100644
--- a/modules/emacs/doom/config.el
+++ b/modules/emacs/doom/config.el
@@ -260,3 +260,105 @@
                                  (setq-local company-idle-delay 0.1))))
   :init
   (setq! hledger-input-buffer-height 20))
+
+;;
+;;; LLM
+;;
+
+(use-package! gptel
+  :config
+  (setq! gptel-model 'codegemma:7b
+         gptel-backend (gptel-make-ollama "ollama"
+                         :host "eonwe.shire.net:11434"
+                         :stream t
+                         :models '(mistral:7b
+                                   codegemma:7b
+                                   codellama:7b
+                                   deepseek-coder-v2:16b
+                                   llama3.2:3b))))
+
+(use-package! ellama
+  :init
+  (setq! ellama-naming-scheme 'ellama-generate-name-by-time)
+  :config
+  (require 'llm-ollama)
+  (setq! ellama-provider (make-llm-ollama
+                          :scheme "http"
+                          :host "eonwe.shire.net"
+                          :port 11434
+                          :chat-model "llama3.2:3b"
+                          :embedding-model "nomic-embed-text:latest")
+         ellama-providers '(("llama" . (make-llm-ollama
+                                        :scheme "http"
+                                        :host "eonwe.shire.net"
+                                        :port 11434
+                                        :chat-model "llama3.2:3b"
+                                        :embedding-model "nomic-embed-text:latest"))
+                            ("codellama" . (make-llm-ollama
+                                            :scheme "http"
+                                            :host "eonwe.shire.net"
+                                            :port 11434
+                                            :chat-model "codellama:7b"
+                                            :embedding-model "nomic-embed-text:latest"))
+                            ("qwen" . (make-llm-ollama
+                                       :scheme "http"
+                                       :host "eonwe.shire.net"
+                                       :port 11434
+                                       :chat-model "qwen2.5:7b"
+                                       :embedding-model "nomic-embed-text:latest"))
+                            ("gemma" . (make-llm-ollama
+                                        :scheme "http"
+                                        :host "eonwe.shire.net"
+                                        :port 11434
+                                        :chat-model "gemma2:9b"
+                                        :embedding-model "nomic-embed-text:latest"))
+                            ("codegemma" . (make-llm-ollama
+                                            :scheme "http"
+                                            :host "eonwe.shire.net"
+                                            :port 11434
+                                            :chat-model "codegemma:7b"
+                                            :embedding-model "nomic-embed-text:latest"))
+                            ("mistral" . (make-llm-ollama
+                                          :scheme "http"
+                                          :host "eonwe.shire.net"
+                                          :port 11434
+                                          :chat-model "mistral:7b"
+                                          :embedding-model "nomic-embed-text:latest"))
+                            ("hermes" . (make-llm-ollama
+                                         :scheme "http"
+                                         :host "eonwe.shire.net"
+                                         :port 11434
+                                         :chat-model "hermes3:8b"
+                                         :embedding-model "nomic-embed-text:latest"))
+                            ("deepseek" . (make-llm-ollama
+                                           :scheme "http"
+                                           :host "eonwe.shire.net"
+                                           :port 11434
+                                           :chat-model "deepseek-coder-v2:16b"
+                                           :embedding-model "nomic-embed-text:latest")))
+         ellama-translation-provider (make-llm-ollama
+                                      :scheme "http"
+                                      :host "eonwe.shire.net"
+                                      :port 11434
+                                      :chat-model "qwen2.5:7b"
+                                      :embedding-model "nomic-embed-text:latest")
+         ellama-summarization-provider (make-llm-ollama
+                                        :scheme "http"
+                                        :host "eonwe.shire.net"
+                                        :port 11434
+                                        :chat-model "mistral:7b"
+                                        :embedding-model "nomic-embed-text:latest")))
+
+(use-package! magit-gptcommit
+  :after magit
+  :config
+  (require 'llm-ollama)
+  (setq! magit-gptcommit-llm-provider (make-llm-ollama
+                                       :scheme "http"
+                                       :host "eonwe.shire.net"
+                                       :port 11434
+                                       :chat-model "llama3.2:3b"
+                                       :embedding-model "nomic-embed-text:latest"))
+
+
+  (magit-gptcommit-status-buffer-setup))
diff --git a/modules/emacs/doom/init.el b/modules/emacs/doom/init.el
index 8575c3f..3845fd6 100644
--- a/modules/emacs/doom/init.el
+++ b/modules/emacs/doom/init.el
@@ -48,7 +48,7 @@
 
        :checkers
        syntax
-       (spell +everywhere +icons)
+       (spell +flyspell +everywhere +icons)
        grammar
 
        :tools
diff --git a/modules/emacs/doom/packages.el b/modules/emacs/doom/packages.el
index fb521bc..8fb24f4 100644
--- a/modules/emacs/doom/packages.el
+++ b/modules/emacs/doom/packages.el
@@ -21,6 +21,10 @@
   :recipe (:host gitlab
            :repo "emacs-ansible/emacs-ansible"))
 
+(package! gptel)
+(package! ellama)
+(package! magit-gptcommit)
+
 ;; (package! tvl
 ;;   :recipe (:host nil
 ;;            :repo "https://code.tvl.fyi/depot.git:/tools/emacs-pkgs/tvl.git"
diff --git a/modules/firefox/addons.json b/modules/firefox/addons.json
index 5c6a090..2a217c2 100644
--- a/modules/firefox/addons.json
+++ b/modules/firefox/addons.json
@@ -19,6 +19,10 @@
     "slug": "languagetool"
   },
   {
+    "pname": "metamask",
+    "slug": "ether-metamask"
+  },
+  {
     "slug": "no-pdf-download"
   },
   {
@@ -32,6 +36,9 @@
     "slug": "skip-redirect"
   },
   {
+    "slug": "switchyomega"
+  },
+  {
     "slug": "ublock-origin"
   },
   {
@@ -40,8 +47,5 @@
   },
   {
     "slug": "violentmonkey"
-  },
-  {
-    "slug": "switchyomega"
   }
 ]
diff --git a/modules/firefox/addons.nix b/modules/firefox/addons.nix
index e416a3f..ebe834a 100644
--- a/modules/firefox/addons.nix
+++ b/modules/firefox/addons.nix
@@ -5,10 +5,10 @@
 {
   "bitwarden" = buildFirefoxXpiAddon {
     pname = "bitwarden";
-    version = "2024.10.0";
+    version = "2024.10.1";
     addonId = "{446900e4-71c2-419f-a6a7-df9c091e268b}";
-    url = "https://addons.mozilla.org/firefox/downloads/file/4363548/bitwarden_password_manager-2024.10.0.xpi";
-    sha256 = "9ea9428444870a74ae1999d77eb12d97a45275c85e83d6afdcbc4597fa3eccfb";
+    url = "https://addons.mozilla.org/firefox/downloads/file/4371752/bitwarden_password_manager-2024.10.1.xpi";
+    sha256 = "7b7357ddce2756dc536b86b5c14139ec09731c1c114ac82807c60fba3ced12a5";
     meta = with lib; {
       homepage = "https://bitwarden.com";
       description = "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.";
@@ -144,6 +144,36 @@
       platforms = platforms.all;
     };
   };
+  "metamask" = buildFirefoxXpiAddon {
+    pname = "metamask";
+    version = "12.0.6";
+    addonId = "webextension@metamask.io";
+    url = "https://addons.mozilla.org/firefox/downloads/file/4342782/ether_metamask-12.0.6.xpi";
+    sha256 = "a66e20bbe5ded1b9408420e4c2ffc82369cc3bfd27350afe25f2c0ef6b26ff3b";
+    meta = with lib; {
+      description = "Ethereum Browser Extension";
+      mozPermissions = [
+        "storage"
+        "unlimitedStorage"
+        "clipboardWrite"
+        "http://localhost:8545/"
+        "https://*.infura.io/"
+        "https://*.codefi.network/"
+        "https://*.cx.metamask.io/"
+        "https://chainid.network/chains.json"
+        "https://lattice.gridplus.io/*"
+        "activeTab"
+        "webRequest"
+        "*://*.eth/"
+        "notifications"
+        "file://*/*"
+        "http://*/*"
+        "https://*/*"
+        "*://connect.trezor.io/*/popup.html"
+      ];
+      platforms = platforms.all;
+    };
+  };
   "no-pdf-download" = buildFirefoxXpiAddon {
     pname = "no-pdf-download";
     version = "1.0.6";
@@ -187,10 +217,10 @@
   };
   "rikaichamp" = buildFirefoxXpiAddon {
     pname = "rikaichamp";
-    version = "1.21.1";
+    version = "1.22.0";
     addonId = "{59812185-ea92-4cca-8ab7-cfcacee81281}";
-    url = "https://addons.mozilla.org/firefox/downloads/file/4355635/10ten_ja_reader-1.21.1.xpi";
-    sha256 = "81d85cfdc03cb0c921cac84547e7a7a539af11ff9a81dd901b3f3bfa67ba45f1";
+    url = "https://addons.mozilla.org/firefox/downloads/file/4371439/10ten_ja_reader-1.22.0.xpi";
+    sha256 = "d6f3197b7e3383f2723b9376d93e03fe515e5c610f9c0723d9618b10d3cc4bf1";
     meta = with lib; {
       homepage = "https://github.com/birchill/10ten-ja-reader/";
       description = "Quickly translate Japanese by hovering over words. Formerly released as Rikaichamp.";
diff --git a/modules/firefox/default.nix b/modules/firefox/default.nix
index b7e47b6..51e464f 100644
--- a/modules/firefox/default.nix
+++ b/modules/firefox/default.nix
@@ -127,6 +127,7 @@ in
                 darkreader
                 furiganaize
                 languagetool
+                metamask
                 no-pdf-download
                 redirector
                 rikaichamp
diff --git a/modules/games/gamemode.nix b/modules/games/gamemode.nix
index eb485f8..4e57a8b 100644
--- a/modules/games/gamemode.nix
+++ b/modules/games/gamemode.nix
@@ -1,13 +1,12 @@
 { config, lib, ... }:
-with lib;
 let
   cfg = config.nixfiles.modules.games.gamemode;
 in
 {
-  options.nixfiles.modules.games.gamemode.enable = mkEnableOption "Feral GameMode";
+  options.nixfiles.modules.games.gamemode.enable = lib.mkEnableOption "Feral GameMode";
 
-  config = mkIf cfg.enable {
-    hm.xdg.configFile."gamemode.ini".text = generators.toINI { } { general.softrealtime = "auto"; };
+  config = lib.mkIf cfg.enable {
+    hm.xdg.configFile."gamemode.ini".text = lib.generators.toINI { } { general.softrealtime = "auto"; };
 
     programs.gamemode.enable = true;
   };
diff --git a/modules/games/minecraft.nix b/modules/games/minecraft.nix
index f93a139..f849360 100644
--- a/modules/games/minecraft.nix
+++ b/modules/games/minecraft.nix
@@ -5,7 +5,6 @@
   pkgs,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.games.minecraft;
 in
@@ -13,28 +12,30 @@ in
   imports = [ inputs.minecraft.nixosModules.minecraft-servers ];
 
   options.nixfiles.modules.games.minecraft = {
-    client.enable = mkEnableOption "Minecraft client";
+    client.enable = lib.mkEnableOption "Minecraft client";
     server = {
-      enable = mkEnableOption "Minecraft server";
+      enable = lib.mkEnableOption "Minecraft server";
 
-      port = mkOption {
+      port = lib.mkOption {
         description = "Server port.";
-        type = types.port;
+        type = lib.types.port;
         default = 25565;
       };
 
-      memory = mkOption {
+      memory = lib.mkOption {
         description = "Amount of RAM to allocate.";
-        type = types.str;
+        type = lib.types.str;
         default = "2G";
       };
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.client.enable { hm.home.packages = [ pkgs.prismlauncher ]; })
-    (mkIf cfg.server.enable {
-      nixfiles.modules.common.nix.allowedUnfreePackages = [ "minecraft-server" ];
+  config = lib.mkMerge [
+    (lib.mkIf cfg.client.enable { hm.home.packages = [ pkgs.prismlauncher ]; })
+    (lib.mkIf cfg.server.enable {
+      nixfiles.modules.common.nix.allowedUnfreePackages = [
+        "minecraft-server" # proprietary
+      ];
 
       ark.directories = [ config.services.minecraft-servers.dataDir ];
 
@@ -50,7 +51,7 @@ in
 
           # https://api.papermc.io/v2/projects/paper
           # https://github.com/Infinidoge/nix-minecraft/blob/master/pkgs/paper-servers/lock.json
-          package = pkgs.paperServers.paper-1_21_47;
+          package = pkgs.minecraftServers.paper-1_21_3;
 
           serverProperties = {
             # motd = "";
@@ -71,7 +72,7 @@ in
           };
 
           jvmOpts =
-            (concatStringsSep " " [
+            (lib.concatStringsSep " " [
               "-Xms${cfg.server.memory}"
               "-Xmx${cfg.server.memory}"
               "--add-modules=jdk.incubator.vector" # Required by some plugins.
diff --git a/modules/games/steam-run.nix b/modules/games/steam-run.nix
index be06c78..9e3c962 100644
--- a/modules/games/steam-run.nix
+++ b/modules/games/steam-run.nix
@@ -2,72 +2,49 @@
   config,
   lib,
   pkgs,
-  pkgsRev,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.games.steam-run;
 in
 {
   options.nixfiles.modules.games.steam-run = {
-    enable = mkEnableOption "native Steam runtime";
+    enable = lib.mkEnableOption "native Steam runtime";
 
     quirks = {
-      blackIsleStudios = mkEnableOption "fixes for games from Black Isle Studios";
-      cryptOfTheNecrodancer = mkEnableOption ''fixes for "Crypt of the NecroDancer" issues'';
-      mountAndBladeWarband = mkEnableOption ''fixes for "Mount & Blade: Warband" issues'';
+      blackIsleStudios = lib.mkEnableOption "fixes for games from Black Isle Studios";
+      cryptOfTheNecrodancer = lib.mkEnableOption ''fixes for "Crypt of the NecroDancer" issues'';
+      mountAndBladeWarband = lib.mkEnableOption ''fixes for "Mount & Blade: Warband" issues'';
     };
   };
 
-  config = mkIf cfg.enable {
-    nixfiles.modules.games.steam.enable = true;
+  config = lib.mkIf cfg.enable {
+    nixfiles.modules = {
+      games.steam.enable = true;
 
-    hm.home.packages = with pkgs; [
-      (steam.override {
+      common.nix.allowedUnfreePackages = lib.optionals cfg.quirks.mountAndBladeWarband [
+        "fmod" # proprietary
+      ];
+    };
+
+    hm.home.packages = [
+      (pkgs.steam.override {
+        extraEnv.MANGOHUD = 1;
         extraLibraries =
           _:
-          with cfg.quirks;
-          optional blackIsleStudios openssl_1_0_0
-          ++ optional cryptOfTheNecrodancer (pkgsRev "d1c3fea7ecbed758168787fe4e4a3157e52bc808" "sha256-3muuhz3fjtF1bz32UXOYCho51E8JSeEwo2iDZFQJdXo=")
-          .flac
-          ++ optionals mountAndBladeWarband [
-            (glew.overrideAttrs (
-              _: super:
-              let
-                opname = super.pname;
-              in
-              rec {
-                pname = "${opname}-steam-run-fix";
-                inherit (super) version;
-                src = fetchurl {
-                  url = "mirror://sourceforge/${opname}/${opname}-${version}.tgz";
-                  hash = "sha256-BN6R5+Z2MDm8EZQAlc2cf4gLq6ghlqd2X3J6wFqZPJU=";
-                };
-              }
-            ))
-            (fmodex.overrideAttrs (
-              _: super:
-              let
-                opname = super.pname;
-              in
-              rec {
-                pname = "${opname}-steam-run-fix";
-                inherit (super) version;
-                installPhase =
-                  let
-                    libPath = makeLibraryPath [
-                      alsa-lib
-                      libpulseaudio
-                      stdenv.cc.cc
-                    ];
-                  in
-                  ''
-                    install -Dm755 api/lib/libfmodex64-${version}.so $out/lib/libfmodex64.so
-                    patchelf --set-rpath ${libPath} $out/lib/libfmodex64.so
-                  '';
-              }
-            ))
+          lib.optionals cfg.quirks.blackIsleStudios [
+            pkgs.openssl_1_0_0
+          ]
+          ++ lib.optionals cfg.quirks.cryptOfTheNecrodancer [
+            (lib.packages.fromRev "d1c3fea7ecbed758168787fe4e4a3157e52bc808" "sha256-3muuhz3fjtF1bz32UXOYCho51E8JSeEwo2iDZFQJdXo=")
+            .flac
+          ]
+          ++ lib.optionals cfg.quirks.mountAndBladeWarband [
+            (pkgs.fmodex.overrideAttrs (oldAttrs: {
+              postInstall = ''
+                ln -s $out/lib/libfmodex64.so $out/lib/libfmodex-${oldAttrs.version}.so
+              '';
+            }))
           ];
       }).run
     ];
diff --git a/modules/git/default.nix b/modules/git/default.nix
index b618a57..f370ae6 100644
--- a/modules/git/default.nix
+++ b/modules/git/default.nix
@@ -8,38 +8,37 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.git;
 in
 {
   options.nixfiles.modules.git = {
-    client.enable = mkEnableOption "Git client";
+    client.enable = lib.mkEnableOption "Git client";
 
     server = {
-      enable = mkEnableOption "Git server";
+      enable = lib.mkEnableOption "Git server";
 
-      domain = mkOption {
+      domain = lib.mkOption {
         description = "Domain name sans protocol scheme.";
-        type = with types; nullOr str;
+        type = with lib.types; nullOr str;
         default = "git.${config.networking.domain}";
       };
 
-      package = mkOption {
+      package = lib.mkOption {
         description = "Package.";
-        type = types.package;
+        type = lib.types.package;
         default = pkgs.cgit;
       };
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.client.enable {
+  config = lib.mkMerge [
+    (lib.mkIf cfg.client.enable {
       secrets = {
         glab-cli-config = {
           file = "${inputs.self}/secrets/glab-cli-config";
           path = "${config.dirs.config}/glab-cli/config.yml";
-          owner = my.username;
+          owner = lib.my.username;
         };
         # NOTE SSO requires relogin every day, so keeping persistent auth tokens
         # doesn't work.
@@ -51,7 +50,7 @@ in
         hut = {
           file = "${inputs.self}/secrets/hut";
           path = "${config.dirs.config}/hut/config";
-          owner = my.username;
+          owner = lib.my.username;
         };
       };
 
@@ -73,10 +72,10 @@ in
 
             package = if this.isHeadful then pkgs.gitFull else pkgs.gitMinimal;
 
-            userName = my.username;
-            userEmail = my.email;
+            userName = lib.my.username;
+            userEmail = lib.my.email;
             signing = {
-              inherit (my.pgp) key;
+              inherit (lib.my.pgp) key;
               signByDefault = true;
             };
 
@@ -102,48 +101,46 @@ in
                 };
                 submodule.recurse = true;
                 sendemail = rec {
-                  smtpServer = my.domain.shire;
-                  smtpUser = "${my.username}@${smtpServer}";
+                  smtpServer = lib.my.domain.shire;
+                  smtpUser = "${lib.my.username}@${smtpServer}";
                   smtpEncryption = "ssl";
                   smtpServerPort = 465;
                   annotate = true;
                   confirm = "always";
                 };
                 column.ui = "auto";
-                github.user = my.username;
-                gitlab.user = my.username;
+                github.user = lib.my.username;
+                gitlab.user = lib.my.username;
               }
-              // mapAttrs' (name: value: nameValuePair ''url "git@${value}:"'' { insteadOf = "${name}:"; }) {
+              // lib.mapAttrs' (n: v: lib.nameValuePair ''url "git@${v}:"'' { insteadOf = "${n}:"; }) {
                 "bitbucket" = "bitbucket.com";
                 "codeberg" = "codeberg.org";
                 "github" = "github.com";
                 "gitlab" = "gitlab.com";
                 "sourcehut" = "git.sr.ht";
               }
-              //
-                mapAttrs' (name: values: nameValuePair ''url "https://${values}/"'' { insteadOf = "${name}:"; })
-                  {
-                    "alpine" = "gitlab.alpinelinux.org";
-                    "clan" = "git.clan.lol";
-                    "debian" = "salsa.debian.org";
-                    "freedesktop" = "gitlab.freedesktop.org";
-                    "gnome" = "gitlab.gnome.org";
-                    "haskell" = "gitlab.haskell.org";
-                    "homotopic" = "gitlab.homotopic.tech";
-                    "horizon" = "gitlab.horizon-haskell.net";
-                    "kde" = "invent.kde.org";
-                    "nixca" = "gitlab.nixca.dev";
-                    "notabug" = "notabug.org";
-                    "opencode" = "opencode.net";
-                    "syndicate" = "git.syndicate-lang.org";
-                    "torproject" = "gitlab.torproject.org";
-                    "videolan" = "code.videolan.org";
-                  };
+              // lib.mapAttrs' (n: v: lib.nameValuePair ''url "https://${v}/"'' { insteadOf = "${n}:"; }) {
+                "alpine" = "gitlab.alpinelinux.org";
+                "clan" = "git.clan.lol";
+                "debian" = "salsa.debian.org";
+                "freedesktop" = "gitlab.freedesktop.org";
+                "gnome" = "gitlab.gnome.org";
+                "haskell" = "gitlab.haskell.org";
+                "homotopic" = "gitlab.homotopic.tech";
+                "horizon" = "gitlab.horizon-haskell.net";
+                "kde" = "invent.kde.org";
+                "nixca" = "gitlab.nixca.dev";
+                "notabug" = "notabug.org";
+                "opencode" = "opencode.net";
+                "syndicate" = "git.syndicate-lang.org";
+                "torproject" = "gitlab.torproject.org";
+                "videolan" = "code.videolan.org";
+              };
 
             aliases =
               let
-                git = getExe config.hm.programs.git.package;
-                curl = getExe pkgs.curl;
+                git = lib.getExe config.hm.programs.git.package;
+                curl = lib.getExe pkgs.curl;
               in
               {
                 amend = "commit --amend";
@@ -189,181 +186,178 @@ in
         };
       };
     })
-    (mkIf cfg.server.enable (
-      with cfg.server;
-      {
-        ark.directories = [ config.services.gitolite.dataDir ];
+    (lib.mkIf cfg.server.enable {
+      ark.directories = [ config.services.gitolite.dataDir ];
 
-        nixfiles.modules.nginx = {
-          enable = true;
-          virtualHosts.${domain}.locations = { };
-        };
+      nixfiles.modules.nginx = {
+        enable = true;
+        virtualHosts.${cfg.server.domain}.locations = { };
+      };
 
-        services = {
-          cgit.${domain} = {
-            enable = true;
+      services = {
+        cgit.${cfg.server.domain} = {
+          enable = true;
 
-            package = pkgs.cgit-pink;
+          package = pkgs.cgit-pink;
 
-            # We make gitolite repos readable by the common group.
-            user = "git";
-            group = "git";
+          # We make gitolite repos readable by the common group.
+          user = "git";
+          group = "git";
 
-            scanPath = "${config.services.gitolite.dataDir}/repositories";
+          scanPath = "${config.services.gitolite.dataDir}/repositories";
 
-            settings = {
-              root-title = "git.azahi.cc";
-              root-desc = "British scientists have discovered that using GitHub frequently is harmful to one's mental health, especially GitHub Actions...";
+          settings = {
+            root-title = "git.azahi.cc";
+            root-desc = "British scientists have discovered that using GitHub frequently is harmful to one's mental health, especially GitHub Actions...";
 
-              footer = "${pkgs.writeText "cgit-footer" ''
-                <p style="text-align: center;">Consider giving <a href="https://nixos.org">Nix/NixOS</a> a try! <3</p>
-              ''}";
+            footer = "${pkgs.writeText "cgit-footer" ''
+              <p style="text-align: center;">Consider giving <a href="https://nixos.org">Nix/NixOS</a> a try! <3</p>
+            ''}";
 
-              about-filter = "${pkgs.writeScript "cgit-about-filter.sh" ''
-                #!${pkgs.bash}/bin/sh
-                filename=$1
-                case "$filename" in
-                  *.md)
-                    exec ${pkgs.pandoc}/bin/pandoc -f markdown -t html
-                    ;;
-                  *.org)
-                    exec ${pkgs.pandoc}/bin/pandoc -f org -t html
-                        ;;
-                  *)
-                    echo "<pre>"
-                    ${pkgs.coreutils}/bin/cat
-                    echo "</pre>"
-                    ;;
-                esac
-              ''}";
-              source-filter = "${package}/lib/cgit/filters/syntax-highlighting.py";
-              commit-filter = "${package}/lib/cgit/filters/commit-links.sh";
+            about-filter = "${pkgs.writeScript "cgit-about-filter.sh" ''
+              #!${pkgs.bash}/bin/sh
+              filename=$1
+              case "$filename" in
+                *.md)
+                  exec ${pkgs.pandoc}/bin/pandoc -f markdown -t html
+                  ;;
+                *.org)
+                  exec ${pkgs.pandoc}/bin/pandoc -f org -t html
+                      ;;
+                *)
+                  echo "<pre>"
+                  ${pkgs.coreutils}/bin/cat
+                  echo "</pre>"
+                  ;;
+              esac
+            ''}";
+            source-filter = "${cfg.server.package}/lib/cgit/filters/syntax-highlighting.py";
+            commit-filter = "${cfg.server.package}/lib/cgit/filters/commit-links.sh";
 
-              readme = [
-                ":README"
-                ":readme.md"
-                ":readme.org"
-              ];
+            readme = [
+              ":README"
+              ":readme.md"
+              ":readme.org"
+            ];
 
-              clone-url = "https://$HTTP_HOST/$CGIT_REPO_URL";
+            clone-url = "https://$HTTP_HOST/$CGIT_REPO_URL";
 
-              enable-blame = true;
-              enable-commit-graph = true;
-              enable-follow-links = true;
-              enable-git-config = true;
-              enable-gitweb-owner = true;
-              enable-html-serving = true;
-              enable-http-clone = true;
-              enable-index-links = false;
-              enable-index-owner = false;
-              enable-log-filecount = true;
-              enable-log-linecount = true;
-              enable-subject-links = true;
-              enable-tree-linenumbers = true;
+            enable-blame = true;
+            enable-commit-graph = true;
+            enable-follow-links = true;
+            enable-git-config = true;
+            enable-gitweb-owner = true;
+            enable-html-serving = true;
+            enable-http-clone = true;
+            enable-index-links = false;
+            enable-index-owner = false;
+            enable-log-filecount = true;
+            enable-log-linecount = true;
+            enable-subject-links = true;
+            enable-tree-linenumbers = true;
 
-              branch-sort = "age";
-              repository-sort = "age";
+            branch-sort = "age";
+            repository-sort = "age";
 
-              remove-suffix = true;
+            remove-suffix = true;
 
-              logo = "/logo.gif";
-              logo-link = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
-            };
+            logo = "/logo.gif";
+            logo-link = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
           };
+        };
 
-          gitolite = {
-            enable = true;
-            user = "git";
-            group = "git";
-            adminPubkey = my.ssh.key;
-            extraGitoliteRc = ''
-              # This allows cgit to scan repositories while running under a
-              # different user.
-              $RC{UMASK} = 0027;
+        gitolite = {
+          enable = true;
+          user = "git";
+          group = "git";
+          adminPubkey = lib.my.ssh.key;
+          extraGitoliteRc = ''
+            # This allows cgit to scan repositories while running under a
+            # different user.
+            $RC{UMASK} = 0027;
 
-              # This allows hiding repositories via "cgit.ignore"[1].
-              #
-              # [1]: https://www.omarpolo.com/post/cgit-gitolite.html
-              $RC{GIT_CONFIG_KEYS} = '.*';
-            '';
-          };
+            # This allows hiding repositories via "cgit.ignore"[1].
+            #
+            # [1]: https://www.omarpolo.com/post/cgit-gitolite.html
+            $RC{GIT_CONFIG_KEYS} = '.*';
+          '';
+        };
 
-          nginx.virtualHosts.${domain}.locations =
-            let
-              extraHead = ''
-                ${libNginx.config.appendHead [
-                  ''<meta name="go-import" content="$host$uri git https://$host$uri">''
-                  (libPlausible.htmlPlausibleScript { inherit (cfg.server) domain; })
-                ]}
+        nginx.virtualHosts.${cfg.server.domain}.locations =
+          let
+            extraHead = ''
+              ${libNginx.config.appendHead [
+                ''<meta name="go-import" content="$host$uri git https://$host$uri">''
+                (libPlausible.htmlPlausibleScript { inherit (cfg.server) domain; })
+              ]}
+            '';
+          in
+          {
+            "/" = {
+              extraConfig = lib.mkBefore extraHead;
+              fastcgiParams.HTTP_ACCEPT_ENCODING = "";
+            };
+            "~ /.+/(info/refs|git-upload-pack)" = {
+              extraConfig = lib.mkBefore extraHead;
+              fastcgiParams.HTTP_ACCEPT_ENCODING = "";
+            };
+            "= /logo.gif".alias = "${./logo.gif}";
+            "= /favicon.ico" = {
+              alias = "${./favicon.ico}";
+              extraConfig = lib.mkForce "";
+            };
+            "= /cgit.css" = {
+              alias = pkgs.writeText "cgit.css" ''
+                ${builtins.readFile "${cfg.server.package}/cgit/cgit.css"}
+                * {
+                  line-height: 1.25em;
+                }
+                div#cgit {
+                  font-family: ${
+                    lib.concatMapStringsSep ", " (f: ''"${f}"'') config.fonts.fontconfig.defaultFonts.monospace
+                  }, monospace;
+                  -moz-tab-size: 2;
+                  tab-size: 2;
+                  max-width: 117ch;
+                  margin: auto;
+                }
+                div#cgit table#header td.sub {
+                  border-top: none;
+                }
+                div#cgit table#header td.sub.right {
+                  padding-right: 1em;
+                }
+                div#cgit table.tabs {
+                  border-bottom: none;
+                }
+                div#cgit div.content {
+                  border-bottom: none;
+                }
+                div#cgit table.list th a {
+                  color: inherit;
+                }
+                div#cgit table.list tr:nth-child(even) {
+                  background: inherit;
+                }
+                div#cgit table.list tr:hover {
+                  background: inherit;
+                }
+                div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+                  background: inherit;
+                }
+                div#cgit table.blob td.linenumbers a:target {
+                  color: goldenrod;
+                  text-decoration: underline;
+                  outline: none;
+                }
+                div#cgit div#summary {
+                  max-width: 80ch;
+                }
               '';
-            in
-            {
-              "/" = {
-                extraConfig = mkBefore extraHead;
-                fastcgiParams.HTTP_ACCEPT_ENCODING = "";
-              };
-              "~ /.+/(info/refs|git-upload-pack)" = {
-                extraConfig = mkBefore extraHead;
-                fastcgiParams.HTTP_ACCEPT_ENCODING = "";
-              };
-              "= /logo.gif".alias = "${./logo.gif}";
-              "= /favicon.ico" = {
-                alias = "${./favicon.ico}";
-                extraConfig = mkForce "";
-              };
-              "= /cgit.css" = {
-                alias = pkgs.writeText "cgit.css" ''
-                  ${readFile "${package}/cgit/cgit.css"}
-                  * {
-                    line-height: 1.25em;
-                  }
-                  div#cgit {
-                    font-family: ${
-                      concatMapStringsSep ", " (f: ''"${f}"'') config.fonts.fontconfig.defaultFonts.monospace
-                    }, monospace;
-                    -moz-tab-size: 2;
-                    tab-size: 2;
-                    max-width: 117ch;
-                    margin: auto;
-                  }
-                  div#cgit table#header td.sub {
-                    border-top: none;
-                  }
-                  div#cgit table#header td.sub.right {
-                    padding-right: 1em;
-                  }
-                  div#cgit table.tabs {
-                    border-bottom: none;
-                  }
-                  div#cgit div.content {
-                    border-bottom: none;
-                  }
-                  div#cgit table.list th a {
-                    color: inherit;
-                  }
-                  div#cgit table.list tr:nth-child(even) {
-                    background: inherit;
-                  }
-                  div#cgit table.list tr:hover {
-                    background: inherit;
-                  }
-                  div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
-                    background: inherit;
-                  }
-                  div#cgit table.blob td.linenumbers a:target {
-                    color: goldenrod;
-                    text-decoration: underline;
-                    outline: none;
-                  }
-                  div#cgit div#summary {
-                    max-width: 80ch;
-                  }
-                '';
-                extraConfig = mkForce "";
-              };
+              extraConfig = lib.mkForce "";
             };
-        };
-      }
-    ))
+          };
+      };
+    })
   ];
 }
diff --git a/modules/hyprland.nix b/modules/hyprland.nix
new file mode 100644
index 0000000..cab01b6
--- /dev/null
+++ b/modules/hyprland.nix
@@ -0,0 +1,143 @@
+{
+  config,
+  inputs,
+  lib,
+  ...
+}:
+let
+  cfg = config.nixfiles.modules.hyprland;
+in
+{
+  options.nixfiles.modules.hyprland.enable = lib.mkEnableOption "Hyprland";
+
+  config = lib.mkIf cfg.enable {
+    nixfiles.modules.wayland.enable = true;
+
+    hm = {
+      stylix.targets.hyprland.enable = false;
+
+      wayland.windowManager.hyprland = {
+        enable = true;
+
+        systemd = {
+          enable = true;
+          variables = [ "--all" ];
+        };
+
+        settings = {
+          misc = {
+            disable_hyprland_logo = true;
+            disable_splash_rendering = true;
+          };
+
+          general = {
+            gaps_in = 0;
+            gaps_out = 0;
+          };
+
+          decoration = {
+            blur.enabled = false;
+          };
+
+          animations.enabled = false;
+
+          debug.disable_logs = false;
+
+          input = with config.services.xserver.xkb; {
+            kb_layout = layout;
+            kb_variant = variant;
+            kb_options = options;
+
+            repeat_delay = config.services.xserver.autoRepeatDelay;
+            repeat_rate = config.services.xserver.autoRepeatInterval;
+          };
+
+          bindm = [
+            "SUPER, mouse:272, movewindow"
+            "SUPER, mouse:273, resizewindow"
+            "SUPER ALT, mouse:272, resizewindow"
+          ];
+
+          bind =
+            [
+              "SUPER SHIFT, E, exec, pkill Hyprland"
+
+              "SUPER, D, killactive,"
+              "SUPER, F, fullscreen,"
+
+              "SUPER, G, togglegroup,"
+              "SUPER SHIFT, N, changegroupactive, f"
+              "SUPER SHIFT, P, changegroupactive, b"
+
+              "SUPER, R, togglesplit,"
+              "SUPER, T, togglefloating,"
+              "SUPER, P, pseudo,"
+              "SUPER ALT, ,resizeactive,"
+
+              "SUPER, Return, exec, foot"
+              "SUPER, L, exec, pgrep hyprlock || hyprlock"
+
+              "SUPER, H, movefocus, l"
+              "SUPER, J, movefocus, d"
+              "SUPER, K, movefocus, u"
+              "SUPER, L, movefocus, r"
+
+              "SUPER SHIFT, H, movewindow, l"
+              "SUPER SHIFT, J, movewindow, d"
+              "SUPER SHIFT, K, movewindow, u"
+              "SUPER SHIFT, L, movewindow, r"
+
+              "SUPER ALT, H, resizeactive, 10 0"
+              "SUPER ALT, J, resizeactive, 0 10"
+              "SUPER ALT, K, resizeactive, 0 -10"
+              "SUPER ALT, L, resizeactive, -10 0"
+
+              ", XF86AudioPlay, exec, mpc play"
+              ", XF86AudioPrev, exec, mpc prev"
+              ", XF86AudioNext, exec, mpc next"
+
+              ", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ .1+"
+              ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ .1-"
+
+              ", XF86AudioMute,    exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
+              ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
+
+              ", XF86MonBrightnessUp,   exec, brightnessctl set +5%"
+              ", XF86MonBrightnessDown, exec, brightnessctl set 5%-"
+            ]
+            ++ (builtins.concatLists (
+              builtins.genList (
+                x:
+                let
+                  ws =
+                    let
+                      c = (x + 1) / 10;
+                    in
+                    toString (x + 1 - (c * 10));
+                in
+                [
+                  "SUPER, ${ws}, workspace, ${toString (x + 1)}"
+                  "SUPER SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}"
+                ]
+              ) 10
+            ));
+        };
+      };
+
+      programs.hyprlock.enable = true;
+    };
+
+    programs.hyprland.enable = true;
+
+    nixpkgs.overlays = [ inputs.hyprland.overlays.default ];
+
+    nix.settings = {
+      substituters = [
+        "https://hyprland.cachix.org"
+      ];
+      trusted-public-keys = [
+        "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
+      ];
+    };
+  };
+}
diff --git a/modules/jackett.nix b/modules/jackett.nix
index 07a5b16..5b0b2c0 100644
--- a/modules/jackett.nix
+++ b/modules/jackett.nix
@@ -6,22 +6,21 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.jackett;
 in
 {
   options.nixfiles.modules.jackett = {
-    enable = mkEnableOption "Jackett";
+    enable = lib.mkEnableOption "Jackett";
 
-    domain = mkOption {
+    domain = lib.mkOption {
       description = "Domain name sans protocol scheme.";
-      type = with types; str;
+      type = lib.types.str;
       default = "jackett.${config.networking.domain}";
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     ark.directories = [ "/var/lib/jackett" ];
 
     nixfiles.modules.nginx = {
diff --git a/modules/openssh.nix b/modules/openssh.nix
index 470b6c9..a41f0d6 100644
--- a/modules/openssh.nix
+++ b/modules/openssh.nix
@@ -4,26 +4,25 @@
   pkgs,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.openssh;
 in
 {
   options.nixfiles.modules.openssh = {
-    client.enable = mkEnableOption "OpenSSH client";
+    client.enable = lib.mkEnableOption "OpenSSH client";
     server = {
-      enable = mkEnableOption "OpenSSH server";
+      enable = lib.mkEnableOption "OpenSSH server";
 
-      port = mkOption {
+      port = lib.mkOption {
         description = "OpenSSH server port.";
-        type = types.port;
+        type = lib.types.port;
         default = 22022; # Port 22 should be occupied by a tarpit.
       };
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.client.enable {
+  config = lib.mkMerge [
+    (lib.mkIf cfg.client.enable {
       hm = {
         home.packages = with pkgs; [
           mosh
@@ -49,11 +48,11 @@ in
                 {
                   hostname ? name,
                   port ? 22022, # NOTE This is not the default OpenSSH port.
-                  user ? my.username,
-                  identityFile ? "${config.my.home}/.ssh/${my.username}_${my.ssh.type}",
+                  user ? lib.my.username,
+                  identityFile ? "${config.my.home}/.ssh/${lib.my.username}_${lib.my.ssh.type}",
                   extraAttrs ? { },
                 }:
-                nameValuePair name (
+                lib.nameValuePair name (
                   {
                     inherit
                       hostname
@@ -65,23 +64,23 @@ in
                   // extraAttrs
                 );
 
-              internalServers = mapAttrs' mkBlock (
-                mapAttrs (name: _: { hostname = "${name}.${my.domain.shire}"; }) (
-                  filterAttrs (_: attr: hasAttr "wireguard" attr && attr.isHeadless) my.configurations
+              internalServers = lib.mapAttrs' mkBlock (
+                lib.mapAttrs (name: _: { hostname = "${name}.${lib.my.domain.shire}"; }) (
+                  lib.filterAttrs (_: attr: lib.hasAttr "wireguard" attr && attr.isHeadless) lib.my.configurations
                 )
               );
             in
             internalServers
-            // (mapAttrs' mkBlock {
+            // (lib.mapAttrs' mkBlock {
               gitolite = {
                 user = "git";
-                hostname = "git.${my.domain.shire}";
+                hostname = "git.${lib.my.domain.shire}";
               };
             });
         };
       };
     })
-    (mkIf cfg.server.enable {
+    (lib.mkIf cfg.server.enable {
       ark.files = [
         "/etc/ssh/ssh_host_ed25519_key"
         "/etc/ssh/ssh_host_ed25519_key.pub"
@@ -101,7 +100,7 @@ in
             KbdInteractiveAuthentication = false;
             MaxAuthTries = 3;
             PasswordAuthentication = false;
-            PermitRootLogin = mkForce "no";
+            PermitRootLogin = lib.mkForce "no";
           };
         };
 
diff --git a/modules/profiles/default.nix b/modules/profiles/default.nix
index 8824dfd..ae03bcc 100644
--- a/modules/profiles/default.nix
+++ b/modules/profiles/default.nix
@@ -54,6 +54,7 @@ in
       dnsutils
       file
       inetutils
+      iotop
       ldns
       lshw
       lsof
diff --git a/modules/profiles/dev/default.nix b/modules/profiles/dev/default.nix
index 61de848..b0755d2 100644
--- a/modules/profiles/dev/default.nix
+++ b/modules/profiles/dev/default.nix
@@ -22,6 +22,7 @@ in
       git.client.enable = true;
       nmap.enable = true;
       wget.enable = true;
+      podman.enable = true;
     };
 
     hm = {
@@ -58,6 +59,7 @@ in
 
         packages = with pkgs; [
           age
+          distrobox
           google-cloud-sdk
           htmlq
           httpie
diff --git a/modules/profiles/headful.nix b/modules/profiles/headful.nix
index 256ec25..3a795f1 100644
--- a/modules/profiles/headful.nix
+++ b/modules/profiles/headful.nix
@@ -130,8 +130,10 @@ in
     time.timeZone = "Europe/Moscow";
 
     environment.systemPackages = with pkgs; [
+      brightnessctl
       lm_sensors
       usbutils
+      wirelesstools
     ];
 
     my.extraGroups = [
diff --git a/modules/profiles/headless.nix b/modules/profiles/headless.nix
index 5d42df0..bf0d23a 100644
--- a/modules/profiles/headless.nix
+++ b/modules/profiles/headless.nix
@@ -5,16 +5,15 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.profiles.headless;
 in
 {
-  options.nixfiles.modules.profiles.headless.enable = mkEnableOption "headless profile" // {
+  options.nixfiles.modules.profiles.headless.enable = lib.mkEnableOption "headless profile" // {
     default = this.isHeadless;
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     nixfiles.modules = {
       openssh.server.enable = true;
       endlessh-go.enable = true;
diff --git a/modules/searx.nix b/modules/searx.nix
index de51a20..ab186af 100644
--- a/modules/searx.nix
+++ b/modules/searx.nix
@@ -5,28 +5,27 @@
   libNginx,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.searx;
 in
 {
   options.nixfiles.modules.searx = {
-    enable = mkEnableOption "SearX";
+    enable = lib.mkEnableOption "SearX";
 
-    port = mkOption {
+    port = lib.mkOption {
       description = "Port.";
-      type = with types; port;
+      type = with lib.types; port;
       default = 61001;
     };
 
-    domain = mkOption {
+    domain = lib.mkOption {
       description = "Domain name sans protocol scheme.";
-      type = with types; nullOr str;
+      type = with lib.types; nullOr str;
       default = "searx.${config.networking.domain}";
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     secrets.searx-environment = {
       file = "${inputs.self}/secrets/searx-environment";
       owner = "searx";
diff --git a/modules/vaultwarden.nix b/modules/vaultwarden.nix
index edce8e5..124ff78 100644
--- a/modules/vaultwarden.nix
+++ b/modules/vaultwarden.nix
@@ -5,17 +5,16 @@
   this,
   ...
 }:
-with lib;
 let
   cfg = config.nixfiles.modules.vaultwarden;
 in
 {
   options.nixfiles.modules.vaultwarden = {
-    enable = mkEnableOption "Vaultwarden";
+    enable = lib.mkEnableOption "Vaultwarden";
 
-    domain = mkOption {
+    domain = lib.mkOption {
       description = "Domain name sans protocol scheme.";
-      type = with types; str;
+      type = lib.types.str;
       default = "vaultwarden.${config.networking.domain}";
     };
   };
@@ -24,7 +23,7 @@ in
     let
       db = "vaultwarden";
     in
-    mkIf cfg.enable {
+    lib.mkIf cfg.enable {
       ark.directories = [ "/var/lib/bitwarden_rs" ];
 
       secrets.vaultwarden-environment = {
@@ -73,7 +72,7 @@ in
 
             WEB_VAULT_ENABLED = true;
 
-            DOMAIN = optionalString (cfg.domain != null) "http://${cfg.domain}";
+            DOMAIN = lib.optionalString (cfg.domain != null) "http://${cfg.domain}";
 
             SIGNUPS_ALLOWED = false;
             INVITATIONS_ALLOWED = false;
@@ -127,14 +126,14 @@ in
       };
 
       environment.etc = {
-        "fail2ban/filter.d/vaultwarden.conf".text = generators.toINI { } {
+        "fail2ban/filter.d/vaultwarden.conf".text = lib.generators.toINI { } {
           Definition = {
             failregex = "^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$";
             ignoreregex = "";
             journalmatch = "_SYSTEMD_UNIT=vaultwarden.service";
           };
         };
-        "fail2ban/filter.d/vaultwarden-admin.conf".text = generators.toINI { } {
+        "fail2ban/filter.d/vaultwarden-admin.conf".text = lib.generators.toINI { } {
           Definition = {
             failregex = "^.*Invalid admin token\. IP: <ADDR>.*$";
             ignoreregex = "";
@@ -143,9 +142,9 @@ in
         };
       };
 
-      topology = with cfg; {
+      topology = {
         nodes.${this.hostname}.services.vaultwarden = {
-          info = mkForce domain;
+          info = lib.mkForce cfg.domain;
         };
       };
     };
diff --git a/modules/wayland.nix b/modules/wayland.nix
index 7a9820d..1ad4fe3 100644
--- a/modules/wayland.nix
+++ b/modules/wayland.nix
@@ -15,9 +15,19 @@ in
     nixfiles.modules.foot.enable = true;
 
     hm.home = {
-      packages = with pkgs; [ wl-clipboard ];
+      packages = with pkgs; [
+        grim
+        slurp
+        wl-clipboard
+        wlr-randr
+      ];
 
-      sessionVariables.NIXOS_OZONE_WL = 1;
+      sessionVariables = {
+        NIXOS_OZONE_WL = 1;
+        QT_QPA_PLATFORM = "wayland";
+        SDL_VIDEODRIVER = "wayland";
+        XDG_SESSION_TYPE = "wayland";
+      };
     };
   };
 }

Consider giving Nix/NixOS a try! <3