about summary refs log tree commit diff
path: root/modules/nixos
diff options
context:
space:
mode:
authorAzat Bahawi <azat@bahawi.net>2022-12-17 16:39:09 +0300
committerAzat Bahawi <azat@bahawi.net>2022-12-17 16:39:09 +0300
commit8f137c28230623259a964484adcf31fe00756594 (patch)
tree82bce6a13fda125087cf6d9dc80aa91d9230d6c4 /modules/nixos
parent2022-11-20 (diff)
2022-12-17
Diffstat (limited to '')
-rw-r--r--modules/nixos/acme.nix (renamed from modules/nixfiles/acme.nix)0
-rw-r--r--modules/nixos/alertmanager.nix (renamed from modules/nixfiles/alertmanager.nix)0
-rw-r--r--modules/nixos/android.nix (renamed from modules/nixfiles/android.nix)0
-rw-r--r--modules/nixos/bluetooth.nix (renamed from modules/nixfiles/bluetooth.nix)0
-rw-r--r--modules/nixos/common/console.nix (renamed from modules/nixfiles/common/console.nix)0
-rw-r--r--modules/nixos/common/default.nix19
-rw-r--r--modules/nixos/common/documentation.nix31
-rw-r--r--modules/nixos/common/home-manager.nix3
-rw-r--r--modules/nixos/common/kernel.nix (renamed from modules/nixfiles/common/kernel.nix)8
-rw-r--r--modules/nixos/common/locale.nix24
-rw-r--r--modules/nixos/common/networking.nix108
-rw-r--r--modules/nixos/common/nix.nix39
-rw-r--r--modules/nixos/common/secrets.nix (renamed from modules/nixfiles/common/secrets.nix)2
-rw-r--r--modules/nixos/common/security.nix (renamed from modules/nixfiles/common/security.nix)0
-rw-r--r--modules/nixos/common/services.nix10
-rw-r--r--modules/nixos/common/shell.nix3
-rw-r--r--modules/nixos/common/systemd.nix (renamed from modules/nixfiles/common/systemd.nix)0
-rw-r--r--modules/nixos/common/tmp.nix (renamed from modules/nixfiles/common/tmp.nix)0
-rw-r--r--modules/nixos/common/users.nix19
-rw-r--r--modules/nixos/common/xdg.nix (renamed from modules/nixfiles/common/xdg.nix)0
-rw-r--r--modules/nixos/default.nix59
-rw-r--r--modules/nixos/discord.nix22
-rw-r--r--modules/nixos/docker.nix (renamed from modules/nixfiles/docker.nix)0
-rw-r--r--modules/nixos/dwm.nix (renamed from modules/nixfiles/dwm.nix)0
-rw-r--r--modules/nixos/emacs.nix30
-rw-r--r--modules/nixos/endlessh-go.nix (renamed from modules/nixfiles/endlessh-go.nix)2
-rw-r--r--modules/nixos/endlessh.nix24
-rw-r--r--modules/nixos/fail2ban.nix (renamed from modules/nixfiles/fail2ban.nix)0
-rw-r--r--modules/nixos/fonts.nix45
-rw-r--r--modules/nixos/games/default.nix (renamed from modules/nixfiles/games/default.nix)0
-rw-r--r--modules/nixos/games/gamemode.nix (renamed from modules/nixfiles/games/gamemode.nix)0
-rw-r--r--modules/nixos/games/gog.nix (renamed from modules/nixfiles/games/gog.nix)0
-rw-r--r--modules/nixos/games/lutris.nix (renamed from modules/nixfiles/games/lutris.nix)7
-rw-r--r--modules/nixos/games/mangohud.nix (renamed from modules/nixfiles/games/mangohud.nix)6
-rw-r--r--modules/nixos/games/minecraft.nix (renamed from modules/nixfiles/games/minecraft.nix)4
-rw-r--r--modules/nixos/games/steam-run.nix (renamed from modules/nixfiles/games/steam-run.nix)26
-rw-r--r--modules/nixos/games/steam.nix (renamed from modules/nixfiles/games/steam.nix)17
-rw-r--r--modules/nixos/git.nix117
-rw-r--r--modules/nixos/gnupg.nix38
-rw-r--r--modules/nixos/gotify.nix (renamed from modules/nixfiles/gotify.nix)0
-rw-r--r--modules/nixos/grafana.nix (renamed from modules/nixfiles/grafana.nix)0
-rw-r--r--modules/nixos/hydra.nix (renamed from modules/nixfiles/hydra.nix)0
-rw-r--r--modules/nixos/ipfs.nix (renamed from modules/nixfiles/ipfs.nix)0
-rw-r--r--modules/nixos/kde.nix (renamed from modules/nixfiles/kde.nix)0
-rw-r--r--modules/nixos/libvirtd.nix (renamed from modules/nixfiles/libvirtd.nix)0
-rw-r--r--modules/nixos/lidarr.nix (renamed from modules/nixfiles/lidarr.nix)0
-rw-r--r--modules/nixos/loki.nix (renamed from modules/nixfiles/loki.nix)0
-rw-r--r--modules/nixos/lxc.nix (renamed from modules/nixfiles/lxc.nix)0
-rw-r--r--modules/nixos/matrix/default.nix (renamed from modules/nixfiles/matrix/default.nix)0
-rw-r--r--modules/nixos/matrix/dendrite.nix (renamed from modules/nixfiles/matrix/dendrite.nix)0
-rw-r--r--modules/nixos/matrix/element.nix (renamed from modules/nixfiles/matrix/element.nix)0
-rw-r--r--modules/nixos/matrix/synapse.nix (renamed from modules/nixfiles/matrix/synapse.nix)0
-rw-r--r--modules/nixos/monitoring/dashboards/endlessh.json (renamed from modules/nixfiles/monitoring/dashboards/endlessh.json)0
-rw-r--r--modules/nixos/monitoring/dashboards/nginx.json (renamed from modules/nixfiles/monitoring/dashboards/nginx.json)0
-rw-r--r--modules/nixos/monitoring/dashboards/postgresql.json (renamed from modules/nixfiles/monitoring/dashboards/postgresql.json)0
-rw-r--r--modules/nixos/monitoring/dashboards/unbound.json (renamed from modules/nixfiles/monitoring/dashboards/unbound.json)0
-rw-r--r--modules/nixos/monitoring/default.nix (renamed from modules/nixfiles/monitoring/default.nix)0
-rw-r--r--modules/nixos/nextcloud.nix (renamed from modules/nixfiles/nextcloud.nix)0
-rw-r--r--modules/nixos/nginx.nix (renamed from modules/nixfiles/nginx.nix)0
-rw-r--r--modules/nixos/node-exporter.nix (renamed from modules/nixfiles/node-exporter.nix)0
-rw-r--r--modules/nixos/nsd.nix (renamed from modules/nixfiles/nsd.nix)2
-rw-r--r--modules/nixos/openssh.nix34
-rw-r--r--modules/nixos/podman.nix (renamed from modules/nixfiles/podman.nix)0
-rw-r--r--modules/nixos/postgresql.nix (renamed from modules/nixfiles/postgresql.nix)0
-rw-r--r--modules/nixos/profiles/default.nix33
-rw-r--r--modules/nixos/profiles/dev/containers.nix27
-rw-r--r--modules/nixos/profiles/dev/default.nix19
-rw-r--r--modules/nixos/profiles/headful.nix88
-rw-r--r--modules/nixos/profiles/headless.nix42
-rw-r--r--modules/nixos/prometheus.nix (renamed from modules/nixfiles/prometheus.nix)0
-rw-r--r--modules/nixos/promtail.nix (renamed from modules/nixfiles/promtail.nix)0
-rw-r--r--modules/nixos/psd.nix (renamed from modules/nixfiles/psd.nix)0
-rw-r--r--modules/nixos/radarr.nix (renamed from modules/nixfiles/radarr.nix)0
-rw-r--r--modules/nixos/radicale.nix (renamed from modules/nixfiles/radicale.nix)0
-rw-r--r--modules/nixos/rss-bridge.nix (renamed from modules/nixfiles/rss-bridge.nix)0
-rw-r--r--modules/nixos/rtorrent.nix (renamed from modules/nixfiles/rtorrent.nix)0
-rw-r--r--modules/nixos/searx.nix (renamed from modules/nixfiles/searx.nix)0
-rw-r--r--modules/nixos/shadowsocks.nix (renamed from modules/nixfiles/shadowsocks.nix)0
-rw-r--r--modules/nixos/soju.nix (renamed from modules/nixfiles/soju.nix)0
-rw-r--r--modules/nixos/solaar.nix (renamed from modules/nixfiles/solaar.nix)0
-rw-r--r--modules/nixos/sonarr.nix (renamed from modules/nixfiles/sonarr.nix)0
-rw-r--r--modules/nixos/sound.nix (renamed from modules/nixfiles/sound.nix)0
-rw-r--r--modules/nixos/syncthing.nix (renamed from modules/nixfiles/syncthing.nix)0
-rw-r--r--modules/nixos/throttled.nix (renamed from modules/nixfiles/throttled.nix)0
-rw-r--r--modules/nixos/unbound.nix (renamed from modules/nixfiles/unbound.nix)0
-rw-r--r--modules/nixos/vaultwarden.nix (renamed from modules/nixfiles/vaultwarden.nix)0
-rw-r--r--modules/nixos/wireguard.nix (renamed from modules/nixfiles/wireguard.nix)0
-rw-r--r--modules/nixos/x11.nix (renamed from modules/nixfiles/x11.nix)0
-rw-r--r--modules/nixos/xmonad.nix (renamed from modules/nixfiles/xmonad.nix)2
89 files changed, 868 insertions, 42 deletions
diff --git a/modules/nixfiles/acme.nix b/modules/nixos/acme.nix
index d3ad661..d3ad661 100644
--- a/modules/nixfiles/acme.nix
+++ b/modules/nixos/acme.nix
diff --git a/modules/nixfiles/alertmanager.nix b/modules/nixos/alertmanager.nix
index 871b0c4..871b0c4 100644
--- a/modules/nixfiles/alertmanager.nix
+++ b/modules/nixos/alertmanager.nix
diff --git a/modules/nixfiles/android.nix b/modules/nixos/android.nix
index 307490a..307490a 100644
--- a/modules/nixfiles/android.nix
+++ b/modules/nixos/android.nix
diff --git a/modules/nixfiles/bluetooth.nix b/modules/nixos/bluetooth.nix
index 8347361..8347361 100644
--- a/modules/nixfiles/bluetooth.nix
+++ b/modules/nixos/bluetooth.nix
diff --git a/modules/nixfiles/common/console.nix b/modules/nixos/common/console.nix
index 3c73695..3c73695 100644
--- a/modules/nixfiles/common/console.nix
+++ b/modules/nixos/common/console.nix
diff --git a/modules/nixos/common/default.nix b/modules/nixos/common/default.nix
new file mode 100644
index 0000000..8724c8b
--- /dev/null
+++ b/modules/nixos/common/default.nix
@@ -0,0 +1,19 @@
+_: {
+  imports = [
+    ./console.nix
+    ./documentation.nix
+    ./home-manager.nix
+    ./kernel.nix
+    ./locale.nix
+    ./networking.nix
+    ./nix.nix
+    ./secrets.nix
+    ./security.nix
+    ./services.nix
+    ./shell.nix
+    ./systemd.nix
+    ./tmp.nix
+    ./users.nix
+    ./xdg.nix
+  ];
+}
diff --git a/modules/nixos/common/documentation.nix b/modules/nixos/common/documentation.nix
new file mode 100644
index 0000000..f909108
--- /dev/null
+++ b/modules/nixos/common/documentation.nix
@@ -0,0 +1,31 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; {
+  config = mkIf this.isHeadful {
+    documentation = {
+      dev.enable = true;
+      nixos.enable = true;
+
+      man.man-db.manualPages =
+        (pkgs.buildEnv {
+          name = "man-paths";
+          paths = with config;
+            environment.systemPackages ++ hm.home.packages;
+          pathsToLink = ["/share/man"];
+          extraOutputsToInstall = ["man"];
+          ignoreCollisions = true;
+        })
+        .overrideAttrs (_: _: {__contentAddressed = true;});
+    };
+
+    environment.sessionVariables = {
+      MANOPT = "--no-hyphenation";
+      MANPAGER = "${pkgs.less}/bin/less -+F";
+    };
+  };
+}
diff --git a/modules/nixos/common/home-manager.nix b/modules/nixos/common/home-manager.nix
new file mode 100644
index 0000000..52f2fd3
--- /dev/null
+++ b/modules/nixos/common/home-manager.nix
@@ -0,0 +1,3 @@
+{inputs, ...}: {
+  imports = [inputs.home-manager.nixosModule];
+}
diff --git a/modules/nixfiles/common/kernel.nix b/modules/nixos/common/kernel.nix
index 2fdfeeb..2fc40f9 100644
--- a/modules/nixfiles/common/kernel.nix
+++ b/modules/nixos/common/kernel.nix
@@ -1,7 +1,10 @@
 {lib, ...}:
 with lib; {
   boot = {
-    # I don't use it even on laptops.
+    # I don't use it even on laptops. It's also /required/ to disable it for
+    # ZFS[1].
+    # [1]: https://github.com/openzfs/zfs/issues/260
+    # [1]: https://github.com/openzfs/zfs/issues/12842
     kernelParams = ["hibernate=no"];
 
     kernel.sysctl = {
@@ -30,4 +33,7 @@ with lib; {
       "vm.vfs_cache_pressure" = 50;
     };
   };
+
+  # https://docs.kernel.org/admin-guide/mm/ksm.html
+  hardware.ksm.enable = true;
 }
diff --git a/modules/nixos/common/locale.nix b/modules/nixos/common/locale.nix
new file mode 100644
index 0000000..62d19f4
--- /dev/null
+++ b/modules/nixos/common/locale.nix
@@ -0,0 +1,24 @@
+{lib, ...}:
+with lib; {
+  i18n = {
+    defaultLocale = mkDefault "en_GB.UTF-8";
+    supportedLocales = [
+      "C.UTF-8/UTF-8"
+      "en_GB.UTF-8/UTF-8"
+      "en_US.UTF-8/UTF-8"
+      "ja_JP.UTF-8/UTF-8"
+      "ru_RU.UTF-8/UTF-8"
+    ];
+  };
+
+  services.xserver = {
+    layout = comcat ["us" "ru"];
+    xkbVariant = comcat ["" "phonetic"];
+    xkbOptions = comcat [
+      "terminate:ctrl_alt_bksp"
+      "caps:escape"
+      "compose:menu"
+      "grp:win_space_toggle"
+    ];
+  };
+}
diff --git a/modules/nixos/common/networking.nix b/modules/nixos/common/networking.nix
new file mode 100644
index 0000000..6109933
--- /dev/null
+++ b/modules/nixos/common/networking.nix
@@ -0,0 +1,108 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; {
+  # TODO Support multiple interfaces and IP addresses.
+  networking = mkMerge [
+    {
+      domain = my.domain.shire;
+
+      hostName = this.hostname;
+      hostId = substring 0 8 (builtins.hashString "md5" this.hostname);
+
+      # Remove default hostname mappings. This is required at least by the current
+      # implementation of the montoring module.
+      hosts = {
+        "127.0.0.2" = mkForce [];
+        "::1" = mkForce [];
+      };
+
+      nameservers = mkDefault dns.const.quad9.default;
+
+      useDHCP = false;
+
+      firewall = {
+        enable = true;
+
+        rejectPackets = false;
+
+        allowPing = true;
+        pingLimit = "--limit 1/minute --limit-burst 5";
+
+        logRefusedConnections = false;
+        logRefusedPackets = false;
+        logRefusedUnicastsOnly = false;
+        logReversePathDrops = false;
+      };
+    }
+    (let
+      interface = "eth0"; # This assumes `usePredictableInterfaceNames` is false.
+    in
+      mkIf (hasAttr "ipv4" this && 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;
+            };
+
+          ipv6.addresses = with this.ipv6;
+            optional (isString address && isInt prefixLength) {
+              inherit address prefixLength;
+            };
+        };
+        defaultGateway = with this.ipv4;
+          mkIf (isString gatewayAddress) {
+            inherit interface;
+            address = gatewayAddress;
+          };
+        defaultGateway6 = with this.ipv6;
+          mkIf (isString gatewayAddress) {
+            inherit interface;
+            address = gatewayAddress;
+          };
+      })
+    (mkIf this.isHeadful {
+      interfaces = {
+        eth0.useDHCP = mkDefault true;
+        wlan0.useDHCP = mkDefault true;
+      };
+
+      networkmanager = {
+        enable = mkDefault true;
+        wifi.backend = "iwd";
+      };
+
+      wireless = {
+        enable = false;
+        iwd.enable = mkDefault true;
+        userControlled.enable = true;
+        allowAuxiliaryImperativeNetworks = true;
+      };
+    })
+  ];
+
+  environment.shellAliases = listToAttrs (map
+    ({
+      name,
+      value,
+    }:
+      nameValuePair name "${pkgs.iproute2}/bin/${value}") [
+      {
+        name = "bridge";
+        value = "bridge -color=always";
+      }
+      {
+        name = "ip";
+        value = "ip -color=always";
+      }
+      {
+        name = "tc";
+        value = "tc -color=always";
+      }
+    ]);
+}
diff --git a/modules/nixos/common/nix.nix b/modules/nixos/common/nix.nix
new file mode 100644
index 0000000..07136a0
--- /dev/null
+++ b/modules/nixos/common/nix.nix
@@ -0,0 +1,39 @@
+{
+  config,
+  inputs,
+  lib,
+  this,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.common.nix;
+in {
+  options.nixfiles.modules.common.nix.allowedUnfreePackages = mkOption {
+    description = "A list of allowed unfree packages.";
+    type = with types; listOf str;
+    default = [];
+  };
+
+  config = {
+    nix.settings.trusted-users = ["@wheel"];
+
+    nixpkgs = {
+      config.allowUnfreePredicate = p: elem (getName p) cfg.allowedUnfreePackages;
+
+      overlays = with inputs; [
+        agenix.overlay
+        # nix-minecraft-servers.overlays.default
+        xmonad-ng.overlays.default
+      ];
+    };
+
+    system.stateVersion = with builtins;
+      head (split "\n" (readFile "${inputs.nixpkgs}/.version"));
+
+    environment = {
+      sessionVariables.NIX_SHELL_PRESERVE_PROMPT = "1";
+      localBinInPath = true;
+      defaultPackages = [];
+    };
+  };
+}
diff --git a/modules/nixfiles/common/secrets.nix b/modules/nixos/common/secrets.nix
index 9e59716..4fcdc61 100644
--- a/modules/nixfiles/common/secrets.nix
+++ b/modules/nixos/common/secrets.nix
@@ -41,7 +41,5 @@ with lib; {
     };
 
     environment.systemPackages = with pkgs; [agenix];
-
-    system.extraDependencies = [inputs.agenix];
   };
 }
diff --git a/modules/nixfiles/common/security.nix b/modules/nixos/common/security.nix
index 09c5da1..09c5da1 100644
--- a/modules/nixfiles/common/security.nix
+++ b/modules/nixos/common/security.nix
diff --git a/modules/nixos/common/services.nix b/modules/nixos/common/services.nix
new file mode 100644
index 0000000..725502a
--- /dev/null
+++ b/modules/nixos/common/services.nix
@@ -0,0 +1,10 @@
+_: {
+  services = {
+    # https://github.com/Irqbalance/irqbalance/issues/54#issuecomment-319245584
+    # https://unix.stackexchange.com/questions/710603/should-the-irqbalance-daemon-be-used-on-a-modern-desktop-x86-system
+    irqbalance.enable = true;
+
+    # https://github.com/NixOS/nixpkgs/issues/135888
+    nscd.enableNsncd = true;
+  };
+}
diff --git a/modules/nixos/common/shell.nix b/modules/nixos/common/shell.nix
new file mode 100644
index 0000000..5fbc441
--- /dev/null
+++ b/modules/nixos/common/shell.nix
@@ -0,0 +1,3 @@
+_: {
+  programs.command-not-found.enable = false;
+}
diff --git a/modules/nixfiles/common/systemd.nix b/modules/nixos/common/systemd.nix
index 5c7282d..5c7282d 100644
--- a/modules/nixfiles/common/systemd.nix
+++ b/modules/nixos/common/systemd.nix
diff --git a/modules/nixfiles/common/tmp.nix b/modules/nixos/common/tmp.nix
index d56e2b6..d56e2b6 100644
--- a/modules/nixfiles/common/tmp.nix
+++ b/modules/nixos/common/tmp.nix
diff --git a/modules/nixos/common/users.nix b/modules/nixos/common/users.nix
new file mode 100644
index 0000000..22e8023
--- /dev/null
+++ b/modules/nixos/common/users.nix
@@ -0,0 +1,19 @@
+{lib, ...}:
+with lib; {
+  users = {
+    mutableUsers = false;
+
+    users = {
+      root.hashedPassword = "@HASHED_PASSWORD@";
+
+      ${my.username} = {
+        isNormalUser = true;
+        uid = 1000;
+        description = my.fullname;
+        inherit (my) hashedPassword;
+        openssh.authorizedKeys.keys = [my.ssh.key];
+        extraGroups = ["wheel"];
+      };
+    };
+  };
+}
diff --git a/modules/nixfiles/common/xdg.nix b/modules/nixos/common/xdg.nix
index 8ddf1ac..8ddf1ac 100644
--- a/modules/nixfiles/common/xdg.nix
+++ b/modules/nixos/common/xdg.nix
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
new file mode 100644
index 0000000..b35e461
--- /dev/null
+++ b/modules/nixos/default.nix
@@ -0,0 +1,59 @@
+_: {
+  imports = [
+    ./acme.nix
+    ./alertmanager.nix
+    ./android.nix
+    ./bluetooth.nix
+    ./common
+    ./discord.nix
+    ./docker.nix
+    ./dwm.nix
+    ./emacs.nix
+    ./endlessh-go.nix
+    ./endlessh.nix
+    ./fail2ban.nix
+    ./fonts.nix
+    ./games
+    ./git.nix
+    ./gnupg.nix
+    ./gotify.nix
+    ./grafana.nix
+    ./hydra.nix
+    ./ipfs.nix
+    ./kde.nix
+    ./libvirtd.nix
+    ./lidarr.nix
+    ./loki.nix
+    ./lxc.nix
+    ./matrix
+    ./monitoring
+    ./nextcloud.nix
+    ./nginx.nix
+    ./node-exporter.nix
+    ./nsd.nix
+    ./openssh.nix
+    ./podman.nix
+    ./postgresql.nix
+    ./profiles
+    ./prometheus.nix
+    ./promtail.nix
+    ./psd.nix
+    ./radarr.nix
+    ./radicale.nix
+    ./rss-bridge.nix
+    ./rtorrent.nix
+    ./searx.nix
+    ./shadowsocks.nix
+    ./soju.nix
+    ./solaar.nix
+    ./sonarr.nix
+    ./sound.nix
+    ./syncthing.nix
+    ./throttled.nix
+    ./unbound.nix
+    ./vaultwarden.nix
+    ./wireguard.nix
+    ./x11.nix
+    ./xmonad.nix
+  ];
+}
diff --git a/modules/nixos/discord.nix b/modules/nixos/discord.nix
new file mode 100644
index 0000000..190b5fc
--- /dev/null
+++ b/modules/nixos/discord.nix
@@ -0,0 +1,22 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.discord;
+in {
+  options.nixfiles.modules.discord.enable =
+    mkEnableOption "Steam runtime";
+
+  config = mkIf cfg.enable {
+    nixfiles.modules.common.nix.allowedUnfreePackages = ["discord"];
+
+    hm.home.packages = with pkgs; [
+      (discord.override {
+        withOpenASAR = true;
+      })
+    ];
+  };
+}
diff --git a/modules/nixfiles/docker.nix b/modules/nixos/docker.nix
index e642030..e642030 100644
--- a/modules/nixfiles/docker.nix
+++ b/modules/nixos/docker.nix
diff --git a/modules/nixfiles/dwm.nix b/modules/nixos/dwm.nix
index 618d8ed..618d8ed 100644
--- a/modules/nixfiles/dwm.nix
+++ b/modules/nixos/dwm.nix
diff --git a/modules/nixos/emacs.nix b/modules/nixos/emacs.nix
new file mode 100644
index 0000000..800d411
--- /dev/null
+++ b/modules/nixos/emacs.nix
@@ -0,0 +1,30 @@
+{
+  config,
+  inputs,
+  lib,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.emacs;
+in {
+  config = mkIf cfg.enable {
+    secrets.authinfo = {
+      file = "${inputs.self}/secrets/authinfo";
+      owner = my.username;
+      inherit (config.my) group;
+    };
+
+    nixfiles.modules.x11.enable = true;
+
+    hm = {
+      programs.doom-emacs.extraConfig = ''
+        (appendq! auth-sources '("${config.secrets.authinfo.path}"))
+      '';
+
+      services.emacs = {
+        enable = true;
+        client.enable = true;
+      };
+    };
+  };
+}
diff --git a/modules/nixfiles/endlessh-go.nix b/modules/nixos/endlessh-go.nix
index 9ceb4e4..435305d 100644
--- a/modules/nixfiles/endlessh-go.nix
+++ b/modules/nixos/endlessh-go.nix
@@ -1,8 +1,6 @@
 {
   config,
-  inputs,
   lib,
-  pkgs,
   this,
   ...
 }:
diff --git a/modules/nixos/endlessh.nix b/modules/nixos/endlessh.nix
new file mode 100644
index 0000000..67789fd
--- /dev/null
+++ b/modules/nixos/endlessh.nix
@@ -0,0 +1,24 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.endlessh;
+in {
+  options.nixfiles.modules.endlessh.enable = mkEnableOption "endlessh";
+
+  config = let
+    port = 22;
+  in
+    mkIf cfg.enable {
+      services.endlessh = {
+        enable = true;
+        inherit port;
+        extraOptions = ["-v" "-4"];
+      };
+
+      networking.firewall.allowedTCPPorts = [port];
+    };
+}
diff --git a/modules/nixfiles/fail2ban.nix b/modules/nixos/fail2ban.nix
index 5ac3c9c..5ac3c9c 100644
--- a/modules/nixfiles/fail2ban.nix
+++ b/modules/nixos/fail2ban.nix
diff --git a/modules/nixos/fonts.nix b/modules/nixos/fonts.nix
new file mode 100644
index 0000000..d4a7330
--- /dev/null
+++ b/modules/nixos/fonts.nix
@@ -0,0 +1,45 @@
+{
+  config,
+  lib,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.fonts;
+in {
+  config = mkMerge [
+    (mkIf cfg.enable {
+      hm.fonts.fontconfig.enable = true;
+      fonts.fontconfig = {
+        enable = true;
+
+        defaultFonts = {
+          monospace = [
+            "Iosevka"
+            "Sarasa Mono K"
+            "Sarasa Mono J"
+            "Sarasa Mono SC"
+            "Sarasa Mono CL"
+          ];
+          sansSerif = [
+            "Iosevka Aile"
+            "Sarasa Gothic K"
+            "Sarasa Gothic J"
+            "Sarasa Gothic SC"
+            "Sarasa Gothic CL"
+          ];
+          serif = [
+            "Iosevka Etoile"
+            "Sarasa Gothic K"
+            "Sarasa Gothic J"
+            "Sarasa Gothic SC"
+            "Sarasa Gothic CL"
+          ];
+        };
+      };
+    })
+    (mkIf (!cfg.enable) {
+      hm.fonts.fontconfig.enable = false;
+      fonts.fontconfig.enable = false;
+    })
+  ];
+}
diff --git a/modules/nixfiles/games/default.nix b/modules/nixos/games/default.nix
index 1c5766b..1c5766b 100644
--- a/modules/nixfiles/games/default.nix
+++ b/modules/nixos/games/default.nix
diff --git a/modules/nixfiles/games/gamemode.nix b/modules/nixos/games/gamemode.nix
index 051d12e..051d12e 100644
--- a/modules/nixfiles/games/gamemode.nix
+++ b/modules/nixos/games/gamemode.nix
diff --git a/modules/nixfiles/games/gog.nix b/modules/nixos/games/gog.nix
index 86039f1..86039f1 100644
--- a/modules/nixfiles/games/gog.nix
+++ b/modules/nixos/games/gog.nix
diff --git a/modules/nixfiles/games/lutris.nix b/modules/nixos/games/lutris.nix
index e7faef3..72179fc 100644
--- a/modules/nixfiles/games/lutris.nix
+++ b/modules/nixos/games/lutris.nix
@@ -16,20 +16,17 @@ in {
       steam-run.enable = true;
     };
 
-    # This removes the annoying warning.
-    boot.kernel.sysctl."dev.i915.perf_stream_paranoid" = 0;
-
     hm.home.packages = with pkgs; [
       (lutris.override {
         lutris-unwrapped = lutris-unwrapped.override {
           wine = buildFHSUserEnv {
-            # We don't really need Wine because Lutris downloads the required
+            # We don't really need Wine because Lutris downloads a required
             # runtime for us.
             name = "empty";
           };
         };
-        steamSupport = false;
       })
+      vkBasalt
     ];
   };
 }
diff --git a/modules/nixfiles/games/mangohud.nix b/modules/nixos/games/mangohud.nix
index b521687..d693c82 100644
--- a/modules/nixfiles/games/mangohud.nix
+++ b/modules/nixos/games/mangohud.nix
@@ -13,13 +13,13 @@ in {
       enable = true;
       settings = {
         fps = true;
+        frame_timing = true;
         gpu_stats = true;
         gpu_temp = true;
         cpu_stats = true;
         cpu_temp = true;
-      };
-      settingsPerApplication = {
-        mpv.no_display = true;
+        ram = true;
+        vram = true;
       };
     };
   };
diff --git a/modules/nixfiles/games/minecraft.nix b/modules/nixos/games/minecraft.nix
index 47279f8..e53f9eb 100644
--- a/modules/nixfiles/games/minecraft.nix
+++ b/modules/nixos/games/minecraft.nix
@@ -23,8 +23,6 @@ in {
   config = mkMerge [
     (mkIf cfg.client.enable {
       hm.home.packages = with pkgs; [pollymc];
-
-      system.extraDependencies = [inputs.pollymc];
     })
     (mkIf cfg.server.enable {
       # Configurations, opslist, whitelist and plugins are managed imperatively.
@@ -47,8 +45,6 @@ in {
 
       # Defined in /var/lib/minecraft/server.properties.
       networking.firewall.allowedTCPPorts = [55565];
-
-      system.extraDependencies = [inputs.nix-minecraft-servers];
     })
   ];
 }
diff --git a/modules/nixfiles/games/steam-run.nix b/modules/nixos/games/steam-run.nix
index 4731fd6..1a1e61f 100644
--- a/modules/nixfiles/games/steam-run.nix
+++ b/modules/nixos/games/steam-run.nix
@@ -11,12 +11,15 @@ in {
     enable = mkEnableOption "native Steam runtime";
 
     quirks = {
-      mountandblade = mkEnableOption ''fixes for "Mount & Blade: Warband" issues'';
+      mountAndBladeWarband = mkEnableOption ''fixes for "Mount & Blade: Warband" issues'';
+      cryptOfTheNecrodancer = mkEnableOption ''fixes for "Crypt of the NecroDancer" issues'';
     };
   };
 
   config = mkIf cfg.enable {
     nixfiles.modules = {
+      common.nix.allowedUnfreePackages = ["steam" "steam-run"];
+
       games = {
         enable32BitSupport = true;
         gamemode.enable = true;
@@ -27,11 +30,12 @@ in {
       (steam.override {
         extraLibraries = _:
           with cfg.quirks;
-            optionals mountandblade [
+            []
+            ++ optionals mountAndBladeWarband [
               (glew.overrideAttrs (_: super: let
                 opname = super.pname;
               in rec {
-                pname = "${opname}-mbw";
+                pname = "${opname}-runfix";
                 inherit (super) version;
                 src = fetchurl {
                   url = "mirror://sourceforge/${opname}/${opname}-${version}.tgz";
@@ -41,7 +45,7 @@ in {
               (fmodex.overrideAttrs (_: super: let
                 opname = super.pname;
               in rec {
-                pname = "${opname}-mbw";
+                pname = "${opname}-runfix";
                 inherit (super) version;
                 installPhase = let
                   libPath = makeLibraryPath [
@@ -54,16 +58,16 @@ in {
                   patchelf --set-rpath ${libPath} $out/lib/libfmodex64.so
                 '';
               }))
+            ]
+            ++ optionals cryptOfTheNecrodancer [
+              (import (builtins.fetchTarball {
+                url = "https://github.com/NixOS/nixpkgs/archive/d1c3fea7ecbed758168787fe4e4a3157e52bc808.tar.gz";
+                sha256 = "0ykm15a690v8lcqf2j899za3j6hak1rm3xixdxsx33nz7n3swsyy";
+              }) {inherit (config.nixpkgs) config localSystem;})
+              .flac
             ];
       })
       .run
     ];
-
-    nixpkgs.config.allowUnfreePredicate = p:
-      elem (getName p) [
-        "steam"
-        "steam-original"
-        "steam-run"
-      ];
   };
 }
diff --git a/modules/nixfiles/games/steam.nix b/modules/nixos/games/steam.nix
index bbd01f6..8dfa72c 100644
--- a/modules/nixfiles/games/steam.nix
+++ b/modules/nixos/games/steam.nix
@@ -11,18 +11,15 @@ in {
     mkEnableOption "Steam runtime";
 
   config = mkIf cfg.enable {
-    nixfiles.modules.games = {
-      enable32BitSupport = true;
-      gamemode.enable = true;
+    nixfiles.modules = {
+      common.nix.allowedUnfreePackages = ["steam" "steam-original"];
+
+      games = {
+        enable32BitSupport = true;
+        gamemode.enable = true;
+      };
     };
 
     hm.home.packages = with pkgs; [steam];
-
-    nixpkgs.config.allowUnfreePredicate = p:
-      elem (getName p) [
-        "steam"
-        "steam-original"
-        "steam-run"
-      ];
   };
 }
diff --git a/modules/nixos/git.nix b/modules/nixos/git.nix
new file mode 100644
index 0000000..f754588
--- /dev/null
+++ b/modules/nixos/git.nix
@@ -0,0 +1,117 @@
+{
+  config,
+  lib,
+  inputs,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.git;
+in {
+  options.nixfiles.modules.git.server = {
+    enable = mkEnableOption "Git server";
+
+    domain = mkOption {
+      description = "Domain name sans protocol scheme.";
+      type = with types; nullOr str;
+      default = "git.${config.networking.domain}";
+    };
+
+    package = mkOption {
+      description = "Package.";
+      type = types.package;
+      default = pkgs.cgit-pink;
+    };
+  };
+
+  config = mkMerge [
+    (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;
+          inherit (config.my) group;
+        };
+        gh-hosts = {
+          file = "${inputs.self}/secrets/gh-hosts";
+          path = "${config.dirs.config}/gh/hosts.yml";
+          owner = my.username;
+          inherit (config.my) group;
+        };
+        hut = {
+          file = "${inputs.self}/secrets/hut";
+          path = "${config.dirs.config}/hut/config";
+          owner = my.username;
+          inherit (config.my) group;
+        };
+      };
+    })
+    (mkIf cfg.server.enable {
+      nixfiles.modules.nginx = {
+        enable = true;
+        virtualHosts.${cfg.server.domain} = {
+          locations = {
+            "/".extraConfig = let
+              cgitrc = pkgs.writeText "cgitrc" ''
+                root-title=azahi’s git stuff
+                root-desc=鯛も一人はうまからず
+
+                about-filter=${cfg.server.package}/lib/cgit/filters/about-formatting.sh
+                source-filter=${cfg.server.package}/lib/cgit/filters/syntax-highlighting.py
+                commit-filter=${cfg.server.package}/lib/cgit/filters/commit-links.sh
+
+                enable-git-config=1
+                enable-gitweb-owner=1
+                remove-suffix=1
+
+                snapshots=tar.gz tar.bz2 zip
+
+                readme=:README
+                readme=:README.md
+                readme=:README.org
+                readme=:README.txt
+                readme=:readme
+                readme=:readme.md
+                readme=:readme.org
+                readme=:readme.txt
+
+                scan-path=${config.services.gitolite.dataDir}/repositories
+              '';
+            in ''
+              include ${config.services.nginx.package}/conf/fastcgi_params;
+              fastcgi_split_path_info ^(/?)(.+)$;
+              fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
+              fastcgi_param SCRIPT_FILENAME ${cfg.server.package}/cgit/cgit.cgi;
+              fastcgi_param CGIT_CONFIG ${cgitrc};
+              fastcgi_param PATH_INFO $uri;
+              fastcgi_param QUERY_STRING $args;
+              fastcgi_param HTTP_HOST $server_name;
+            '';
+            # FIXME This breaks sources previewing for these files.
+            "~* ^/(.+.(ico|css|png))$".extraConfig = ''
+              alias ${cfg.server.package}/cgit/$1;
+            '';
+          };
+        };
+      };
+
+      services = let
+        user = "git";
+        group = "git";
+      in {
+        gitolite = {
+          # TODO Make the configuration purely declarative.
+          enable = true;
+          inherit user group;
+          adminPubkey = my.ssh.key;
+        };
+
+        fcgiwrap = {
+          enable = true;
+          inherit user group;
+        };
+      };
+    })
+  ];
+}
diff --git a/modules/nixos/gnupg.nix b/modules/nixos/gnupg.nix
new file mode 100644
index 0000000..b86be9b
--- /dev/null
+++ b/modules/nixos/gnupg.nix
@@ -0,0 +1,38 @@
+{
+  config,
+  lib,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.gnupg;
+in {
+  options.nixfiles.modules.gnupg.pinentry = mkOption {
+    description = "Name of a pinentry implementation.";
+    type = types.str;
+    default = "curses";
+  };
+
+  config = mkIf cfg.enable {
+    hm = {
+      programs.gpg.homedir = "${config.dirs.data}/gnupg";
+
+      services.gpg-agent = {
+        enable = true;
+
+        enableSshSupport = true;
+        enableScDaemon = false;
+
+        defaultCacheTtl = 999999;
+        defaultCacheTtlSsh = 999999;
+        maxCacheTtl = 999999;
+        maxCacheTtlSsh = 999999;
+
+        grabKeyboardAndMouse = true;
+
+        sshKeys = [my.pgp.grip];
+
+        pinentryFlavor = cfg.pinentry;
+      };
+    };
+  };
+}
diff --git a/modules/nixfiles/gotify.nix b/modules/nixos/gotify.nix
index db47bb4..db47bb4 100644
--- a/modules/nixfiles/gotify.nix
+++ b/modules/nixos/gotify.nix
diff --git a/modules/nixfiles/grafana.nix b/modules/nixos/grafana.nix
index a614502..a614502 100644
--- a/modules/nixfiles/grafana.nix
+++ b/modules/nixos/grafana.nix
diff --git a/modules/nixfiles/hydra.nix b/modules/nixos/hydra.nix
index 590fecb..590fecb 100644
--- a/modules/nixfiles/hydra.nix
+++ b/modules/nixos/hydra.nix
diff --git a/modules/nixfiles/ipfs.nix b/modules/nixos/ipfs.nix
index 0ec64e5..0ec64e5 100644
--- a/modules/nixfiles/ipfs.nix
+++ b/modules/nixos/ipfs.nix
diff --git a/modules/nixfiles/kde.nix b/modules/nixos/kde.nix
index a430294..a430294 100644
--- a/modules/nixfiles/kde.nix
+++ b/modules/nixos/kde.nix
diff --git a/modules/nixfiles/libvirtd.nix b/modules/nixos/libvirtd.nix
index ae8b336..ae8b336 100644
--- a/modules/nixfiles/libvirtd.nix
+++ b/modules/nixos/libvirtd.nix
diff --git a/modules/nixfiles/lidarr.nix b/modules/nixos/lidarr.nix
index f73f917..f73f917 100644
--- a/modules/nixfiles/lidarr.nix
+++ b/modules/nixos/lidarr.nix
diff --git a/modules/nixfiles/loki.nix b/modules/nixos/loki.nix
index 1582164..1582164 100644
--- a/modules/nixfiles/loki.nix
+++ b/modules/nixos/loki.nix
diff --git a/modules/nixfiles/lxc.nix b/modules/nixos/lxc.nix
index 4f7805f..4f7805f 100644
--- a/modules/nixfiles/lxc.nix
+++ b/modules/nixos/lxc.nix
diff --git a/modules/nixfiles/matrix/default.nix b/modules/nixos/matrix/default.nix
index bd221c4..bd221c4 100644
--- a/modules/nixfiles/matrix/default.nix
+++ b/modules/nixos/matrix/default.nix
diff --git a/modules/nixfiles/matrix/dendrite.nix b/modules/nixos/matrix/dendrite.nix
index 0fad5f2..0fad5f2 100644
--- a/modules/nixfiles/matrix/dendrite.nix
+++ b/modules/nixos/matrix/dendrite.nix
diff --git a/modules/nixfiles/matrix/element.nix b/modules/nixos/matrix/element.nix
index 3d47800..3d47800 100644
--- a/modules/nixfiles/matrix/element.nix
+++ b/modules/nixos/matrix/element.nix
diff --git a/modules/nixfiles/matrix/synapse.nix b/modules/nixos/matrix/synapse.nix
index 6ff5e0d..6ff5e0d 100644
--- a/modules/nixfiles/matrix/synapse.nix
+++ b/modules/nixos/matrix/synapse.nix
diff --git a/modules/nixfiles/monitoring/dashboards/endlessh.json b/modules/nixos/monitoring/dashboards/endlessh.json
index 0b47ee2..0b47ee2 100644
--- a/modules/nixfiles/monitoring/dashboards/endlessh.json
+++ b/modules/nixos/monitoring/dashboards/endlessh.json
diff --git a/modules/nixfiles/monitoring/dashboards/nginx.json b/modules/nixos/monitoring/dashboards/nginx.json
index b2cc499..b2cc499 100644
--- a/modules/nixfiles/monitoring/dashboards/nginx.json
+++ b/modules/nixos/monitoring/dashboards/nginx.json
diff --git a/modules/nixfiles/monitoring/dashboards/postgresql.json b/modules/nixos/monitoring/dashboards/postgresql.json
index 4e533f7..4e533f7 100644
--- a/modules/nixfiles/monitoring/dashboards/postgresql.json
+++ b/modules/nixos/monitoring/dashboards/postgresql.json
diff --git a/modules/nixfiles/monitoring/dashboards/unbound.json b/modules/nixos/monitoring/dashboards/unbound.json
index 8a0d503..8a0d503 100644
--- a/modules/nixfiles/monitoring/dashboards/unbound.json
+++ b/modules/nixos/monitoring/dashboards/unbound.json
diff --git a/modules/nixfiles/monitoring/default.nix b/modules/nixos/monitoring/default.nix
index 4ff4c50..4ff4c50 100644
--- a/modules/nixfiles/monitoring/default.nix
+++ b/modules/nixos/monitoring/default.nix
diff --git a/modules/nixfiles/nextcloud.nix b/modules/nixos/nextcloud.nix
index 69bea8a..69bea8a 100644
--- a/modules/nixfiles/nextcloud.nix
+++ b/modules/nixos/nextcloud.nix
diff --git a/modules/nixfiles/nginx.nix b/modules/nixos/nginx.nix
index b8ab24d..b8ab24d 100644
--- a/modules/nixfiles/nginx.nix
+++ b/modules/nixos/nginx.nix
diff --git a/modules/nixfiles/node-exporter.nix b/modules/nixos/node-exporter.nix
index 43f48f6..43f48f6 100644
--- a/modules/nixfiles/node-exporter.nix
+++ b/modules/nixos/node-exporter.nix
diff --git a/modules/nixfiles/nsd.nix b/modules/nixos/nsd.nix
index f5a7d84..0dade8f 100644
--- a/modules/nixfiles/nsd.nix
+++ b/modules/nixos/nsd.nix
@@ -170,7 +170,5 @@ in {
       allowedTCPPorts = [53];
       allowedUDPPorts = allowedTCPPorts;
     };
-
-    system.extraDependencies = [inputs.dns-nix];
   };
 }
diff --git a/modules/nixos/openssh.nix b/modules/nixos/openssh.nix
new file mode 100644
index 0000000..00d2852
--- /dev/null
+++ b/modules/nixos/openssh.nix
@@ -0,0 +1,34 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.openssh;
+in {
+  options.nixfiles.modules.openssh.server.enable =
+    mkEnableOption "OpenSSH server";
+
+  config = mkIf cfg.server.enable {
+    programs.mosh.enable = true;
+
+    services = let
+      port = 22022; # Port 22 should be occupied by a tarpit.
+    in {
+      openssh = {
+        enable = true;
+        ports = [port];
+        logLevel = "VERBOSE"; # Required by fail2ban.
+        permitRootLogin = "no";
+        passwordAuthentication = false;
+      };
+
+      fail2ban.jails.sshd = ''
+        enabled = true
+        mode = aggressive
+        port = ${toString port}
+      '';
+    };
+  };
+}
diff --git a/modules/nixfiles/podman.nix b/modules/nixos/podman.nix
index 1c5378b..1c5378b 100644
--- a/modules/nixfiles/podman.nix
+++ b/modules/nixos/podman.nix
diff --git a/modules/nixfiles/postgresql.nix b/modules/nixos/postgresql.nix
index df05e7e..df05e7e 100644
--- a/modules/nixfiles/postgresql.nix
+++ b/modules/nixos/postgresql.nix
diff --git a/modules/nixos/profiles/default.nix b/modules/nixos/profiles/default.nix
new file mode 100644
index 0000000..d5ab838
--- /dev/null
+++ b/modules/nixos/profiles/default.nix
@@ -0,0 +1,33 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.profiles.default;
+in {
+  imports = [
+    ./dev
+    ./headful.nix
+    ./headless.nix
+  ];
+
+  config = mkIf cfg.enable {
+    programs.less = {
+      enable = true;
+      envVariables.LESSHISTFILE = "-";
+    };
+
+    environment.systemPackages = with pkgs; [
+      cryptsetup
+      lshw
+      lsof
+      pciutils
+      psmisc
+      usbutils
+      util-linux
+    ];
+  };
+}
diff --git a/modules/nixos/profiles/dev/containers.nix b/modules/nixos/profiles/dev/containers.nix
new file mode 100644
index 0000000..195b892
--- /dev/null
+++ b/modules/nixos/profiles/dev/containers.nix
@@ -0,0 +1,27 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.profiles.dev.containers;
+in {
+  config = mkIf cfg.enable {
+    nixfiles.modules.podman.enable = true;
+
+    hm = {
+      home = {
+        sessionVariables.MINIKUBE_HOME = "${config.dirs.config}/minikube";
+
+        packages = with pkgs; [buildah];
+      };
+
+      xdg.dataFile."minikube/config/config.json".text = generators.toJSON {} {
+        config.Rootless = true;
+        driver = "podman";
+        container-runtime = "cri-o";
+      };
+    };
+  };
+}
diff --git a/modules/nixos/profiles/dev/default.nix b/modules/nixos/profiles/dev/default.nix
new file mode 100644
index 0000000..83d41c0
--- /dev/null
+++ b/modules/nixos/profiles/dev/default.nix
@@ -0,0 +1,19 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.profiles.dev.default;
+in {
+  config = mkIf cfg.enable {
+    hm.home.language = {
+      collate = "C";
+      messages = "C";
+    };
+
+    my.extraGroups = ["kvm"];
+  };
+}
diff --git a/modules/nixos/profiles/headful.nix b/modules/nixos/profiles/headful.nix
new file mode 100644
index 0000000..01c442e
--- /dev/null
+++ b/modules/nixos/profiles/headful.nix
@@ -0,0 +1,88 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.profiles.headful;
+in {
+  config = mkIf cfg.enable {
+    nixfiles.modules = {
+      chromium.enable = true;
+      firefox.enable = true;
+      sound.enable = true;
+      x11.enable = true;
+
+      dwm.enable = mkDefault false;
+      kde.enable = mkDefault true;
+      xmonad.enable = mkDefault false;
+    };
+
+    hm = {
+      home.packages = with pkgs; [
+        calibre
+        imv
+        neochat
+        tdesktop
+        tor-browser
+      ];
+
+      programs.bash.shellAliases.open = "${pkgs.xdg-utils}/bin/xdg-open";
+    };
+
+    boot = {
+      # Pretty much placebo but has some nice patches for `-march=native`
+      # optimisations, P-State Zen4 support and Fsync for Wine.
+      kernelPackages = mkDefault pkgs.linuxPackages_xanmod_latest;
+
+      # There are (arguably) not a lot of reasons to keep mitigations enabled
+      # for on machine that is not web-facing. First of all, to completely
+      # mitigate any possible Spectre holes one would need to disable
+      # Hyperthreading altogether which will essentially put one's computer into
+      # the stone age by not being able to to effectively utilise multi-core its
+      # multicore capabilities. Secondly, by enabling mitigations, we introduce
+      # a plethora of performace overheads[1], which, albeit small, but still
+      # contribute to the overall speed of things. This is however still poses a
+      # security risk, which I am willing to take.
+      #
+      # [1]: https://www.phoronix.com/scan.php?page=article&item=spectre-meltdown-2&num=11
+      kernelParams = ["mitigations=off"];
+
+      loader = {
+        efi.canTouchEfiVariables = true;
+
+        systemd-boot = {
+          enable = true;
+          configurationLimit = 10;
+        };
+      };
+    };
+
+    hardware.opengl = {
+      enable = true;
+      driSupport = true;
+    };
+
+    programs = {
+      iftop.enable = true;
+      mtr.enable = true;
+      traceroute.enable = true;
+    };
+
+    services = {
+      # https://github.com/NixOS/nixpkgs/issues/135888
+      upower.enable = true;
+
+      psd.enable = true;
+    };
+
+    environment.systemPackages = with pkgs; [
+      ethtool
+      nethogs
+    ];
+
+    my.extraGroups = ["audio" "video" "input"];
+  };
+}
diff --git a/modules/nixos/profiles/headless.nix b/modules/nixos/profiles/headless.nix
new file mode 100644
index 0000000..9faf531
--- /dev/null
+++ b/modules/nixos/profiles/headless.nix
@@ -0,0 +1,42 @@
+{
+  config,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; let
+  cfg = config.nixfiles.modules.profiles.headless;
+in {
+  config = mkIf cfg.enable {
+    nixfiles.modules = {
+      openssh.server.enable = true;
+      endlessh-go.enable = true;
+
+      fail2ban.enable = true;
+
+      node-exporter.enable = true;
+      promtail.enable = true;
+    };
+
+    # Pin version to prevent any surprises.
+    boot.kernelPackages = pkgs.linuxPackages_5_15_hardened;
+
+    nix = {
+      gc = {
+        automatic = true;
+        dates = "weekly";
+        options = "--delete-older-than 30d";
+      };
+
+      optimise = {
+        automatic = true;
+        dates = ["daily"];
+      };
+    };
+
+    services.udisks2.enable = false;
+
+    xdg.sounds.enable = false;
+  };
+}
diff --git a/modules/nixfiles/prometheus.nix b/modules/nixos/prometheus.nix
index a75c151..a75c151 100644
--- a/modules/nixfiles/prometheus.nix
+++ b/modules/nixos/prometheus.nix
diff --git a/modules/nixfiles/promtail.nix b/modules/nixos/promtail.nix
index 552df82..552df82 100644
--- a/modules/nixfiles/promtail.nix
+++ b/modules/nixos/promtail.nix
diff --git a/modules/nixfiles/psd.nix b/modules/nixos/psd.nix
index 77d3c66..77d3c66 100644
--- a/modules/nixfiles/psd.nix
+++ b/modules/nixos/psd.nix
diff --git a/modules/nixfiles/radarr.nix b/modules/nixos/radarr.nix
index 0abfdf2..0abfdf2 100644
--- a/modules/nixfiles/radarr.nix
+++ b/modules/nixos/radarr.nix
diff --git a/modules/nixfiles/radicale.nix b/modules/nixos/radicale.nix
index c903d39..c903d39 100644
--- a/modules/nixfiles/radicale.nix
+++ b/modules/nixos/radicale.nix
diff --git a/modules/nixfiles/rss-bridge.nix b/modules/nixos/rss-bridge.nix
index fef1070..fef1070 100644
--- a/modules/nixfiles/rss-bridge.nix
+++ b/modules/nixos/rss-bridge.nix
diff --git a/modules/nixfiles/rtorrent.nix b/modules/nixos/rtorrent.nix
index 4014a3b..4014a3b 100644
--- a/modules/nixfiles/rtorrent.nix
+++ b/modules/nixos/rtorrent.nix
diff --git a/modules/nixfiles/searx.nix b/modules/nixos/searx.nix
index 9462d5d..9462d5d 100644
--- a/modules/nixfiles/searx.nix
+++ b/modules/nixos/searx.nix
diff --git a/modules/nixfiles/shadowsocks.nix b/modules/nixos/shadowsocks.nix
index b59359c..b59359c 100644
--- a/modules/nixfiles/shadowsocks.nix
+++ b/modules/nixos/shadowsocks.nix
diff --git a/modules/nixfiles/soju.nix b/modules/nixos/soju.nix
index 14faf00..14faf00 100644
--- a/modules/nixfiles/soju.nix
+++ b/modules/nixos/soju.nix
diff --git a/modules/nixfiles/solaar.nix b/modules/nixos/solaar.nix
index ceff23d..ceff23d 100644
--- a/modules/nixfiles/solaar.nix
+++ b/modules/nixos/solaar.nix
diff --git a/modules/nixfiles/sonarr.nix b/modules/nixos/sonarr.nix
index 8c79175..8c79175 100644
--- a/modules/nixfiles/sonarr.nix
+++ b/modules/nixos/sonarr.nix
diff --git a/modules/nixfiles/sound.nix b/modules/nixos/sound.nix
index ae35e44..ae35e44 100644
--- a/modules/nixfiles/sound.nix
+++ b/modules/nixos/sound.nix
diff --git a/modules/nixfiles/syncthing.nix b/modules/nixos/syncthing.nix
index b690ab4..b690ab4 100644
--- a/modules/nixfiles/syncthing.nix
+++ b/modules/nixos/syncthing.nix
diff --git a/modules/nixfiles/throttled.nix b/modules/nixos/throttled.nix
index f182ee1..f182ee1 100644
--- a/modules/nixfiles/throttled.nix
+++ b/modules/nixos/throttled.nix
diff --git a/modules/nixfiles/unbound.nix b/modules/nixos/unbound.nix
index 8c40291..8c40291 100644
--- a/modules/nixfiles/unbound.nix
+++ b/modules/nixos/unbound.nix
diff --git a/modules/nixfiles/vaultwarden.nix b/modules/nixos/vaultwarden.nix
index 7d51667..7d51667 100644
--- a/modules/nixfiles/vaultwarden.nix
+++ b/modules/nixos/vaultwarden.nix
diff --git a/modules/nixfiles/wireguard.nix b/modules/nixos/wireguard.nix
index d05c6ae..d05c6ae 100644
--- a/modules/nixfiles/wireguard.nix
+++ b/modules/nixos/wireguard.nix
diff --git a/modules/nixfiles/x11.nix b/modules/nixos/x11.nix
index cd8dfbe..cd8dfbe 100644
--- a/modules/nixfiles/x11.nix
+++ b/modules/nixos/x11.nix
diff --git a/modules/nixfiles/xmonad.nix b/modules/nixos/xmonad.nix
index 847110e..2cc7ad6 100644
--- a/modules/nixfiles/xmonad.nix
+++ b/modules/nixos/xmonad.nix
@@ -24,7 +24,5 @@ in {
     };
 
     services.xserver.displayManager.startx.enable = true;
-
-    system.extraDependencies = [inputs.xmonad-ng];
   };
 }

Consider giving Nix/NixOS a try! <3