about summary refs log tree commit diff
path: root/modules/nixos/common
diff options
context:
space:
mode:
Diffstat (limited to 'modules/nixos/common')
-rw-r--r--modules/nixos/common/console.nix6
-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.nix39
-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.nix45
-rw-r--r--modules/nixos/common/security.nix29
-rw-r--r--modules/nixos/common/services.nix10
-rw-r--r--modules/nixos/common/shell.nix3
-rw-r--r--modules/nixos/common/systemd.nix22
-rw-r--r--modules/nixos/common/tmp.nix18
-rw-r--r--modules/nixos/common/users.nix19
-rw-r--r--modules/nixos/common/xdg.nix87
16 files changed, 502 insertions, 0 deletions
diff --git a/modules/nixos/common/console.nix b/modules/nixos/common/console.nix
new file mode 100644
index 0000000..3c73695
--- /dev/null
+++ b/modules/nixos/common/console.nix
@@ -0,0 +1,6 @@
+{config, ...}: {
+  console = {
+    earlySetup = true;
+    useXkbConfig = config.services.xserver.enable;
+  };
+}
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/nixos/common/kernel.nix b/modules/nixos/common/kernel.nix
new file mode 100644
index 0000000..2fc40f9
--- /dev/null
+++ b/modules/nixos/common/kernel.nix
@@ -0,0 +1,39 @@
+{lib, ...}:
+with lib; {
+  boot = {
+    # 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 = {
+      "fs.file-max" = pow 2 17;
+      "fs.inotify.max_user_watches" = 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.randomize_va_space" = 2;
+      "kernel.shmall" = pow 2 28;
+      "kernel.shmmax" = pow 2 28;
+      "kernel.sysrq" = 0;
+      "vm.dirty_background_bytes" = pow 2 22;
+      "vm.dirty_background_ratio" = 5;
+      "vm.dirty_bytes" = 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.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/nixos/common/secrets.nix b/modules/nixos/common/secrets.nix
new file mode 100644
index 0000000..4fcdc61
--- /dev/null
+++ b/modules/nixos/common/secrets.nix
@@ -0,0 +1,45 @@
+{
+  config,
+  inputs,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib; {
+  imports = [
+    inputs.agenix.nixosModule
+    (mkAliasOptionModule ["secrets"] ["age" "secrets"])
+  ];
+
+  config = {
+    age = {
+      identityPaths =
+        if this.isHeadful
+        then ["${config.my.home}/.ssh/id_${my.ssh.type}"]
+        else
+          map (attr: attr.path) (filter (attr: attr.type == my.ssh.type)
+            config.services.openssh.hostKeys);
+
+      # This can be used to auto-add all secrets, thus eleminating the need to
+      # specify path to each envrypted file. The drawback is that this will
+      # expose *all* secrets to all machines and try to decrypt them all even on
+      # machines where the secret will not be used.
+      #
+      # secrets =
+      #   let
+      #     secretsSourceDir = "${inputs.self}/age";
+      #   in
+      #   mapAttrs'
+      #     (name: _:
+      #       nameValuePair name {
+      #         file = "${secretsSourceDir}/${name}";
+      #         owner = mkDefault my.username;
+      #         group = mkDefault config.my.group;
+      #       })
+      #     (builtins.readDir secretsSourceDir);
+    };
+
+    environment.systemPackages = with pkgs; [agenix];
+  };
+}
diff --git a/modules/nixos/common/security.nix b/modules/nixos/common/security.nix
new file mode 100644
index 0000000..09c5da1
--- /dev/null
+++ b/modules/nixos/common/security.nix
@@ -0,0 +1,29 @@
+{
+  inputs,
+  lib,
+  ...
+}:
+with lib; {
+  security = {
+    sudo = {
+      enable = true;
+      execWheelOnly = true;
+      wheelNeedsPassword = false;
+      # https://mwl.io/archives/1000
+      extraConfig = ''
+        Defaults env_keep += "SSH_CLIENT SSH_CONNECTION SSH_TTY SSH_AUTH_SOCK"
+      '';
+    };
+
+    polkit = {
+      enable = true;
+      # https://wiki.archlinux.org/title/Polkit#Bypass_password_prompt
+      extraConfig = ''
+        polkit.addRule(function (action, subject) {
+          if (subject.isInGroup('wheel'))
+            return polkit.Result.YES;
+        });
+      '';
+    };
+  };
+}
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/nixos/common/systemd.nix b/modules/nixos/common/systemd.nix
new file mode 100644
index 0000000..5c7282d
--- /dev/null
+++ b/modules/nixos/common/systemd.nix
@@ -0,0 +1,22 @@
+{pkgs, ...}: {
+  hm.systemd.user.startServices = "sd-switch";
+
+  services.journald.extraConfig = ''
+    SystemMaxUse=5G
+  '';
+
+  systemd = let
+    extraConfig = ''
+      DefaultTimeoutStartSec=30s
+      DefaultTimeoutStopSec=15s
+    '';
+  in {
+    inherit extraConfig;
+    user = {inherit extraConfig;};
+  };
+
+  environment.sessionVariables = {
+    SYSTEMD_PAGER = "${pkgs.less}/bin/less";
+    SYSTEMD_LESS = "FRSXMK";
+  };
+}
diff --git a/modules/nixos/common/tmp.nix b/modules/nixos/common/tmp.nix
new file mode 100644
index 0000000..d56e2b6
--- /dev/null
+++ b/modules/nixos/common/tmp.nix
@@ -0,0 +1,18 @@
+_: {
+  systemd.mounts = [
+    {
+      type = "tmpfs";
+      what = "tmpfs";
+      where = "/tmp";
+      mountConfig.Options = [
+        "huge=within_size"
+        "mode=1777"
+        "noatime"
+        "nodev"
+        "nosuid"
+        "rw"
+        "size=25%"
+      ];
+    }
+  ];
+}
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/nixos/common/xdg.nix b/modules/nixos/common/xdg.nix
new file mode 100644
index 0000000..8ddf1ac
--- /dev/null
+++ b/modules/nixos/common/xdg.nix
@@ -0,0 +1,87 @@
+{
+  config,
+  lib,
+  this,
+  ...
+}:
+with lib; {
+  imports = let
+    withBase = s: ["home-manager" "users" my.username "xdg" s];
+  in [
+    (mkAliasOptionModule ["dirs" "cache"] (withBase "cacheHome"))
+    (mkAliasOptionModule ["dirs" "config"] (withBase "configHome"))
+    (mkAliasOptionModule ["dirs" "data"] (withBase "dataHome"))
+    (mkAliasOptionModule ["dirs" "state"] (withBase "stateHome"))
+    (mkAliasOptionModule ["userDirs"] (withBase "userDirs"))
+  ];
+
+  hm.xdg = mkMerge [
+    {
+      enable = true;
+
+      userDirs = let
+        inherit (config.my) home;
+        tmp = home + "/tmp";
+      in {
+        enable = true;
+
+        desktop = tmp;
+        documents = "${home}/doc";
+        download = tmp;
+        music = tmp;
+        pictures = tmp;
+        publicShare = "${home}/share";
+        templates = tmp;
+        videos = tmp;
+      };
+    }
+    (mkIf this.isHeadful {
+      mimeApps = {
+        enable = true;
+        defaultApplications = mkMerge (mapAttrsToList
+          (n: v: genAttrs v (_: ["${n}.desktop"]))
+          {
+            emacsclient = [
+              "application/json"
+              "application/vnd.ms-publisher"
+              "application/x-desktop"
+              "application/x-shellscript"
+              "application/x-trash"
+              "application/x-wine-extension-ini"
+              "application/xml"
+              "text/markdown"
+              "text/plain"
+            ];
+            firefox = [
+              "text/html"
+              "x-scheme-handler/http"
+              "x-scheme-handler/https"
+            ];
+            imv = [
+              "image/bmp"
+              "image/gif"
+              "image/jpeg"
+              "image/jpg"
+              "image/png"
+              "image/svg+xml"
+              "image/tiff"
+              "image/webp"
+            ];
+            mpv = [
+              "audio/aac"
+              "audio/flac"
+              "audio/mp3"
+              "audio/ogg"
+              "audio/wav"
+              "audio/webm"
+              "video/mkv"
+              "video/mp4"
+              "video/ogg"
+              "video/webm"
+              "video/x-matroska"
+            ];
+          });
+      };
+    })
+  ];
+}

Consider giving Nix/NixOS a try! <3