diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/audio.nix | 96 | ||||
| -rw-r--r-- | modules/bluetooth.nix | 19 | ||||
| -rw-r--r-- | modules/bootloader.nix | 100 | ||||
| -rw-r--r-- | modules/compat.nix | 28 | ||||
| -rw-r--r-- | modules/drivers.nix | 99 | ||||
| -rw-r--r-- | modules/files.nix | 55 | ||||
| -rw-r--r-- | modules/fonts.nix | 32 | ||||
| -rw-r--r-- | modules/gaming.nix | 145 | ||||
| -rw-r--r-- | modules/greet.nix | 32 | ||||
| -rw-r--r-- | modules/i2p.nix | 81 | ||||
| -rw-r--r-- | modules/localization.nix | 41 | ||||
| -rw-r--r-- | modules/memory.nix | 41 | ||||
| -rw-r--r-- | modules/monero.nix | 124 | ||||
| -rw-r--r-- | modules/networking.nix | 186 | ||||
| -rw-r--r-- | modules/niri.nix | 28 | ||||
| -rw-r--r-- | modules/nix-helper.nix | 40 | ||||
| -rw-r--r-- | modules/omnisearch.nix | 73 | ||||
| -rw-r--r-- | modules/persistance.nix | 50 | ||||
| -rw-r--r-- | modules/power.nix | 54 | ||||
| -rw-r--r-- | modules/security.nix | 72 | ||||
| -rw-r--r-- | modules/sops.nix | 36 | ||||
| -rw-r--r-- | modules/ssh.nix | 95 | ||||
| -rw-r--r-- | modules/storage.nix | 21 | ||||
| -rw-r--r-- | modules/syncthing.nix | 136 | ||||
| -rw-r--r-- | modules/tor.nix | 31 | ||||
| -rw-r--r-- | modules/users.nix | 54 | ||||
| -rw-r--r-- | modules/virtualization.nix | 40 |
27 files changed, 1809 insertions, 0 deletions
diff --git a/modules/audio.nix b/modules/audio.nix new file mode 100644 index 0000000..e926076 --- /dev/null +++ b/modules/audio.nix @@ -0,0 +1,96 @@ +{ + flake.nixosModules.audio = { config, lib, pkgs, ... }: + let + cfg = config.os.core.audio; + in + { + options.os.core.audio = { + enable = lib.mkEnableOption "audio support"; + disable-devices.enable = lib.mkEnableOption "disables some random devices cluttering up"; + noise-cancellation.enable = lib.mkEnableOption "RNNoise background noise cancellation"; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + services.pulseaudio.enable = false; + security.rtkit.enable = true; + + services.pipewire = { + enable = true; + audio.enable = true; + pulse.enable = true; + alsa = { + enable = true; + support32Bit = true; + }; + jack.enable = true; + + wireplumber = { + enable = true; + extraConfig."99-lock-microphone-gain"."pulse.rules" = [{ + matches = [ { "application.name" = "~*cord*"; } ]; + actions.quirks = [ "no-source-volume" ]; + }]; + }; + }; + services.playerctld.enable = true; + + environment.systemPackages = with pkgs; [ + crosspipe + pulsemixer + pavucontrol + alsa-utils + ]; + }) + + (lib.mkIf cfg.disable-devices.enable { + services.pipewire.wireplumber.extraConfig = { + "99-disable-devices"."monitor.alsa.rules" = [{ + matches = [ + { "device.name" = "~alsa_card.pci-0000_03_00.1*"; } + { "device.description" = "~USB Audio*"; } + ]; + actions.update-props."device.disabled" = true; + }]; + }; + }) + + (lib.mkIf cfg.noise-cancellation.enable { + services.pipewire.extraConfig.pipewire."99-rnnoise" = { + "context.modules" = [ + { + name = "libpipewire-module-filter-chain"; + args = { + "node.description" = "Noise Canceling Source"; + "media.name" = "Noise Canceling Source"; + "filter.graph".nodes = [ + { + type = "ladspa"; + name = "rnnoise"; + plugin = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so"; + label = "noise_suppressor_mono"; + control = { + "VAD Threshold (%)" = 50.0; + "VAD Grace Period (ms)" = 200.0; + "Retroactive VAD Grace Period (ms)" = 0.0; + }; + } + ]; + "capture.props" = { + "node.name" = "effect_input.rnnoise"; + "node.passive" = true; + "audio.position" = [ "MONO" ]; + }; + "playback.props" = { + "node.name" = "effect_output.rnnoise"; + "media.class" = "Audio/Source"; + "audio.position" = [ "MONO" ]; + }; + }; + } + ]; + }; + }) + ]; + }; +} diff --git a/modules/bluetooth.nix b/modules/bluetooth.nix new file mode 100644 index 0000000..1705db6 --- /dev/null +++ b/modules/bluetooth.nix @@ -0,0 +1,19 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.srv.bluetooth; +in +{ + options.os.srv.bluetooth.enable = lib.mkEnableOption "enables bluetooth support"; + config = lib.mkIf cfg.enable { + hardware.bluetooth = { + enable = true; + powerOnBoot = true; + }; + environment.systemPackages = [ pkgs.bluetui ]; + }; +} diff --git a/modules/bootloader.nix b/modules/bootloader.nix new file mode 100644 index 0000000..e8dfc11 --- /dev/null +++ b/modules/bootloader.nix @@ -0,0 +1,100 @@ +{ + config, + lib, + ... +}: +let + cfg = config.os.core.bootloader; +in +{ + options.os.core.bootloader = { + type = lib.mkOption { + type = lib.types.enum [ + "systemd-boot" + "grub" + "none" + ]; + default = "systemd-boot"; + description = "Which bootloader to use"; + }; + + efi = lib.mkOption { + type = lib.types.bool; + default = if cfg.grub.device == "nodev" then true else false; + description = "Whether the system uses UEFI or Legacy BIOS"; + }; + + timeout = lib.mkOption { + type = lib.types.int; + default = 3; + description = "Boot menu timeout in seconds"; + }; + + grub = { + device = lib.mkOption { + type = lib.types.str; + default = "nodev"; + description = "Device to install GRUB to (e.g. /dev/nvme0n1). Use 'nodev' for UEFI."; + }; + useOSProber = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Scan for other operating systems"; + }; + defaultEntry = lib.mkOption { + type = lib.types.int; + default = 0; + description = "Index of the default boot entry"; + }; + }; + + #TODO add boot.initrd.luks.reusePassphrases = true; somewhere + luks.enable = lib.mkEnableOption "LUKS encryption support"; + }; + + config = lib.mkMerge [ + # 1. Common Kernel & Initrd Settings + { + boot = { + loader = { + timeout = cfg.timeout; + efi.canTouchEfiVariables = lib.mkDefault cfg.efi; + }; + supportedFilesystems = [ + "ntfs" + "btrfs" + ]; + kernelParams = [ + "quiet" + "splash" + ]; + consoleLogLevel = 0; + initrd.availableKernelModules = [ + "aesni_intel" + "cryptd" + ]; + }; + systemd.settings.Manager.DefaultTimeoutStopSec = "5s"; + } + + # 2. Systemd-boot Implementation + (lib.mkIf (cfg.type == "systemd-boot") { + boot.loader.systemd-boot = { + enable = true; + editor = false; + consoleMode = "max"; + }; + }) + + # 3. GRUB Implementation + (lib.mkIf (cfg.type == "grub") { + boot.loader.grub = { + enable = true; + efiSupport = cfg.efi; + useOSProber = cfg.grub.useOSProber; + default = cfg.grub.defaultEntry; + enableCryptodisk = cfg.luks.enable; + }; + }) + ]; +} diff --git a/modules/compat.nix b/modules/compat.nix new file mode 100644 index 0000000..1ea6105 --- /dev/null +++ b/modules/compat.nix @@ -0,0 +1,28 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.srv.compat; +in +{ + options.os.srv.compat.enable = lib.mkEnableOption "enables compatibility with windows & x11"; + config = lib.mkIf cfg.enable { + programs.xwayland = { + enable = true; + package = pkgs.xwayland-satellite; + }; + + environment.systemPackages = with pkgs; [ + wineWow64Packages.stagingFull + winetricks + ]; + + environment.sessionVariables = { + NIXOS_OZONE_WL = "1"; + ELECTRON_ENABLE_WAYLAND = "1"; + }; + }; +} diff --git a/modules/drivers.nix b/modules/drivers.nix new file mode 100644 index 0000000..6e74e98 --- /dev/null +++ b/modules/drivers.nix @@ -0,0 +1,99 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.core.drivers; +in +{ + options.os.core.drivers = { + enable = lib.mkEnableOption "enables hardware drivers"; + + cpu = lib.mkOption { + type = lib.types.enum [ + "intel" + "amd" + "none" + ]; + default = "none"; + description = "cpu manufacturer for microcode and platform-specific drivers"; + }; + + graphics = { + enable = lib.mkEnableOption "graphics support"; + amdgpu.enable = lib.mkEnableOption "amd specific gpu features"; + }; + + kernel = lib.mkOption { + type = lib.types.enum [ + "stable" + "zen" + "zfs" + "hardened" + ]; + default = "stable"; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + hardware.enableAllFirmware = true; + services = { + smartd.enable = true; + fwupd.enable = true; + }; + environment.systemPackages = [ pkgs.rivalcfg ]; + } + + (lib.mkIf (cfg.cpu == "amd") { + hardware.cpu.amd.updateMicrocode = true; + programs.coolercontrol.enable = true; + }) + + (lib.mkIf (cfg.cpu == "intel") { + hardware.cpu.intel.updateMicrocode = true; + services.thermald.enable = true; + }) + + (lib.mkIf cfg.graphics.enable { + hardware.graphics = { + enable = true; + enable32Bit = true; + }; + hardware.sensor.iio.enable = true; + }) + + (lib.mkIf (cfg.graphics.enable && cfg.graphics.amdgpu.enable) { + services = { + lact.enable = true; + hardware.openrgb.enable = true; + }; + hardware = { + amdgpu = { + initrd.enable = true; + overdrive.enable = true; + }; + graphics.extraPackages = with pkgs; [ + rocmPackages.clr.icd + libva-utils + ]; + }; + }) + { + boot.kernelPackages = + let + kernels = { + "stable" = pkgs.linuxPackages_latest; + "zen" = pkgs.linuxPackages_zen; + "hardened" = pkgs.linuxPackages_hardened; + "zfs" = config.boot.zfs.package.latestCompatibleLinuxPackages; + }; + in + kernels.${cfg.kernel} or kernels."stable"; + } + ] + ); +} diff --git a/modules/files.nix b/modules/files.nix new file mode 100644 index 0000000..777a394 --- /dev/null +++ b/modules/files.nix @@ -0,0 +1,55 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.srv.files; +in +{ + options.os.srv.files = { + enable = lib.mkEnableOption "enables general file management stuff"; + localsend.enable = lib.mkEnableOption "enables localsend for sharing files locally"; + krusader.enable = lib.mkEnableOption "enables krusader for easier file moving using ssh"; + }; + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + # programs.thunar = { + # enable = true; + # plugins = with pkgs; [ + # ffmpegthumbnailer + # libgsf + # poppler + # freetype + # webp-pixbuf-loader + # thunar-volman + # thunar-archive-plugin + # ]; + # }; + services = { + tumbler.enable = true; + gvfs.enable = true; + }; + environment.systemPackages = with pkgs; [ + pcmanfm + file-roller + gdu + pxz + ripunzip + ]; + }) + (lib.mkIf cfg.localsend.enable { + programs.localsend = { + enable = true; + openFirewall = true; + }; + }) + (lib.mkIf cfg.krusader.enable { + environment.systemPackages = with pkgs; [ + krusader + kdePackages.kio-extras + ]; + }) + ]; +} diff --git a/modules/fonts.nix b/modules/fonts.nix new file mode 100644 index 0000000..344ff63 --- /dev/null +++ b/modules/fonts.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.core.fonts; +in +{ + options.os.core.fonts.enable = lib.mkEnableOption "system-wide font and console configuration"; + + config = lib.mkIf cfg.enable { + # console = { + # keyMap = "pl"; + # earlySetup = true; + # font = "ter-v32n"; + # packages = with pkgs; [ terminus_font ]; + # }; + + fonts.packages = with pkgs; [ + nerd-fonts.jetbrains-mono + nerd-fonts.fira-mono + nerd-fonts.fira-code + + noto-fonts + noto-fonts-cjk-sans + noto-fonts-cjk-serif + noto-fonts-color-emoji + ]; + }; +} diff --git a/modules/gaming.nix b/modules/gaming.nix new file mode 100644 index 0000000..b9b6766 --- /dev/null +++ b/modules/gaming.nix @@ -0,0 +1,145 @@ +{ + config, + lib, + pkgs, + username, + inputs, + ... +}: +let + cfg = config.os.srv.gaming; +in +{ + options.os.srv.gaming = { + enable = lib.mkEnableOption "enables general gaming support"; + + tools.enable = lib.mkEnableOption "enables performance tools" // { + default = cfg.enable; + }; + launchers.enable = lib.mkEnableOption "enables 3rd party launchers" // { + default = cfg.enable; + }; + games.enable = lib.mkEnableOption "enables specific native games"; + steam = { + enable = lib.mkEnableOption "enables the steam launcher"; + enableSls = lib.mkEnableOption "enables the SLS Steam library modification"; + }; + vr.enable = lib.mkEnableOption "enables vr support"; + }; + + config = lib.mkMerge [ + # --- PERFORMANCE & TOOLING --- + (lib.mkIf cfg.tools.enable { + hardware.xone.enable = true; + programs = { + gamescope = { + enable = true; + capSysNice = true; + }; + + gamemode = { + enable = true; + enableRenice = true; + settings = { + general.renice = 10; + }; + }; + }; + environment = { + sessionVariables = { + OPTISCALER_ShortcutKey = "0x24"; # sets the optiscaler shortcut key to be home by default + }; + + systemPackages = with pkgs; [ + mangohud + theclicker + ludusavi + protonplus + ]; + }; + }) + + # --- EXTERNAL LAUNCHERS --- + (lib.mkIf cfg.launchers.enable { + environment.systemPackages = with pkgs; [ + heroic + (prismlauncher.override { + additionalLibs = with pkgs; [ ocl-icd ]; + jdks = with pkgs; [ javaPackages.compiler.temurin-bin.jdk-26 ]; + }) + ]; + }) + + # --- SPECIFIC GAMES --- + (lib.mkIf cfg.games.enable { + environment.systemPackages = with inputs.openmw-nix.packages.${pkgs.stdenv.hostPlatform.system}; [ + (pkgs.openttd-jgrpp) + + # OpenMW Specific + (pkgs.openmw) + (pkgs.tes3cmd) + delta-plugin + groundcoverify + momw-configurator + openmw-validator + s3lightfixes + umo + ]; + }) + + # --- STEAM --- + (lib.mkIf cfg.steam.enable ( + lib.mkMerge [ + { + programs.steam = { + enable = true; + localNetworkGameTransfers.openFirewall = true; + dedicatedServer.openFirewall = true; + remotePlay.openFirewall = false; + extest.enable = true; + protontricks.enable = true; + }; + environment.systemPackages = with pkgs; [ steamtinkerlaunch ]; + } + + (lib.mkIf cfg.steam.enableSls { + environment.systemPackages = [ + inputs.sls-steam.packages.${pkgs.stdenv.hostPlatform.system}.wrapped + ]; + home-manager.users.${username} = { + xdg.desktopEntries = { + steam = { + name = "Steam"; + comment = "Library modified Steam client"; + exec = "${ + lib.getExe' inputs.sls-steam.packages.${pkgs.stdenv.hostPlatform.system}.wrapped "SLSsteam" + } %U"; + icon = "steam"; + terminal = false; + type = "Application"; + categories = [ + "Game" + "Utility" + ]; + mimeType = [ "x-scheme-handler/steamcmd" ]; + }; + }; + }; + }) + ] + )) + + # --- VR SUPPORT --- + (lib.mkIf cfg.vr.enable { + services.wivrn = { + enable = true; + openFirewall = true; + highPriority = true; + steam.importOXRRuntimes = true; + # defaultRuntime = true; + }; + environment.systemPackages = [ pkgs.android-tools ]; + users.users.${username}.extraGroups = [ "adbusers" ]; + }) + ]; +} diff --git a/modules/greet.nix b/modules/greet.nix new file mode 100644 index 0000000..1c01b68 --- /dev/null +++ b/modules/greet.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.core.greet; +in +{ + options.os.core.greet.enable = lib.mkEnableOption "enables greetd daemon with tuigreet"; + config = lib.mkIf cfg.enable { + services.greetd = { + enable = true; + settings = { + default_session = { + user = "greeter"; + command = lib.concatStringsSep " " [ + "${pkgs.tuigreet}/bin/tuigreet" + "--sessions ${config.services.displayManager.sessionData.desktops}/share/xsessions:${config.services.displayManager.sessionData.desktops}/share/wayland-sessions" + "--remember" + "--remember-user-session" + "--asterisks" + "--greeting 'Welcome to NixOS!'" + "--time" + ]; + }; + }; + }; + security.pam.services.greetd.enableGnomeKeyring = true; + }; +} diff --git a/modules/i2p.nix b/modules/i2p.nix new file mode 100644 index 0000000..5e36c20 --- /dev/null +++ b/modules/i2p.nix @@ -0,0 +1,81 @@ +{ + config, + lib, + masterDomain, + securityTemplates, + ... +}: +let + cfg = config.os.srv.i2p; +in +{ + options.os.srv.i2p = { + enable = lib.mkEnableOption "enables a flexible, polymorphic i2pd deployment profile"; + + mode = lib.mkOption { + type = lib.types.enum [ + "server" + "client" + ]; + default = "client"; + description = ""; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + services.i2pd = { + enable = true; + enableIPv6 = true; + reseed.verify = true; + + yggdrasil.enable = true; + + proto = { + http.enable = true; + httpProxy.enable = true; + socksProxy = { + enable = true; + outproxyEnable = true; + }; + sam.enable = true; + i2pControl.enable = true; + }; + }; + } + + (lib.mkIf (cfg.mode == "server") { + services.i2pd = { + bandwidth = 4096; + + ntcp2.published = true; + ssu2.published = true; + + #TODO add address + yggdrasil.address = ""; + }; + + os.cluster.nginxProxies."i2p.${masterDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${config.os.core.network.ips.relay-vm}:7070"; + extraConfig = securityTemplates.restrictToInternal; + }; + }; + }) + + (lib.mkIf (cfg.mode == "client") { + services.i2pd = { + bandwidth = 512; + + ntcp2.published = false; + ssu2.published = false; + + yggdrasil.address = ""; + }; + }) + ] + ); +} diff --git a/modules/localization.nix b/modules/localization.nix new file mode 100644 index 0000000..49933fa --- /dev/null +++ b/modules/localization.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: +let + cfg = config.os.core.locale; +in +{ + options.os.core.locale = { + enable = lib.mkEnableOption "system localization (timezone and language)"; + + timeZone = lib.mkOption { + type = lib.types.str; + default = "Europe/Warsaw"; + description = "the system timezone."; + }; + + format = lib.mkOption { + type = lib.types.str; + default = "pl_PL.UTF-8"; + description = "the locale used for numbers, time, and measurements."; + }; + }; + config = lib.mkIf cfg.enable { + time.timeZone = cfg.timeZone; + + i18n = { + defaultLocale = "en_US.UTF-8"; + + extraLocaleSettings = { + LC_TIME = cfg.format; + LC_NUMERIC = cfg.format; + LC_MONETARY = cfg.format; + LC_PAPER = cfg.format; + LC_MEASUREMENT = cfg.format; + LC_COLLATE = cfg.format; + LC_NAME = cfg.format; + LC_ADDRESS = cfg.format; + LC_TELEPHONE = cfg.format; + LC_IDENTIFICATION = cfg.format; + }; + }; + }; +} diff --git a/modules/memory.nix b/modules/memory.nix new file mode 100644 index 0000000..b20ec8a --- /dev/null +++ b/modules/memory.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: +let + cfg = config.os.core.memory; +in +{ + options.os.core.memory = { + zram = { + enable = lib.mkEnableOption "enables zram compression"; + percent = lib.mkOption { + type = lib.types.int; + default = 25; + }; + }; + + swapfile = { + enable = lib.mkEnableOption "enables a swapfile"; + size = lib.mkOption { + type = lib.types.int; + default = 8; + }; + }; + }; + config = lib.mkMerge [ + (lib.mkIf cfg.zram.enable { + zramSwap = { + enable = true; + algorithm = "zstd"; + memoryPercent = cfg.zram.percent; + priority = 100; + }; + }) + + (lib.mkIf cfg.swapfile.enable { + swapDevices = [ { + device = "/.swapvol/swapfile"; + size = cfg.swapfile.size * 1024; + priority = 0; + } ]; + }) + ]; +} diff --git a/modules/monero.nix b/modules/monero.nix new file mode 100644 index 0000000..eb21abc --- /dev/null +++ b/modules/monero.nix @@ -0,0 +1,124 @@ +{ + config, + lib, + pkgs, + masterDomain, + securityTemplates, + ... +}: +let + cfg = config.os.srv.monero; + banlist1 = pkgs.fetchurl { + url = "https://gui.xmr.pm/files/block.txt"; + hash = "sha256-0ik4d66js6wvrvciza0li6bsajj8dvxsqlf09hcz7hg610szdxcw"; + }; + banlist2 = pkgs.fetchurl { + url = "https://raw.githubusercontent.com/Boog900/monero-ban-list/refs/heads/main/ban_list.txt"; + hash = "sh256-01z4wm2mp4z1wq2wdkrm66j50gwk3r82m2ml4n0pwjcbajxkdc87"; + }; + + combinedBanlist = pkgs.writeText "combined-monero-banlist.txt" '' + ${builtins.readFile banlist1} + ${builtins.readFile banlist2} + ''; +in +{ + options.os.srv.monero = { + wallet.enable = lib.mkEnableOption "enables the monero wallet"; + service = { + enable = lib.mkEnableOption "enables hosting a monero node"; + public = lib.mkEnableOption "makes the RPC node public (disables authentication for general wallet syncing)"; + tor.enable = lib.mkEnableOption "exposes monero RPC via Tor Onion Service"; + i2p.enable = lib.mkEnableOption "exposes monero RPC via I2P Tunnel"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.wallet.enable { + environment.systemPackages = [ pkgs.monero-cli ]; + }) + (lib.mkIf cfg.service.enable { + assertions = [ + { + assertion = if (!cfg.service.public) then config.os.srv.sops.enable else true; + message = "sops must be enabled"; + } + { + assertion = if cfg.service.tor.enable then config.os.srv.tor.enable else true; + message = "tor must be enabled"; + } + { + assertion = if cfg.service.i2p.enable then config.os.srv.i2p.enable else true; + message = "i2p must be enabled"; + } + ]; + + sops.secrets."monero/rpc-password" = { + owner = "monero"; + restartUnits = [ "monero.service" ]; + }; + + services.monero = { + enable = true; + prune = true; + banlist = combinedBanlist; + + limits = { + upload = 1250; + download = 12500; + threads = 8; + }; + + rpc = { + address = "0.0.0.0"; + } + // lib.optionalAttrs (!cfg.service.public) { + restricted = true; + user = "admin"; + password = config.sops.secrets."monero/rpc-password".path; + }; + + }; + + services.tor = lib.mkIf cfg.service.tor.enable { + # onionServices."xmr-rpc" = { + # to = [ + # { + # port = 18081; + # address = config.os.core.network.ips.relay-vm; + # } + # ]; + # }; + }; + + services.i2pd = lib.mkIf cfg.service.i2p.enable { + # tunnels.server."xmr-rpc" = { + # port = 18081; + # address = config.os.core.network.ips.relay-vm; + # keys = "xmr-rpc-key.dat"; + # inbound.length = 3; + # outbound.length = 3; + # }; + }; + + os.cluster.nginxProxies."xmr.${masterDomain}" = { + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyPass = "http://${config.os.core.network.ips.relay-vm}:18081"; + extraConfig = '' + proxy_read_timeout 600s; + proxy_send_timeout 600s; + client_max_body_size 50m; + + ${securityTemplates.restrictToInternal} + ''; + }; + }; + + # Left open for P2P syncing + networking.firewall.allowedTCPPorts = [ 18080 ]; + }) + ]; +} diff --git a/modules/networking.nix b/modules/networking.nix new file mode 100644 index 0000000..9e4c329 --- /dev/null +++ b/modules/networking.nix @@ -0,0 +1,186 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.core.network; +in +{ + options.os.core.network = { + enable = lib.mkEnableOption "system-wide networking setup"; + enableFirewall = lib.mkEnableOption "integrated zero-trust nftables firewall layers"; + + isVM = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Set to true if this configuration is running inside a guest VM. Set to false for the bare-metal host."; + }; + + ips = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { + bare-metal = "10.0.0.2"; + opnsense-vm = "10.0.0.1"; + gateway-vm = "10.0.0.3"; + auth-vm = "10.0.0.4"; + database-vm = "10.0.0.5"; + monitor-vm = "10.0.0.6"; + media-vm = "10.0.0.7"; + torrent-vm = "10.0.0.8"; + storage-vm = "10.0.0.9"; + web-vm = "10.0.0.10"; + comm-vm = "10.0.0.11"; + mail-vm = "10.0.0.12"; + relay-vm = "10.0.0.13"; + gameserver-vm = "10.0.0.14"; + }; + description = "Central registry of static IP allocations for the cluster."; + }; + + profile = lib.mkOption { + type = lib.types.enum [ + "client" + "server" + ]; + default = "client"; + description = "Which networking profile configuration to apply"; + }; + + lan = lib.mkOption { + description = "Physical Home Local Area Network configuration parameters."; + type = lib.types.submodule { + options = { + ip = lib.mkOption { + type = lib.types.str; + default = "10.0.0.2"; + description = "The local static or leased IP assigned to this machine on the home network."; + }; + range = lib.mkOption { + type = lib.types.str; + default = "10.0.0.0/24"; + description = "The broader subnet block representing the physical home network."; + }; + }; + }; + }; + + wg = lib.mkOption { + description = "Standard WireGuard VPN tunnel configuration parameters."; + type = lib.types.submodule { + options = { + ip = lib.mkOption { + type = lib.types.str; + default = "10.3.0.1"; + description = "The explicit tunnel IP address assigned to this machine's WireGuard interface."; + }; + range = lib.mkOption { + type = lib.types.str; + default = "10.3.0.0/24"; + description = "The total addressable IP space assigned to the WireGuard network pool."; + }; + }; + }; + }; + + hs = lib.mkOption { + description = "Headscale mesh overlay network configuration parameters."; + type = lib.types.submodule { + options = { + ip = lib.mkOption { + type = lib.types.str; + default = "10.4.0.1"; + description = "The explicit mesh network IP address assigned to this machine via Headscale."; + }; + range = lib.mkOption { + type = lib.types.str; + default = "10.4.0.0/24"; + description = "The full mesh overlay allocation subnet block."; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + services.resolved.enable = true; + } + + (lib.mkIf (cfg.profile == "client") { + networking.networkmanager = { + enable = true; + dns = "systemd-resolved"; + wifi.macAddress = "random"; + wifi.backend = "iwd"; + ethernet.macAddress = "random"; + }; + + systemd.services."NetworkManager-wait-online".enable = false; + + environment.systemPackages = [ + pkgs.impala + ]; + }) + + (lib.mkIf (cfg.profile == "client" && cfg.enableFirewall) { + networking = { + firewall.enable = true; + nftables.enable = true; + }; + }) + + (lib.mkIf (cfg.profile == "server") { + networking = { + useNetworkd = true; + useDHCP = false; + }; + systemd.network = { + enable = true; + wait-online.enable = lib.mkIf (!cfg.isVM) false; + + netdevs = lib.mkIf (!cfg.isVM) { + "10-br-srv" = { + netdevConfig = { + Name = "br-srv"; + Kind = "bridge"; + }; + }; + }; + networks."20-host-management" = { + matchConfig.Name = if cfg.isVM then "eth0" else "br-srv"; + address = [ "${cfg.lan.ip}/24" ]; + gateway = [ cfg.ips.router ]; + networkConfig.LinkLocalAddressing = "no"; + }; + }; + boot.kernel.sysctl = { + "net.ipv4.ip_nonlocal_bind" = 1; + "net.ipv4.ip_forward" = 1; + }; + }) + (lib.mkIf + ( + cfg.profile == "server" + && cfg.enableFirewall + && cfg.isVM + && config.networking.hostName != "vm2-gateway" + ) + { + networking.nftables.enable = true; + networking.firewall = { + enable = true; + extraCommands = '' + nft add table ip nat 2>/dev/null || true + nft flush table ip nat + nft add chain ip nat PREROUTING { type nat hook prerouting priority dstnat \; } + nft add rule ip nat PREROUTING ip saddr ${cfg.ips.vm2-gateway} ip daddr ${cfg.lan.ip} redirect + ''; + }; + } + ) + ] + ); +} diff --git a/modules/niri.nix b/modules/niri.nix new file mode 100644 index 0000000..58d27af --- /dev/null +++ b/modules/niri.nix @@ -0,0 +1,28 @@ +{ + inputs, + config, + lib, + username, + pkgs, + ... +}: +let + cfg = config.os.wm.niri; +in +{ + imports = [ inputs.niri.nixosModules.niri ]; + + options.os.wm.niri.enable = lib.mkEnableOption "Niri"; + + config = lib.mkIf cfg.enable { + nixpkgs.overlays = [ inputs.niri.overlays.niri ]; + + programs.niri = { + enable = true; + package = pkgs.niri-unstable; + }; + + os.srv.compat.enable = true; + home-manager.users.${username}.hm.env.niri.enable = true; + }; +} diff --git a/modules/nix-helper.nix b/modules/nix-helper.nix new file mode 100644 index 0000000..5e5e133 --- /dev/null +++ b/modules/nix-helper.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + username, + ... +}: +let + cfg = config.os.srv.nix-helper; +in +{ + options.os.srv.nix-helper.enable = lib.mkEnableOption "enables nix-helper"; + config = lib.mkIf cfg.enable { + nix.settings = { + trusted-users = [ + "root" + "${username}" + ]; + experimental-features = [ + "nix-command" + "flakes" + ]; + }; + + programs.nh = { + enable = true; + flake = "/etc/nixos"; + clean.extraArgs = "--keep 5"; + }; + + environment.sessionVariables = { + NH_OS_FLAKE = "/etc/nixos"; + }; + + environment.systemPackages = with pkgs; [ + nix-output-monitor + nvd + ]; + }; +} diff --git a/modules/omnisearch.nix b/modules/omnisearch.nix new file mode 100644 index 0000000..ac36184 --- /dev/null +++ b/modules/omnisearch.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + inputs, + masterDomain, + templates, + ... +}: +let + cfg = config.os.srv.omnisearch; +in +{ + imports = [ inputs.omnisearch.nixosModules.default ]; + + options.os.srv.omnisearch = { + enable = lib.mkEnableOption "enables omnisearch tracking infrastructure"; + + role = lib.mkOption { + type = lib.types.enum [ + "server" + "standalone" + ]; + default = "standalone"; + description = "Designates the deployment method"; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + services.omnisearch = { + enable = true; + settings = { + server = { + host = "127.0.0.1"; + port = 8087; + locale = "en"; + domain = if cfg.role == "server" then "https://search.${masterDomain}" else "http://localhost:8087"; + }; + proxy = { + max_retries = 3; + randomize_username = true; + randomize_password = true; + }; + cache = { + dir = "/var/cache/omnisearch"; + ttl_search = 1800; + ttl_infobox = 86400; + }; + }; + }; + } + + (lib.mkIf (cfg.role == "server") { + assertions = [ + { + assertion = config.os.srv.nginx.enable; + message = "Required for proxying"; + } + ]; + services.nginx.virtualHosts."search.${masterDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:8087"; + proxyWebsockets = true; + extraConfig = templates.restrictToInternal; + }; + }; + }) + ] + ); +} diff --git a/modules/persistance.nix b/modules/persistance.nix new file mode 100644 index 0000000..89f3702 --- /dev/null +++ b/modules/persistance.nix @@ -0,0 +1,50 @@ +{ + config, + lib, + inputs, + ... +}: +let + cfg = config.os.srv.persistance; +in +{ + imports = [ inputs.impermanence.nixosModules.impermanence ]; + + options.os.srv.persistance.enable = lib.mkEnableOption "enables persistance drive maintnance"; + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + environment.persistence."/persist" = { + hideMounts = true; + directories = [ + "/var/lib/nixos" + "/var/lib/systemd" + "/var/lib/microvm" + ]; + files = [ + "/etc/machine-id" + ]; + }; + }) + (lib.mkIf (cfg.enable && config.os.srv.ssh.server.enable) { + environment.persistence."/persist" = { + files = [ + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + ]; + }; + }) + (lib.mkIf (cfg.enable && config.os.srv.crowdsec.agent.enable) { + environment.persistence."/persist" = lib.mkIf cfg.agent.enable { + hideMounts = true; + directories = [ + { + directory = "/var/lib/crowdsec"; + user = "crowdsec"; + group = "crowdsec"; + mode = "0750"; + } + ]; + }; + }) + ]; +} diff --git a/modules/power.nix b/modules/power.nix new file mode 100644 index 0000000..b3dbf91 --- /dev/null +++ b/modules/power.nix @@ -0,0 +1,54 @@ +{ + config, + lib, + ... +}: +let + cfg = config.os.core.power; +in +{ + options.os.core.power = { + enable = lib.mkEnableOption "enables power management"; + mode = lib.mkOption { + type = lib.types.enum [ + "amd" + "intel" + "none" + ]; + default = "none"; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + powerManagement.powertop.enable = true; + boot.kernelParams = [ "nvme_core.default_ps_max_latency_us=0" ]; + } + + (lib.mkIf (cfg.mode == "amd") { + services.power-profiles-daemon.enable = true; + boot.kernelParams = [ "amd_pstate=active" ]; + }) + + (lib.mkIf (cfg.mode == "intel") { + services = { + power-profiles-daemon.enable = false; + + thermald.enable = true; + tlp = { + enable = true; + settings = { + START_CHARGE_THRESH_BAT0 = 75; + STOP_CHARGE_THRESH_BAT0 = 80; + START_CHARGE_THRESH_BAT1 = 75; + STOP_CHARGE_THRESH_BAT1 = 80; + CPU_SCALING_GOVERNOR_ON_AC = "performance"; + CPU_SCALING_GOVERNOR_ON_BAT = "powersave"; + }; + }; + }; + }) + ] + ); +} diff --git a/modules/security.nix b/modules/security.nix new file mode 100644 index 0000000..33aa919 --- /dev/null +++ b/modules/security.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + pkgs, + username, + ... +}: +let + cfg = config.os.core.security; +in +{ + options.os.core.security = { + enable = lib.mkEnableOption "core security services"; + antivirus.enable = lib.mkEnableOption "enables clamav antivirus"; + sandboxing.enable = lib.mkEnableOption "enables sandboxing stuff"; + }; + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + security = { + polkit.enable = true; + rtkit.enable = true; + doas = { + enable = true; + extraRules = [ + { + users = [ username ]; + keepEnv = true; + persist = true; + } + ]; + }; + # sudo.enable = false; + pam.services = { + swaylock = { }; + login.enableGnomeKeyring = true; + }; + }; + # environment.systemPackages = [ pkgs.doas-sudo-shim ]; + } + (lib.mkIf cfg.sandboxing.enable { + security.apparmor = { + enable = true; + enableCache = true; + killUnconfinedConfinables = true; + packages = with pkgs; [ + apparmor-profiles + roddhjav-apparmor-rules + ]; + }; + services.dbus.apparmor = "enabled"; + specialisation.no-apparmor.configuration.security.apparmor.enable = lib.mkForce false; + + programs.firejail.enable = true; + environment.systemPackages = with pkgs; [ + apparmor-utils + apparmor-parser + apparmor-bin-utils + ]; + }) + { + services.gnome.gnome-keyring.enable = true; + + environment.systemPackages = with pkgs; [ + veracrypt + gocryptfs + keepassxc + ]; + } + ] + ); +} diff --git a/modules/sops.nix b/modules/sops.nix new file mode 100644 index 0000000..3ca2d16 --- /dev/null +++ b/modules/sops.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + pkgs, + inputs, + username, + ... +}: +let + cfg = config.os.srv.sops; +in +{ + imports = [ inputs.sops-nix.nixosModules.sops ]; + + options.os.srv.sops.enable = lib.mkEnableOption "enables sops-nix"; + config = lib.mkIf cfg.enable { + sops = { + defaultSopsFile = ../../secrets/common.yaml; + defaultSopsFormat = "yaml"; + age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; + + secrets = { + # "syncthing/gui_password".owner = username; + "syncthing/encryption/keepass".owner = username; + "syncthing/encryption/sync".owner = username; + "obs/websocket_password".owner = username; + }; + }; + + environment.systemPackages = with pkgs; [ + sops + age + ssh-to-age + ]; + }; +} diff --git a/modules/ssh.nix b/modules/ssh.nix new file mode 100644 index 0000000..63b2034 --- /dev/null +++ b/modules/ssh.nix @@ -0,0 +1,95 @@ +{ + config, + lib, + username, + ... +}: +let + cfg = config.os.srv.ssh; + keys.main = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC610CJfgc3yII7MpLVqzEzQGa8Tsm+dih+CTXHXTnv4"; +in +{ + options.os.srv.ssh = { + server.enable = lib.mkEnableOption "enables the ssh server module"; + client = { + enable = lib.mkEnableOption "enables the ssh client module"; + createAliases = lib.mkEnableOption "enables system-wide SSH shortcuts"; + }; + enableSigning = lib.mkEnableOption "enables signing git commits with ssh keys"; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.server.enable { + services.openssh = { + enable = true; + + listenAddresses = [ + { + addr = "127.0.0.1"; + port = 22; + } + ] + ++ lib.optional (config.os.core.network ? lan.ip) { + addr = config.os.core.network.lan.ip; + port = 22; + } + ++ lib.optional (config.os.core.network ? wg.ip) { + addr = config.os.core.network.wg.ip; + port = 22; + } + ++ lib.optional (config.os.core.network ? hs.ip) { + addr = config.os.core.network.hs.ip; + port = 22; + }; + hostKeys = [ + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + ]; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + PermitRootLogin = "no"; + + PubkeyAcceptedAlgorithms = "ssh-ed25519"; + }; + }; + + users.users = ( + lib.optionalAttrs (username != "" && username != null) { + ${username}.openssh.authorizedKeys.keys = [ + "${keys.main} adikro@disroot.org" + ]; + } + ); + }) + + (lib.mkIf cfg.client.enable { + programs.ssh.startAgent = true; + services.gnome.gcr-ssh-agent.enable = false; + }) + + (lib.mkIf (cfg.client.enable && cfg.client.createAliases) { + # TODO use hjem + programs.ssh.extraConfig = '' + Host github.com codeberg.org + IdentityFile /home/${username}/.ssh/main_id_ed25519.pub + IdentitiesOnly yes + User git + + Host oci + HostName 130.162.223.123 + User opc + ''; + systemd.tmpfiles.rules = [ + "d /home/${username}/.ssh 0700 ${username} users - -" + "f /home/${username}/.ssh/main_id_ed25519.pub 0644 ${username} users - ${keys.main}" + ]; + }) + + (lib.mkIf cfg.enableSigning { + environment.etc."ssh/allowed_signers".text = "adikro@disroot.org ${keys.main}"; + }) + ]; +} diff --git a/modules/storage.nix b/modules/storage.nix new file mode 100644 index 0000000..8527bac --- /dev/null +++ b/modules/storage.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: +let + cfg = config.os.core.storage; +in +{ + options.os.core.storage = { + enable = lib.mkEnableOption "enables storage management"; + }; + config = lib.mkIf cfg.enable { + nix.settings.auto-optimise-store = true; + services.fstrim.enable = true; + services.btrfs.autoScrub = { + enable = true; + fileSystems = [ "/" ]; + }; + boot.tmp = { + useTmpfs = true; + tmpfsSize = "50%"; + }; + }; +} diff --git a/modules/syncthing.nix b/modules/syncthing.nix new file mode 100644 index 0000000..0c5e53e --- /dev/null +++ b/modules/syncthing.nix @@ -0,0 +1,136 @@ +{ + config, + lib, + username, + ... +}: +let + cfg = config.os.srv.syncthing; + allFolders = { + "openmw-config" = { + path = "/home/${username}/.config/openmw"; + id = "openmw-config"; + devices = [ "oci" ]; + versioning = { + type = "simple"; + params.keep = "3"; + }; + ignorePatterns = [ + "settings.cfg" + "*.log" + ]; + }; + + "openmw-mods" = { + path = "/home/${username}/games/openmw"; + id = "openmw-mods"; + devices = [ "oci" ]; + versioning = { + type = "trashcan"; + params.cleanoutDays = "7"; + }; + }; + + "game-saves" = { + path = "/home/${username}/.saves"; + id = "game-saves"; + devices = [ "oci" ]; + versioning = { + type = "staggered"; + params = { + cleanInterval = "3600"; + maxAge = "2592000"; + }; + }; + }; + + "keepass" = { + path = "/home/${username}/.keepass"; + id = "keepass"; + devices = [ + { + name = "oci"; + encryptionPasswordFile = config.sops.secrets."syncthing/encryption/keepass".path; + } + ]; + versioning = { + type = "staggered"; + params = { + cleanInterval = "3600"; + maxAge = "31536000"; + }; + }; + }; + + "sync" = { + path = "/home/${username}/sync"; + id = "sync"; + devices = [ + { + name = "oci"; + encryptionPasswordFile = config.sops.secrets."syncthing/encryption/sync".path; + } + ]; + versioning = { + type = "staggered"; + params = { + cleanInterval = "3600"; + maxAge = "15552000"; + }; + }; + }; + + "music" = { + path = "/storage/music"; + id = "music"; + devices = [ "oci" ]; + versioning = { + type = "trashcan"; + params.cleanoutDays = "14"; + }; + }; + }; + activeFoldersSet = lib.filterAttrs (name: _: builtins.elem name cfg.activeFolders) allFolders; + + syncDirs = lib.mapAttrsToList (_: folder: folder.path) activeFoldersSet; +in +{ + options.os.srv.syncthing = { + enable = lib.mkEnableOption "enables syncthing syncing"; + + activeFolders = lib.mkOption { + type = lib.types.listOf ( + lib.types.enum [ + "openmw-config" + "openmw-mods" + "game-saves" + "keepass" + "sync" + "music" + ] + ); + default = [ + "keepass" + "sync" + ]; + description = "List of Syncthing folders to enable and sync on this specific machine."; + }; + }; + config = lib.mkIf cfg.enable { + systemd.tmpfiles.rules = map (path: "d ${path} 0755 ${username} users -") syncDirs; + + services.syncthing = { + enable = true; + user = username; + dataDir = "/home/${username}/.local/share/syncthing"; + configDir = "/home/${username}/.config/syncthing"; + # guiPasswordFile = config.sops.secrets."syncthing/gui_password".path; + + settings = { + devices."oci".id = "DQXGVDC-KGPM6RK-5NDEBJJ-R7PEWYZ-N6Z3WFZ-TSVJG5X-235SHG4-4BEJNQJ"; + + folders = activeFoldersSet; + }; + }; + }; +} diff --git a/modules/tor.nix b/modules/tor.nix new file mode 100644 index 0000000..8777fba --- /dev/null +++ b/modules/tor.nix @@ -0,0 +1,31 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.srv.tor; +in +{ + options.os.srv.tor = { + enable = lib.mkEnableOption "enables tor services"; + enableBrowser = lib.mkEnableOption "enables the tor browser"; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + services.tor = { + enable = true; + client = { + enable = true; + dns.enable = true; + transparentProxy.enable = true; + }; + }; + }) + (lib.mkIf cfg.enableBrowser { + environment.systemPackages = [ pkgs.tor-browser ]; + }) + ]; +} diff --git a/modules/users.nix b/modules/users.nix new file mode 100644 index 0000000..ff45a99 --- /dev/null +++ b/modules/users.nix @@ -0,0 +1,54 @@ +{ + config, + lib, + pkgs, + username, + ... +}: +let + cfg = config.os.core.users; +in +{ + options.os.core.users.enable = lib.mkEnableOption "enables user accounts"; + config = lib.mkIf cfg.enable { + programs.fish.enable = true; + assertions = [ + { + assertion = config.os.srv.sops.enable; + message = "required for storing the ssh key"; + } + ]; + sops.secrets = { + "users/root_password".neededForUsers = true; + "users/main_password".neededForUsers = true; + # "users/opc_password".neededForUsers = true; + }; + users = { + mutableUsers = false; + + users = { + "${username}" = { + isNormalUser = true; + hashedPasswordFile = config.sops.secrets."users/main_password".path; + shell = pkgs.fish; + extraGroups = lib.mkMerge [ + [ + "wheel" + "input" + "uinput" + ] + + (lib.mkIf (config.os.core.drivers.graphics.enable or false) [ + "video" + "render" + ]) + (lib.mkIf (config.os.core.network.enable or false) [ "networkmanager" ]) + (lib.mkIf (config.os.srv.virtualization.kvm.enable or false) [ "libvirtd" ]) + (lib.mkIf (config.os.srv.docker.enable or false) [ "docker" ]) + ]; + }; + root.hashedPasswordFile = config.sops.secrets."users/root_password".path; + }; + }; + }; +} diff --git a/modules/virtualization.nix b/modules/virtualization.nix new file mode 100644 index 0000000..8ff9f3f --- /dev/null +++ b/modules/virtualization.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.os.srv.virtualization; +in +{ + options.os.srv.virtualization = { + kvm.enable = lib.mkEnableOption "KVM/QEMU virtualization with Virt-Manager"; + waydroid.enable = lib.mkEnableOption "Waydroid Container Virtualization"; + }; + config = lib.mkMerge [ + (lib.mkIf cfg.kvm.enable { + virtualisation.libvirtd = { + enable = true; + qemu.package = pkgs.qemu_kvm; + qemu.swtpm.enable = true; + }; + systemd.services.libvirt-guests.enable = false; + programs.virt-manager.enable = true; + + boot.initrd.kernelModules = + (lib.optional (config.os.core.drivers.cpu == "amd") "kvm-amd") + ++ (lib.optional (config.os.core.drivers.cpu == "intel") "kvm-intel"); + }) + (lib.mkIf cfg.waydroid.enable { + virtualisation.waydroid = { + enable = true; + package = pkgs.waydroid-nftables; + }; + + environment.systemPackages = with pkgs; [ + waydroid-helper + ]; + }) + ]; +} |
