{ pkgs, config, lib, ... }: with lib; let cfg = config.common.linux; # Modules modules = { adb = { config, ... }: mkIf config.common.linux.enable { services.udev.packages = with pkgs; [ android-udev-rules ]; programs.adb.enable = true; users.users.${config.common.linux.username}.extraGroups = [ "adbusers" ]; }; ios = { config, pkgs, ... }: mkIf config.common.linux.enable { services.avahi.enable = true; services.usbmuxd.enable = true; services.usbmuxd.package = pkgs.usbmuxd2; environment.systemPackages = with pkgs; [ libimobiledevice ifuse ]; users.users.${config.common.linux.username}.extraGroups = [ config.services.usbmuxd.group ]; systemd.network.networks."05-ios-tethering" = { matchConfig.Driver = "ipheth"; networkConfig.DHCP = "yes"; linkConfig.RequiredForOnline = "no"; }; }; accounts = { pkgs, ... }: mkIf (config.common.linux.enable && !pkgs.stdenv.isAarch64) { environment.systemPackages = with pkgs.gnome; [ pkgs.glib gnome-control-center ]; services.accounts-daemon.enable = true; services.gnome.gnome-online-accounts.enable = true; # programs.evolution.enable = true; # programs.evolution.plugins = with pkgs; [ evolution-ews ]; # services.gnome.evolution-data-server.enable = true; # services.gnome.evolution-data-server.plugins = with pkgs; [ evolution-ews ]; }; wlr = { ... }: mkIf config.common.linux.enable { # swaync disable notifications on screencast xdg.portal.wlr.settings.screencast = { exec_before = ''which swaync-client && swaync-client --inhibitor-add "xdg-desktop-portal-wlr" || true''; exec_after = ''which swaync-client && swaync-client --inhibitor-remove "xdg-desktop-portal-wlr" || true''; }; }; logitech = { pkgs, ... }: mkIf cfg.enable { services.ratbagd.enable = true; environment.systemPackages = with pkgs; [ piper ]; }; kwallet = { pkgs, lib, ... }: mkIf cfg.enable { environment.systemPackages = [ pkgs.kdePackages.kwallet ]; services.dbus.packages = [ pkgs.kdePackages.kwallet ]; xdg.portal = { extraPortals = [ pkgs.kdePackages.kwallet ]; }; }; virtualisation = { pkgs, ... }: mkIf cfg.enable { virtualisation.podman = { enable = true; dockerCompat = true; defaultNetwork.settings.dns_enabled = true; }; virtualisation.oci-containers.backend = "podman"; virtualisation.virtualbox.host.enable = false; users.extraGroups.vboxusers.members = [ cfg.username ]; }; }; rt-audio = { pkgs, ... }: mkIf cfg.enable { services.pipewire.lowLatency = { # enable this module enable = true; # defaults (no need to be set unless modified) quantum = 32; rate = 48000; }; security.rtkit.enable = true; # Real time configurations boot.kernel.sysctl = { "vm.swappiness" = 10; "fs.inotify.max_user_watches" = 524288; }; security.pam.loginLimits = [ { domain = "@audio"; item = "rtprio"; type = "-"; value = "90"; } { domain = "@audio"; item = "memlock"; type = "-"; value = "unlimited"; } ]; }; in { imports = with modules; [ adb ios wlr logitech kwallet virtualisation accounts rt-audio ]; options.common.linux = { enable = mkOption { type = types.bool; description = "Enable the common settings for Linux personal machines"; default = pkgs.stdenv.isLinux; }; luksDevices = mkOption { type = types.attrsOf types.str; description = "A mapping from device mount name to its path (/dev/disk/...) to be mounted on boot"; default = { }; }; networking = { hostname = mkOption { type = types.str; description = "Host name for your machine"; }; dnsServers = mkOption { type = types.listOf types.str; description = "DNS server list"; default = [ "1.1.1.1" "2606:4700:4700:1111" ]; }; networks = mkOption { type = types.attrsOf (types.submodule { options.match = mkOption { type = types.str; description = "The interface name to match"; }; options.isRequired = mkOption { type = types.bool; description = "Require this interface to be connected for network-online.target"; default = false; }; }); description = "Network configuration"; default = { default = { match = "*"; }; }; }; }; username = mkOption { type = types.str; description = "The linux username"; default = "nki"; }; }; config = mkIf cfg.enable { ## Boot Configuration # Set kernel version to latest boot.kernelPackages = mkDefault pkgs.linuxPackages_latest; # Use the systemd-boot EFI boot loader. boot = { loader.timeout = 60; loader.systemd-boot.enable = true; loader.efi.canTouchEfiVariables = true; supportedFilesystems.ntfs = true; }; boot.initrd.systemd.enable = builtins.length (builtins.attrNames (cfg.luksDevices)) > 0; # LUKS devices boot.initrd.luks.devices = builtins.mapAttrs (name: path: { device = path; preLVM = true; allowDiscards = true; crypttabExtraOpts = [ "tpm2-device=auto" "fido2-device=auto" ]; }) cfg.luksDevices; ## Hardware-related # Firmware stuff services.fwupd.enable = true; # Enable sound. services.pipewire = { enable = true; # alsa is optional alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; }; # udev configurations services.udev.packages = with pkgs; [ qmk-udev-rules # For keyboards ]; # udisks services.udisks2.enable = true; # Bluetooth: just enable hardware.bluetooth.enable = true; hardware.bluetooth.package = pkgs.bluez5-experimental; # Why do we need experimental...? hardware.bluetooth.settings.General.Experimental = true; services.blueman.enable = true; # For a GUI # ZRAM zramSwap.enable = true; ## Users users.users.${cfg.username} = { isNormalUser = true; uid = 1000; extraGroups = [ "wheel" # Enable ‘sudo’ for the user. "plugdev" # Enable openrazer-daemon privileges "audio" ]; shell = pkgs.fish; }; nix.settings.trusted-users = [ "root" cfg.username ]; ## Network configuration systemd.network.enable = true; networking.dhcpcd.enable = lib.mkForce false; networking.useDHCP = false; networking.useNetworkd = true; systemd.network.wait-online.enable = false; networking.hostName = cfg.networking.hostname; networking.wireless.iwd.enable = true; networking.wireless.iwd.settings.General.EnableNetworkConfiguration = true; systemd.network.networks = builtins.mapAttrs (name: cfg: { matchConfig.Name = cfg.match; networkConfig.DHCP = "yes"; linkConfig.RequiredForOnline = if cfg.isRequired then "yes" else "no"; }) cfg.networking.networks; # Leave DNS to systemd-resolved services.resolved.enable = true; services.resolved.domains = cfg.networking.dnsServers; services.resolved.fallbackDns = cfg.networking.dnsServers; # Firewall: only open to SSH now networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedUDPPorts = [ 22 ]; # Enable tailscale services.tailscale.enable = true; ## Time and Region time.timeZone = "Europe/Zurich"; # Select internationalisation properties. console.keyMap = "jp106"; # Console key layout i18n.defaultLocale = "ja_JP.UTF-8"; # Input methods (only fcitx5 works reliably on Wayland) i18n.inputMethod = { enabled = "fcitx5"; fcitx5.waylandFrontend = true; fcitx5.addons = with pkgs; [ fcitx5-mozc fcitx5-unikey fcitx5-gtk ]; }; # Default packages environment.systemPackages = with pkgs; [ kakoune # An editor wget # A simple fetcher ## System monitoring tools usbutils # lsusb and friends pciutils # lspci and friends psmisc # killall, pstree, ... lm_sensors # sensors ## Security stuff libsForQt5.qtkeychain ## Wayland kdePackages.qtwayland ]; # Add a reliable terminal programs.fish.enable = true; # programs.gnome-terminal.enable = true; # KDEConnect is just based programs.kdeconnect.enable = true; # Flatpaks are useful... sometimes... services.flatpak.enable = true; # DConf for GNOME configurations programs.dconf.enable = true; # Gaming! (not for ARM64) programs.steam.enable = !pkgs.stdenv.isAarch64; hardware.opengl.enable = true; hardware.opengl.driSupport32Bit = !pkgs.stdenv.isAarch64; # For 32 bit applications ## Services # OpenSSH so you can SSH to me services.openssh.enable = true; # PAM security.pam.services.login.enableKwallet = true; security.pam.services.lightdm.enableKwallet = true; security.pam.services.swaylock = { }; # Printers services.printing.enable = true; # Portals xdg.portal = { enable = true; wlr.enable = true; xdgOpenUsePortal = true; # gtk portal needed to make gtk apps happy extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde pkgs.xdg-desktop-portal-gtk ]; config.sway.default = [ "wlr" "kde" "kwallet" ]; }; # D-Bus services.dbus.packages = with pkgs; [ gcr ]; ## Environment environment.variables = { # Set default editor EDITOR = "kak"; VISUAL = "kak"; }; }; }