From 7e82df3df7ce5a4c6f81a8b1291766a859d93d7d Mon Sep 17 00:00:00 2001 From: mjallen18 Date: Thu, 21 Aug 2025 15:39:24 -0500 Subject: [PATCH] idk --- modules/nixos/disko/aarch64-linux/default.nix | 88 +++- modules/nixos/disko/options.nix | 5 + modules/nixos/disko/x86_64-linux/default.nix | 94 ++++- modules/nixos/impermanence/default.nix | 377 +++++++++--------- modules/nixos/impermanence/options.nix | 12 + modules/nixos/network/default.nix | 200 +++++----- modules/nixos/network/options.nix | 160 ++++++++ .../macbook-pro-nixos/default.nix | 24 +- systems/aarch64-linux/pi4/default.nix | 22 +- systems/aarch64-linux/pi5/default.nix | 11 +- systems/x86_64-linux/desktop/default.nix | 13 +- systems/x86_64-linux/nas/default.nix | 63 ++- systems/x86_64-linux/nuc/default.nix | 28 +- systems/x86_64-linux/steamdeck/default.nix | 17 +- 14 files changed, 768 insertions(+), 346 deletions(-) create mode 100644 modules/nixos/impermanence/options.nix create mode 100644 modules/nixos/network/options.nix diff --git a/modules/nixos/disko/aarch64-linux/default.nix b/modules/nixos/disko/aarch64-linux/default.nix index f674801..5160ff5 100644 --- a/modules/nixos/disko/aarch64-linux/default.nix +++ b/modules/nixos/disko/aarch64-linux/default.nix @@ -2,23 +2,78 @@ config, lib, system, + namespace, ... }: let + cfg = config.${namespace}.hardware.disko; isArm = builtins.match "aarch64*" system != null; rootDisk = "/dev/nvme0n1"; + + # BTRFS root partition configuration + btrfsRoot = { + name = "btrfs-root"; + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; # Override existing partition + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + subvolumes = { + "home" = { + mountOptions = [ "compress=zstd" ]; + mountpoint = "/home"; + }; + "root" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/root"; + }; + "nix" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/nix"; + }; + "etc" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/etc"; + }; + "log" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/var/log"; + }; + }; + }; + }; + + # BCacheFS root partition configuration + bcachefsRoot = { + size = "100%"; + content = { + type = "bcachefs"; + # This refers to a filesystem in the `bcachefs_filesystems` attrset below. + filesystem = "mounted_subvolumes_in_multi"; + label = "ssd.ssd1"; + extraFormatArgs = [ + "--discard" + ]; + }; + }; in { - config = lib.mkIf isArm { + imports = [ ../options.nix ]; + config = lib.mkIf (isArm && cfg.enable) { disko.devices = { - nodev."/" = { - fsType = "tmpfs"; - mountOptions = [ - "mode=755" - "defaults" - "size=2G" - ]; - }; # root disk setup disk.main = { type = "disk"; @@ -58,23 +113,12 @@ in }; }; - root = { - size = "100%"; - content = { - type = "bcachefs"; - # This refers to a filesystem in the `bcachefs_filesystems` attrset below. - filesystem = "mounted_subvolumes_in_multi"; - label = "ssd.ssd1"; - extraFormatArgs = [ - "--discard" - ]; - }; - }; + root = if cfg.filesystem == "btrfs" then btrfsRoot else bcachefsRoot; }; }; }; - bcachefs_filesystems = { + bcachefs_filesystems = lib.mkIf (cfg.filesystem == "bcachefs") { mounted_subvolumes_in_multi = { type = "bcachefs_filesystem"; # passwordFile = "/etc/nixos/pool.jwe"; diff --git a/modules/nixos/disko/options.nix b/modules/nixos/disko/options.nix index 4889465..24efd68 100644 --- a/modules/nixos/disko/options.nix +++ b/modules/nixos/disko/options.nix @@ -3,5 +3,10 @@ with lib; { options.${namespace}.hardware.disko = { enable = mkEnableOption "enable disko"; + filesystem = mkOption { + type = types.enum [ "bcachefs" "btrfs" ]; + default = "btrfs"; + description = "Filesystem to use for the root partition"; + }; }; } diff --git a/modules/nixos/disko/x86_64-linux/default.nix b/modules/nixos/disko/x86_64-linux/default.nix index ec6761e..b0c5909 100644 --- a/modules/nixos/disko/x86_64-linux/default.nix +++ b/modules/nixos/disko/x86_64-linux/default.nix @@ -1,16 +1,80 @@ { + config, lib, system, + namespace, ... }: let + cfg = config.${namespace}.hardware.disko; isArm = builtins.match "aarch64*" system != null; rootDisk = "/dev/nvme0n1"; + + # BTRFS root partition configuration + btrfsRoot = { + name = "btrfs-root"; + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; # Override existing partition + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + subvolumes = { + "home" = { + mountOptions = [ "compress=zstd" ]; + mountpoint = "/home"; + }; + "root" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/root"; + }; + "nix" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/nix"; + }; + "etc" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/etc"; + }; + "log" = { + mountOptions = [ + "compress=zstd" + "noatime" + ]; + mountpoint = "/var/log"; + }; + }; + }; + }; + + # BCacheFS root partition configuration + bcachefsRoot = { + size = "100%"; + content = { + type = "bcachefs"; + # This refers to a filesystem in the `bcachefs_filesystems` attrset below. + filesystem = "mounted_subvolumes_in_multi"; + label = "ssd.ssd1"; + extraFormatArgs = [ + "--discard" + ]; + }; + }; in { imports = [ ../options.nix ]; - config = lib.mkIf (!isArm) { - disko.devices = { + config = lib.mkIf (!isArm && cfg.enable) { + disko.devices = lib.mkMerge [ + { disk = { main = { device = rootDisk; @@ -30,24 +94,13 @@ in }; }; - root = { - size = "100%"; - content = { - type = "bcachefs"; - # This refers to a filesystem in the `bcachefs_filesystems` attrset below. - filesystem = "mounted_subvolumes_in_multi"; - label = "ssd.ssd1"; - extraFormatArgs = [ - "--discard" - ]; - }; - }; + root = if cfg.filesystem == "btrfs" then btrfsRoot else bcachefsRoot; }; }; }; }; - bcachefs_filesystems = { + bcachefs_filesystems = lib.mkIf (cfg.filesystem == "bcachefs") { mounted_subvolumes_in_multi = { type = "bcachefs_filesystem"; # passwordFile = "/etc/nixos/pool.jwe"; @@ -71,6 +124,15 @@ in mountpoint = "/partition-root"; }; }; - }; + } (lib.mkIf (cfg.filesystem == "btrfs") { + nodev."/" = { + fsType = "tmpfs"; + mountOptions = [ + "mode=755" + "defaults" + "size=25%" + ]; + }; + })]; }; } diff --git a/modules/nixos/impermanence/default.nix b/modules/nixos/impermanence/default.nix index c85e1cd..7b9b571 100755 --- a/modules/nixos/impermanence/default.nix +++ b/modules/nixos/impermanence/default.nix @@ -1,208 +1,191 @@ -# { ... }: -# { -# # Set up impernance configuration for things like bluetooth -# # In this configuration with /etc and /var/log being persistent, only directories outside of that need to be done here. See hardware configuration for all mountpoints. -# environment.persistence."/nix/persist/system" = { -# hideMounts = true; -# directories = [ -# "/var/lib/bluetooth" -# "/var/lib/iwd" -# "/var/lib/nixos" -# "/var/lib/libvirt" -# "/var/lib/waydroid" -# "/var/lib/systemd/coredump" -# "/etc/NetworkManager/system-connections" -# "/var/lib/tailscale" -# "/var/lib/homeassistant" -# "/var/lib/mosquitto" -# "/var/lib/music-assistant" -# "/var/lib/postgresql" -# "/var/lib/zigbee2mqtt" -# { -# directory = "/var/lib/colord"; -# user = "colord"; -# group = "colord"; -# mode = "u=rwx,g=rx,o="; -# } -# { -# directory = "/etc/nix"; -# user = "root"; -# group = "root"; -# mode = "u=rwx,g=rx,o=rx"; -# } -# { -# directory = "/var/lib/private/authentik/media"; -# user = "authentik"; -# group = "authentik"; -# mode = "u=rwx,g=,o="; -# } -# { -# directory = "/var/lib/private"; -# mode = "u=rwx,g=rx,o="; -# } -# { -# directory = "/media/nas"; -# user = "nas-apps"; -# group = "jallen-nas"; -# mode = "u=rwx,g=rx,o=rx"; -# } -# { -# directory = "/var/lib/crowdsec"; -# user = "crowdsec"; -# group = "crowdsec"; -# mode = "u=rwx,g=rwx,o=rx"; -# } -# { -# directory = "/plugins-storage"; -# user = "traefik"; -# group = "traefik"; -# mode = "u=rwx,g=rwx,o=rx"; -# } -# ]; -# files = [ -# "/etc/machine-id" -# ]; -# }; - -# security.sudo.extraConfig = '' -# # rollback results in sudo lectures after each reboot -# Defaults lecture = never -# ''; - -# } { config, lib, ... }: with lib; +let + cfg = config.mjallen.impermanence; +in { - system.activationScripts = { - "var-lib-private-permissions" = { - deps = [ "createPersistentStorageDirs" ]; - text = '' - mkdir -p /var/lib/private - chmod 0700 /var/lib/private - ''; + imports = [ ./options.nix ]; + + config = mkIf cfg.enable { + security.sudo.extraConfig = '' + # rollback results in sudo lectures after each reboot + Defaults lecture = never + ''; + + system.activationScripts = { + "var-lib-private-permissions" = { + deps = [ "createPersistentStorageDirs" ]; + text = '' + mkdir -p /var/lib/private + chmod 0700 /var/lib/private + ''; + }; + }; + + boot.initrd.systemd.services.rootfs-cleanup = { + description = "Clean file system root"; + wantedBy = [ + "initrd.target" + ]; + after = [ + "initrd-root-device.target" + ]; + before = [ + "sysroot.mount" + ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig.Type = "oneshot"; + script = + if (hasAttr "/" config.fileSystems) && (config.fileSystems."/".fsType == "btrfs") then + '' + # workaround for machines without working rtc battery + # The time may not yet be correctly set, so wait until it is + if [[ $(date '+%s') -lt 1730469314 ]]; then + sleep 30 # this should hopefully be enough + fi + mkdir /btrfs_tmp + mount ${config.fileSystems."/".device} -t btrfs /btrfs_tmp + if [[ -e /btrfs_tmp/root ]]; then + mkdir -p /btrfs_tmp/old_roots + timestamp=$(date --date="@$(stat -c %X /btrfs_tmp/root)" "+%Y-%m-%d_%H:%M:%S") + mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp" + fi + + delete_subvolume_recursively() { + IFS=$'\n' + for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do + delete_subvolume_recursively "/btrfs_tmp/$i" + done + btrfs subvolume delete "$1" || rm -rf "$1" + } + + for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -atime +30); do + delete_subvolume_recursively "$i" + done + + btrfs subvolume create /btrfs_tmp/root + umount /btrfs_tmp + '' + else if (hasAttr "/" config.fileSystems) && (config.fileSystems."/".fsType == "bcachefs") then + '' + # workaround for machines without working rtc battery + # The time may not yet be correctly set, so wait until it is + if [[ $(date '+%s') -lt 1730469314 ]]; then + sleep 30 # this should hopefully be enough + fi + if [[ -e /root_tmp/root ]]; then + mkdir -p /root_tmp/old_roots + timestamp=$(date --date="@$(stat -c %X /root_tmp/root)" "+%Y-%m-%d_%H:%M:%S") + mv /root_tmp/root "/root_tmp/old_roots/$timestamp" + fi + + for i in $(find /root_tmp/old_roots/ -maxdepth 1 -atime +30); do + bcachefs subvolume delete $i + done + + bcachefs subvolume create /root_tmp/root + '' + else + # For tmpfs or other filesystems, do nothing + ""; + }; + + assertions = [ + { + assertion = hasAttr "/" config.fileSystems; + message = "To use impermanence, you need to define a root volume"; + } + + { + assertion = + if hasAttr "/" config.fileSystems then + config.fileSystems."/".fsType == "btrfs" || config.fileSystems."/".fsType == "bcachefs" || config.fileSystems."/".fsType == "tmpfs" + else + false; + message = "rootfs must be btrfs, bcachefs, or tmpfs"; + } + + { + assertion = + if hasAttr "/" config.fileSystems && (config.fileSystems."/".fsType == "btrfs" || config.fileSystems."/".fsType == "bcachefs") then + any ( + t: t == "subvol=root" || t == "subvol=/root" || t == "X-mount.subdir=root" + ) config.fileSystems."/".options + else + true; + message = "btrfs or bcachefs rootfs must mount subvolume root"; + } + { + assertion = !config.boot.isContainer; + message = "impermanence is not supported in containers"; + } + ]; + + environment.persistence.${cfg.persistencePath} = { + hideMounts = true; + directories = [ + "/var/lib/bluetooth" + "/var/lib/iwd" + "/var/lib/nixos" + "/var/lib/libvirt" + "/var/lib/waydroid" + "/var/lib/systemd/coredump" + "/etc/NetworkManager/system-connections" + "/var/lib/tailscale" + "/var/lib/homeassistant" + "/var/lib/mosquitto" + "/var/lib/music-assistant" + "/var/lib/postgresql" + "/var/lib/zigbee2mqtt" + { + directory = "/var/lib/colord"; + user = "colord"; + group = "colord"; + mode = "u=rwx,g=rx,o="; + } + { + directory = "/etc/nix"; + user = "root"; + group = "root"; + mode = "u=rwx,g=rx,o=rx"; + } + { + directory = "/var/lib/private/authentik/media"; + user = "authentik"; + group = "authentik"; + mode = "u=rwx,g=,o="; + } + { + directory = "/var/lib/private"; + mode = "u=rwx,g=rx,o="; + } + { + directory = "/media/nas"; + user = "nas-apps"; + group = "jallen-nas"; + mode = "u=rwx,g=rx,o=rx"; + } + { + directory = "/var/lib/crowdsec"; + user = "crowdsec"; + group = "crowdsec"; + mode = "u=rwx,g=rwx,o=rx"; + } + { + directory = "/plugins-storage"; + user = "traefik"; + group = "traefik"; + mode = "u=rwx,g=rwx,o=rx"; + } + ]; + files = [ + "/etc/machine-id" + ]; }; }; - boot.initrd.systemd.services.rootfs-cleanup = { - description = "Clean file system root"; - wantedBy = [ - "initrd.target" - ]; - after = [ - "initrd-root-device.target" - ]; - before = [ - "sysroot.mount" - ]; - unitConfig.DefaultDependencies = "no"; - serviceConfig.Type = "oneshot"; - script = - if config.fileSystems."/".fsType == "btrfs" then - '' - # workaround for machines without working rtc battery - # The time may not yet be correctly set, so wait until it is - if [[ $(date '+%s') -lt 1730469314 ]]; then - sleep 30 # this should hopefully be enough - fi - mkdir /btrfs_tmp - mount ${config.fileSystems."/".device} -t btrfs /btrfs_tmp - if [[ -e /btrfs_tmp/root ]]; then - mkdir -p /btrfs_tmp/old_roots - timestamp=$(date --date="@$(stat -c %X /btrfs_tmp/root)" "+%Y-%m-%d_%H:%M:%S") - mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp" - fi - - delete_subvolume_recursively() { - IFS=$'\n' - for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do - delete_subvolume_recursively "/btrfs_tmp/$i" - done - btrfs subvolume delete "$1" || rm -rf "$1" - } - - for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -atime +30); do - delete_subvolume_recursively "$i" - done - - btrfs subvolume create /btrfs_tmp/root - umount /btrfs_tmp - '' - else - '' - # workaround for machines without working rtc battery - # The time may not yet be correctly set, so wait until it is - if [[ $(date '+%s') -lt 1730469314 ]]; then - sleep 30 # this should hopefully be enough - fi - if [[ -e /root_tmp/root ]]; then - mkdir -p /root_tmp/old_roots - timestamp=$(date --date="@$(stat -c %X /root_tmp/root)" "+%Y-%m-%d_%H:%M:%S") - mv /root_tmp/root "/root_tmp/old_roots/$timestamp" - fi - - for i in $(find /root_tmp/old_roots/ -maxdepth 1 -atime +30); do - bcachefs subvolume delete $i - done - - bcachefs subvolume create /root_tmp/root - ''; - }; - # assertions = [ - # { - # assertion = hasAttr "/" config.fileSystems; - # message = "To use impermanence, you need to define a root volume"; - # } - - # { - # assertion = - # if hasAttr "/" config.fileSystems then - # config.fileSystems."/".fsType == "btrfs" || config.fileSystems."/".fsType == "bcachefs" - # else - # false; - # message = "rootfs must be btrfs or bcachefs"; - # } - - # { - # assertion = - # if hasAttr "/" config.fileSystems then - # any ( - # t: t == "subvol=root" || t == "subvol=/root" || t == "X-mount.subdir=root" - # ) config.fileSystems."/".options - # else - # false; - # message = "rootfs must mount subvolume root"; - # } - # { - # assertion = !config.boot.isContainer; - # message = "impermanence is not supported in containers"; - # } - # ]; - - fileSystems."/persistent" = { - neededForBoot = true; - }; - environment.persistence."/persistent" = { - enable = true; - hideMounts = true; - directories = [ - "/var/log" - "/var/lib/nixos" - "/var/cache" - ]; - files = [ - "/etc/ssh/ssh_host_ecdsa_key" - "/etc/ssh/ssh_host_ecdsa_key.pub" - "/etc/ssh/ssh_host_ed25519_key" - "/etc/ssh/ssh_host_ed25519_key.pub" - "/etc/ssh/ssh_host_rsa_key" - "/etc/ssh/ssh_host_rsa_key.pub" - ]; - }; - systemd.tmpfiles.rules = [ - "d /persistent/var/cache 1777 root root 7d -" - ]; } diff --git a/modules/nixos/impermanence/options.nix b/modules/nixos/impermanence/options.nix new file mode 100644 index 0000000..11a10ee --- /dev/null +++ b/modules/nixos/impermanence/options.nix @@ -0,0 +1,12 @@ +{ lib, namespace, ... }: +with lib; +{ + options.${namespace}.impermanence = { + enable = mkEnableOption "enable impermanence"; + persistencePath = mkOption { + type = types.str; + default = "/nix/persist/system"; + description = "Path to the persistence directory"; + }; + }; +} diff --git a/modules/nixos/network/default.nix b/modules/nixos/network/default.nix index 903baf6..934ca91 100644 --- a/modules/nixos/network/default.nix +++ b/modules/nixos/network/default.nix @@ -1,6 +1,7 @@ { config, lib, + pkgs, namespace, ... }: @@ -9,113 +10,45 @@ let cfg = config.${namespace}.network; in { - options.${namespace}.network = with types; { - hostName = lib.mkOption { - type = str; - default = "nixos"; - description = "The hostname of the system."; - }; - - ipv4 = { - method = mkOption { - type = types.str; - default = "auto"; - }; - address = lib.mkOption { - type = types.str; - default = "10.0.1.1"; - }; - gateway = lib.mkOption { - type = types.str; - default = "10.0.1.1"; - }; - dns = lib.mkOption { - type = types.str; - default = "10.0.1.1"; - }; - }; - }; + imports = [ + ./options.nix + ]; config = { networking = { hostName = lib.mkForce cfg.hostName; - - # Enable Network Manager - networkmanager = { - enable = true; - wifi.powersave = lib.mkDefault false; - settings.connectivity.uri = lib.mkDefault "http://nmcheck.gnome.org/check_network_status.txt"; - ensureProfiles = { - environmentFiles = [ - config.sops.secrets.wifi.path - ]; - - profiles = { - "Joey's Jungle 6G" = { - connection = { - id = "Joey's Jungle 6G"; - type = "wifi"; - }; - ipv4 = - if (cfg.ipv4.method == "auto") then - { - method = "auto"; - } - else - { - address1 = cfg.ipv4.address; - dns = cfg.ipv4.dns; - gateway = cfg.ipv4.gateway; - method = "manual"; - }; - ipv6 = { - addr-gen-mode = "stable-privacy"; - method = "auto"; - }; - wifi = { - mode = "infrastructure"; - ssid = "Joey's Jungle 6G"; - }; - wifi-security = { - key-mgmt = "sae"; - psk = "$PSK"; - }; - }; - - "Joey's Jungle 5G" = { - connection = { - id = "Joey's Jungle 5G"; - type = "wifi"; - }; - ipv4 = - if (cfg.ipv4.method == "auto") then - { - method = "auto"; - } - else - { - address1 = cfg.ipv4.address; - dns = cfg.ipv4.dns; - gateway = cfg.ipv4.gateway; - method = "manual"; - }; - ipv6 = { - addr-gen-mode = "stable-privacy"; - method = "auto"; - }; - wifi = { - mode = "infrastructure"; - ssid = "Joey's Jungle 5G"; - }; - wifi-security = { - key-mgmt = "sae"; - psk = "$PSK"; - }; - }; - }; - }; + + # Use networkd if enabled + useNetworkd = lib.mkIf cfg.useNetworkd true; + + # Set default gateway and nameservers if in manual mode + defaultGateway = lib.mkIf (cfg.ipv4.method == "manual") { + address = cfg.ipv4.gateway; + interface = lib.mkIf (cfg.ipv4.interface != "") cfg.ipv4.interface; }; + + nameservers = lib.mkIf (cfg.ipv4.method == "manual") [ cfg.ipv4.dns ]; + + # Set hostId if provided + hostId = lib.mkIf (cfg.hostId != "") cfg.hostId; + + # Configure NAT if enabled + nat = lib.mkIf cfg.nat.enable { + enable = true; + internalInterfaces = cfg.nat.internalInterfaces; + externalInterface = cfg.nat.externalInterface; + enableIPv6 = cfg.nat.enableIPv6; + }; + + # Configure firewall firewall = { + enable = cfg.firewall.enable; + allowPing = cfg.firewall.allowPing; + allowedTCPPorts = cfg.firewall.allowedTCPPorts; + allowedUDPPorts = cfg.firewall.allowedUDPPorts; + trustedInterfaces = cfg.firewall.trustedInterfaces; + + # Default port ranges for KDE Connect allowedTCPPortRanges = [ { from = 1714; @@ -123,7 +56,72 @@ in } ]; allowedUDPPortRanges = config.networking.firewall.allowedTCPPortRanges; + + # Extra firewall commands + extraCommands = lib.mkIf (cfg.extraFirewallCommands != "") cfg.extraFirewallCommands; }; + + # Configure iwd if enabled + wireless.iwd = lib.mkIf cfg.iwd.enable { + enable = true; + settings = cfg.iwd.settings; + }; + + # Configure NetworkManager + networkmanager = mkMerge [ + # Disable NetworkManager when iwd is enabled + (mkIf cfg.iwd.enable { + enable = mkForce false; + wifi.backend = mkForce "iwd"; + }) + + # Enable NetworkManager when wifi is enabled and iwd is disabled + (mkIf (cfg.wifi.enable && !cfg.iwd.enable) { + enable = true; + wifi.powersave = cfg.wifi.powersave; + settings.connectivity.uri = mkDefault "http://nmcheck.gnome.org/check_network_status.txt"; + + # Configure WiFi profiles if any are defined + ensureProfiles = mkIf (cfg.wifi.profiles != {}) { + environmentFiles = [ + config.sops.secrets.wifi.path + ]; + + profiles = mapAttrs + (name: profile: { + connection = { + id = name; + type = "wifi"; + }; + ipv4 = + if (cfg.ipv4.method == "auto") then + { + method = "auto"; + } + else + { + address1 = cfg.ipv4.address; + dns = cfg.ipv4.dns; + gateway = cfg.ipv4.gateway; + method = "manual"; + }; + ipv6 = { + addr-gen-mode = "stable-privacy"; + method = "auto"; + }; + wifi = { + mode = "infrastructure"; + ssid = profile.ssid; + }; + wifi-security = { + key-mgmt = profile.keyMgmt; + psk = profile.psk; + }; + }) + cfg.wifi.profiles; + }; + }) + ]; }; }; } diff --git a/modules/nixos/network/options.nix b/modules/nixos/network/options.nix new file mode 100644 index 0000000..de56ac6 --- /dev/null +++ b/modules/nixos/network/options.nix @@ -0,0 +1,160 @@ +{ + lib, + namespace, + ... +}: +with lib; +{ + options.${namespace}.network = with types; { + hostName = lib.mkOption { + type = str; + default = "nixos"; + description = "The hostname of the system."; + }; + + ipv4 = { + method = mkOption { + type = types.str; + default = "auto"; + description = "Method for IPv4 configuration (auto or manual)."; + }; + address = lib.mkOption { + type = types.str; + default = "10.0.1.1/24"; + description = "IPv4 address with subnet mask (e.g., 10.0.1.1/24)."; + }; + gateway = lib.mkOption { + type = types.str; + default = "10.0.1.1"; + description = "IPv4 default gateway."; + }; + interface = lib.mkOption { + type = types.str; + default = ""; + description = "Interface for the default gateway (required when using networkd)."; + }; + dns = lib.mkOption { + type = types.str; + default = "10.0.1.1"; + description = "IPv4 DNS server."; + }; + }; + + useNetworkd = mkOption { + type = types.bool; + default = false; + description = "Whether to use systemd-networkd for networking."; + }; + + nat = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable NAT."; + }; + internalInterfaces = mkOption { + type = types.listOf types.str; + default = []; + description = "List of internal interfaces for NAT."; + }; + externalInterface = mkOption { + type = types.str; + default = ""; + description = "External interface for NAT."; + }; + enableIPv6 = mkOption { + type = types.bool; + default = false; + description = "Whether to enable IPv6 NAT."; + }; + }; + + firewall = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable the firewall."; + }; + allowPing = mkOption { + type = types.bool; + default = true; + description = "Whether to allow ICMP ping."; + }; + allowedTCPPorts = mkOption { + type = types.listOf types.port; + default = []; + description = "List of allowed TCP ports."; + }; + allowedUDPPorts = mkOption { + type = types.listOf types.port; + default = []; + description = "List of allowed UDP ports."; + }; + trustedInterfaces = mkOption { + type = types.listOf types.str; + default = []; + description = "List of trusted interfaces."; + }; + }; + + wifi = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable WiFi configuration."; + }; + powersave = mkOption { + type = types.bool; + default = false; + description = "Whether to enable WiFi power saving."; + }; + profiles = mkOption { + type = types.attrsOf (types.submodule { + options = { + ssid = mkOption { + type = types.str; + description = "SSID of the WiFi network."; + }; + psk = mkOption { + type = types.str; + default = "$PSK"; + description = "PSK environment variable for the WiFi password."; + }; + keyMgmt = mkOption { + type = types.str; + default = "sae"; + description = "Key management type (e.g., sae, wpa-psk)."; + }; + }; + }); + default = {}; + description = "WiFi network profiles."; + }; + }; + + hostId = mkOption { + type = types.str; + default = ""; + description = "Host ID for ZFS and other services."; + }; + + iwd = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable iwd for wireless networking."; + }; + settings = mkOption { + type = types.attrs; + default = {}; + description = "Settings for iwd."; + }; + }; + + extraFirewallCommands = mkOption { + type = types.str; + default = ""; + description = "Extra commands for the firewall."; + }; + }; +} diff --git a/systems/aarch64-linux/macbook-pro-nixos/default.nix b/systems/aarch64-linux/macbook-pro-nixos/default.nix index 515b3fb..98d0b26 100755 --- a/systems/aarch64-linux/macbook-pro-nixos/default.nix +++ b/systems/aarch64-linux/macbook-pro-nixos/default.nix @@ -15,7 +15,7 @@ in imports = [ ./boot.nix ./hardware-configuration.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./services.nix ]; @@ -58,6 +58,28 @@ in }; network = { hostName = "macbook-pro-nixos"; + wifi.enable = false; + iwd = { + enable = true; + settings = { + General = { + EnableNetworkConfiguration = true; + }; + Rank = { + BandModifier2_4GHz = 1.0; + BandModifier5GHz = 5.0; + BandModifier6GHz = 10.0; + }; + Network = { + AutoConnect = true; + }; + }; + }; + extraFirewallCommands = '' + iptables -I INPUT -m pkttype --pkt-type multicast -j ACCEPT + iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT + iptables -I INPUT -p udp -m udp --match multiport --dports 1990,2021 -j ACCEPT + ''; }; }; diff --git a/systems/aarch64-linux/pi4/default.nix b/systems/aarch64-linux/pi4/default.nix index dd243b4..611af04 100755 --- a/systems/aarch64-linux/pi4/default.nix +++ b/systems/aarch64-linux/pi4/default.nix @@ -17,13 +17,31 @@ in imports = [ ./adguard.nix ./boot.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./sops.nix ]; ${namespace} = { hardware.disko.enable = true; - network.hostName = "pi4"; + network = { + hostName = "pi4"; + ipv4 = { + method = "manual"; + address = "10.0.1.2/24"; + gateway = "10.0.1.1"; + dns = "1.1.1.1"; + }; + firewall = { + enable = true; + allowPing = true; + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; + wifi = { + enable = true; + powersave = false; + }; + }; }; # Configure nixpkgs diff --git a/systems/aarch64-linux/pi5/default.nix b/systems/aarch64-linux/pi5/default.nix index 1197c69..eef5494 100644 --- a/systems/aarch64-linux/pi5/default.nix +++ b/systems/aarch64-linux/pi5/default.nix @@ -17,7 +17,7 @@ in { imports = [ ./boot.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./services.nix ./sops.nix ]; @@ -27,6 +27,15 @@ in desktop.hyprland.enable = false; network = { hostName = "pi5"; + ipv4 = { + method = "manual"; + gateway = "10.0.1.1"; + dns = "10.0.1.1"; + }; + firewall = { + enable = true; + allowPing = true; + }; }; }; diff --git a/systems/x86_64-linux/desktop/default.nix b/systems/x86_64-linux/desktop/default.nix index 94d2a2d..397693c 100644 --- a/systems/x86_64-linux/desktop/default.nix +++ b/systems/x86_64-linux/desktop/default.nix @@ -28,7 +28,7 @@ in ./configuration.nix ./filesystems.nix ./hardware-configuration.nix - # ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./nix.nix ./sops.nix @@ -38,10 +38,21 @@ in ]; ${namespace} = { + hardware.disko.enable = false; bootloader.lanzaboote.enable = true; desktop.gnome.enable = true; network = { hostName = "matt-nixos"; + wifi = { + enable = true; + powersave = false; + profiles = { + "Joey's Jungle 6G" = { + ssid = "Joey's Jungle 6G"; + keyMgmt = "sae"; + }; + }; + }; }; user = { passwordFile = passwordFile; diff --git a/systems/x86_64-linux/nas/default.nix b/systems/x86_64-linux/nas/default.nix index ae8300e..5b71e21 100755 --- a/systems/x86_64-linux/nas/default.nix +++ b/systems/x86_64-linux/nas/default.nix @@ -17,7 +17,7 @@ ./boot.nix ./apps.nix ./grafana.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./ups.nix ./users.nix ./samba.nix @@ -44,6 +44,67 @@ ipv4 = { address = "10.0.1.3/24"; method = "manual"; + gateway = "10.0.1.1"; + interface = "wlp6s0"; + }; + useNetworkd = true; + hostId = "4b501480"; + nat = { + enable = true; + internalInterfaces = [ "ve-+" ]; + externalInterface = "wlp6s0"; + enableIPv6 = true; + }; + firewall = { + enable = true; + allowPing = true; + allowedTCPPorts = [ + 8008 # restic + 9000 # authentik + 2342 # grafana + 51820 # wireguard + 1025 + 1143 + 10200 + 10300 + 8127 + 9980 # onlyoffice + 4000 # netbootxyz + 4080 # netbootxyz + 3000 # gitea + 2222 # gitea ssh + 3300 + 9898 + 6754 # lubelogger + 2283 # immich + 4444 # code-server + 9012 + 8192 + ]; + allowedUDPPorts = [ + 8008 # restic + 9000 # authentik + 2342 # grafana + 51820 # wireguard + 1025 + 1143 + 10200 + 10300 + 8127 + 9980 # onlyoffice + 4000 # netbootxyz + 4080 # netbootxyz + 3000 # gitea + 2222 # gitea ssh + 3300 + 9898 + 6754 # lubelogger + 2283 # immich + 4444 # code-server + 9012 + 8192 + ]; + trustedInterfaces = [ "tailscale0" ]; }; }; user = { diff --git a/systems/x86_64-linux/nuc/default.nix b/systems/x86_64-linux/nuc/default.nix index f242120..bf663e5 100644 --- a/systems/x86_64-linux/nuc/default.nix +++ b/systems/x86_64-linux/nuc/default.nix @@ -6,7 +6,7 @@ { imports = [ ./boot.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./users.nix ./sops.nix ]; @@ -18,7 +18,31 @@ ${namespace} = { services.home-assistant.enable = true; hardware.disko.enable = true; - network.hostName = "nuc-nixos"; + network = { + hostName = "nuc-nixos"; + useNetworkd = true; + ipv4 = { + method = "manual"; + address = "10.0.1.4/24"; + gateway = "10.0.1.1"; + dns = "10.0.1.1"; + }; + wifi = { + enable = true; + profiles = { + "Joey's Jungle 6G" = { + ssid = "Joey's Jungle 6G"; + keyMgmt = "sae"; + }; + }; + }; + firewall = { + enable = true; + allowPing = true; + allowedTCPPorts = [ 8192 ]; + allowedUDPPorts = [ 8192 ]; + }; + }; }; # Enable nix flakes and nix-command tools diff --git a/systems/x86_64-linux/steamdeck/default.nix b/systems/x86_64-linux/steamdeck/default.nix index f43fb48..edb8acc 100644 --- a/systems/x86_64-linux/steamdeck/default.nix +++ b/systems/x86_64-linux/steamdeck/default.nix @@ -15,17 +15,30 @@ ./boot.nix ./configuration.nix ./jovian.nix - ./networking.nix + # ./networking.nix - moved to modules/nixos/network ./sops.nix ]; ${namespace} = { hardware.disko.enable = true; + impermanence.enable = true; bootloader.lanzaboote.enable = true; desktop.gnome.enable = true; user = { name = "deck"; }; - network.hostName = "steamdeck"; + network = { + hostName = "steamdeck"; + wifi = { + enable = true; + powersave = false; + profiles = { + "Joey's Jungle 5G" = { + ssid = "Joey's Jungle 5G"; + keyMgmt = "sae"; + }; + }; + }; + }; }; }