From 785564e69ed553abfad30c59b8a6deb5a42db045 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 9 Dec 2025 17:38:41 -0500 Subject: [PATCH] full refactor --- README.md | 111 +++++++++++++ boot.nix | 48 ------ flake.nix | 2 + hosts/boot.nix | 109 +++++++++++++ hosts/default.nix | 166 +++++++------------ hosts/nix-desktop.nix | 23 --- hosts/nix-laptop.nix | 36 ----- hosts/nix-surface.nix | 38 ----- hosts/types/nix-desktop.nix | 24 +++ hosts/types/nix-laptop.nix | 37 +++++ hosts/types/nix-surface.nix | 40 +++++ hosts/user-config.nix | 79 +++++++++ inventory.nix | 26 +++ sw.nix | 91 ----------- sw/default.nix | 69 ++++++++ sw/desktop/default.nix | 5 + sw/desktop/programs.nix | 29 ++++ sw/desktop/services.nix | 51 ++++++ sw/kiosk/default.nix | 6 + sw/kiosk/gsettings.nix | 52 ++++++ sw/kiosk/programs.nix | 22 +++ sw-kiosk.nix => sw/kiosk/services.nix | 220 ++++++++------------------ sw/nvim.nix | 15 ++ sw/python.nix | 22 +++ sw/theme.nix | 71 +++++++++ users.nix | 28 ++++ users/default.nix | 41 ----- users/engr-ugaif.nix | 78 --------- users/hdh20267.nix | 80 ---------- users/python.nix | 9 -- users/root.nix | 51 ------ 31 files changed, 925 insertions(+), 754 deletions(-) create mode 100644 README.md delete mode 100644 boot.nix create mode 100644 hosts/boot.nix delete mode 100644 hosts/nix-desktop.nix delete mode 100644 hosts/nix-laptop.nix delete mode 100644 hosts/nix-surface.nix create mode 100644 hosts/types/nix-desktop.nix create mode 100644 hosts/types/nix-laptop.nix create mode 100644 hosts/types/nix-surface.nix create mode 100644 hosts/user-config.nix create mode 100644 inventory.nix delete mode 100644 sw.nix create mode 100644 sw/default.nix create mode 100644 sw/desktop/default.nix create mode 100644 sw/desktop/programs.nix create mode 100644 sw/desktop/services.nix create mode 100644 sw/kiosk/default.nix create mode 100644 sw/kiosk/gsettings.nix create mode 100644 sw/kiosk/programs.nix rename sw-kiosk.nix => sw/kiosk/services.nix (57%) create mode 100644 sw/nvim.nix create mode 100644 sw/python.nix create mode 100644 sw/theme.nix create mode 100644 users.nix delete mode 100644 users/default.nix delete mode 100644 users/engr-ugaif.nix delete mode 100644 users/hdh20267.nix delete mode 100644 users/python.nix delete mode 100644 users/root.nix diff --git a/README.md b/README.md new file mode 100644 index 0000000..d25a0d3 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# UGA Innovation Factory - NixOS Systems + +This repository contains the NixOS configuration for the Innovation Factory's fleet of laptops, desktops, and surface tablets. + +## Repository Structure + +- **`flake.nix`**: The entry point for the configuration. +- **`inventory.nix`**: Defines the fleet inventory (host types, counts, and device-specific overrides). +- **`users.nix`**: Defines user accounts, passwords, and package sets. +- **`hosts/`**: Contains the logic for generating host configurations and hardware-specific types. +- **`sw/`**: Software modules (Desktop, Kiosk, Python, Neovim, etc.). + +## Quick Start + +### Updating the System + +The system includes a utility script `update-system` that handles rebuilding and switching configurations. It automatically detects if it is running on a Surface tablet and offloads the build to a more powerful host if necessary. + +To apply changes to the current system: + +```bash +update-system +``` + +This command pulls the latest configuration from GitHub and rebuilds the system. + +If your configuration uses external flakes (e.g., via `flakeUrl`), you may need to allow impure evaluation: + +```bash +update-system --impure +``` + +### Manual Rebuilds + +If you need to rebuild manually or target a specific host: + +```bash +# Local build +sudo nixos-rebuild switch --flake . + +# Build for a specific host +sudo nixos-rebuild switch --flake .#nix-laptop1 +``` + +### Updating Flake Inputs + +To update the lockfile (nixpkgs, home-manager versions, etc.): + +```bash +nix flake update +``` + +## Configuration Guide + +### Adding a New User + +1. Open `users.nix`. +2. Add a new entry to `modules.users.accounts`. +3. Generate a hashed password using `mkpasswd -m sha-512` (requires `whois` package or similar). +4. Commit and push. + +### Assigning Users to Hosts + +By default, only `root` and `engr-ugaif` are enabled. To enable a specific student user on a specific device: + +1. Open `inventory.nix`. +2. Locate the host type (e.g., `nix-laptop`). +3. Add or update the `devices` section for the specific index: + +```nix +nix-laptop = { + count = 2; + devices = { + "1" = { extraUsers = [ "student_username" ]; }; + }; +}; +``` + +### Using External Flakes for User Configuration + +Users can manage their own Home Manager configuration in a separate flake repository. To use this: + +1. Open `users.nix`. +2. In the user's configuration block, set the `flakeUrl` option: + +```nix +hdh20267 = { + # ... other settings ... + flakeUrl = "github:hdh20267/dotfiles"; +}; +``` + +The external flake must provide a `homeManagerModules.default` output. Note that using this feature may require running `update-system --impure` if the flake is not locked in the system's `flake.lock`. + +### Adding a New Host + +1. Open `inventory.nix`. +2. Increment the `count` for the relevant host type. +3. The new host will be named sequentially (e.g., `nix-laptop3`). + +## Development + +### Python Environment + +The system comes with `pixi` and `uv` for Python project management. It is recommended to use these tools for project-specific environments rather than installing global Python packages. + +```bash +pixi init my_project +cd my_project +pixi add pandas numpy +``` diff --git a/boot.nix b/boot.nix deleted file mode 100644 index d943e12..0000000 --- a/boot.nix +++ /dev/null @@ -1,48 +0,0 @@ -# Edit this configuration file to define what should be installed on -# your system. Help is available in the configuration.nix(5) man page -# and in the NixOS manual (accessible by running ‘nixos-help’). - -{ ... }: - -{ - # Bootloader. - boot = { - loader.systemd-boot.enable = true; - loader.efi.canTouchEfiVariables = true; - plymouth.enable = true; - - # Enable "Silent boot" - consoleLogLevel = 3; - initrd.verbose = false; - - # Hide the OS choice for bootloaders. - # It's still possible to open the bootloader list by pressing any key - # It will just not appear on screen unless a key is pressed - loader.timeout = 0; - }; - - # Set your time zone. - time.timeZone = "America/New_York"; - - # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; - - i18n.extraLocaleSettings = { - LC_ADDRESS = "en_US.UTF-8"; - LC_IDENTIFICATION = "en_US.UTF-8"; - LC_MEASUREMENT = "en_US.UTF-8"; - LC_MONETARY = "en_US.UTF-8"; - LC_NAME = "en_US.UTF-8"; - LC_NUMERIC = "en_US.UTF-8"; - LC_PAPER = "en_US.UTF-8"; - LC_TELEPHONE = "en_US.UTF-8"; - LC_TIME = "en_US.UTF-8"; - }; - - systemd.sleep.extraConfig = '' - SuspendState=freeze - HibernateDelaySec=2h - ''; - - system.stateVersion = "25.11"; # Did you read the comment? -} diff --git a/flake.nix b/flake.nix index e88605a..a671080 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,8 @@ lazyvim-nixvim.url = "github:azuwis/lazyvim-nixvim"; }; outputs = inputs@{ self, nixpkgs, nixpkgs-old-kernel, home-manager, disko, lazyvim-nixvim, nixos-hardware,... }: { + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-rfc-style; + nixosConfigurations = import ./hosts { inherit inputs; }; }; } diff --git a/hosts/boot.nix b/hosts/boot.nix new file mode 100644 index 0000000..767e150 --- /dev/null +++ b/hosts/boot.nix @@ -0,0 +1,109 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, lib, ... }: + +{ + options.host = { + filesystem = { + device = lib.mkOption { + type = lib.types.str; + description = "The main disk device to use for installation."; + }; + swapSize = lib.mkOption { + type = lib.types.str; + description = "The size of the swap partition."; + }; + }; + }; + + config = { + disko.enableConfig = true; + + disko.devices = { + disk.main = { + type = "disk"; + device = config.host.filesystem.device; + content = { + type = "gpt"; + partitions = { + ESP = { + name = "ESP"; + label = "BOOT"; + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + extraArgs = [ "-n" "BOOT" ]; + }; + }; + + swap = { + name = "swap"; + label = "swap"; + size = config.host.filesystem.swapSize; + content = { type = "swap"; }; + }; + + root = { + name = "root"; + label = "root"; + size = "100%"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + extraArgs = [ "-L" "ROOT" ]; + }; + }; + }; + }; + }; + }; + + # Bootloader. + boot = { + loader.systemd-boot.enable = true; + loader.efi.canTouchEfiVariables = true; + plymouth.enable = true; + + # Enable "Silent boot" + consoleLogLevel = 3; + initrd.verbose = false; + + # Hide the OS choice for bootloaders. + # It's still possible to open the bootloader list by pressing any key + # It will just not appear on screen unless a key is pressed + loader.timeout = 0; + }; + + # Set your time zone. + time.timeZone = "America/New_York"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + systemd.sleep.extraConfig = '' + SuspendState=freeze + HibernateDelaySec=2h + ''; + + system.stateVersion = "25.11"; # Did you read the comment? + }; +} diff --git a/hosts/default.nix b/hosts/default.nix index 0978cf5..ba82ec7 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,63 +1,32 @@ -{ inputs, ... }: +{ inputs, hosts ? import ../inventory.nix, ... }: let nixpkgs = inputs.nixpkgs; + lib = nixpkgs.lib; home-manager = inputs.home-manager; disko = inputs.disko; - lib = nixpkgs.lib; commonModules = [ - ../boot.nix - ../users + ./boot.nix + ./user-config.nix + ../users.nix + ../sw home-manager.nixosModules.home-manager disko.nixosModules.disko - ({ ... }: { - disko.enableConfig = true; - - disko.devices = { - disk.main = { - type = "disk"; - device = lib.mkDefault "/dev/nvme0n1"; - content = { - type = "gpt"; - partitions = { - ESP = { - name = "ESP"; - label = "BOOT"; - size = "1G"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "umask=0077" ]; - extraArgs = [ "-n" "BOOT" ]; - }; - }; - - swap = { - name = "swap"; - label = "swap"; - size = lib.mkDefault "34G"; - content = { type = "swap"; }; - }; - - root = { - name = "root"; - label = "root"; - size = "100%"; - content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; - extraArgs = [ "-L" "ROOT" ]; - }; - }; - }; - }; - }; + { + system.stateVersion = "25.11"; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # Automatic Garbage Collection + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; }; - }) + + # Optimize storage + nix.optimise.automatic = true; + } ]; mkHost = { hostName, system ? "x86_64-linux", extraModules ? [ ] }: @@ -73,61 +42,44 @@ let { networking.hostName = hostName; } ]; }; + + # Function to generate a set of hosts + mkHostGroup = { prefix, count, system ? "x86_64-linux", extraModules ? [], deviceOverrides ? {} }: + lib.listToAttrs (map (i: { + name = "${prefix}${toString i}"; + value = mkHost { + hostName = "${prefix}${toString i}"; + inherit system; + extraModules = extraModules ++ + (lib.optional (builtins.hasAttr (toString i) deviceOverrides) + ({ ... }: + let + devConf = deviceOverrides.${toString i}; + fsConf = builtins.removeAttrs devConf [ "extraUsers" ]; + in { + host.filesystem = fsConf; + modules.users.enabledUsers = devConf.extraUsers or []; + } + ) + ); + }; + }) (lib.range 1 count)); + + # Generate host groups based on the input hosts configuration + hostGroups = lib.mapAttrsToList (type: config: + let + typeFile = ./types + "/${type}.nix"; + modules = if builtins.pathExists typeFile + then import typeFile { inherit inputs; } + else throw "Host type '${type}' not found in hosts/types/"; + in + mkHostGroup { + prefix = type; + inherit (config) count; + extraModules = modules; + deviceOverrides = config.devices or {}; + } + ) hosts; + in -{ - nix-laptop1 = mkHost { - hostName = "nix-laptop1"; - system = "x86_64-linux"; - extraModules = [ - ./nix-laptop.nix - ]; - }; - - nix-laptop2 = mkHost { - hostName = "nix-laptop2"; - system = "x86_64-linux"; - extraModules = [ - ./nix-laptop.nix - ../sw.nix - ]; - }; - - nix-desktop1 = mkHost { - hostName = "nix-desktop1"; - system = "x86_64-linux"; - extraModules = [ - ./nix-desktop.nix - ../sw.nix - ]; - }; - - nix-surface1 = mkHost { - hostName = "nix-surface1"; - system = "x86_64-linux"; - extraModules = [ - ./nix-surface.nix - ../sw-kiosk.nix - inputs.nixos-hardware.nixosModules.microsoft-surface-go - ]; - }; - - nix-surface2 = mkHost { - hostName = "nix-surface2"; - system = "x86_64-linux"; - extraModules = [ - ./nix-surface.nix - ../sw-kiosk.nix - inputs.nixos-hardware.nixosModules.microsoft-surface-go - ]; - }; - - nix-surface3 = mkHost { - hostName = "nix-surface3"; - system = "x86_64-linux"; - extraModules = [ - ./nix-surface.nix - ../sw-kiosk.nix - inputs.nixos-hardware.nixosModules.microsoft-surface-go - ]; - }; -} + lib.foldl' lib.recursiveUpdate {} hostGroups diff --git a/hosts/nix-desktop.nix b/hosts/nix-desktop.nix deleted file mode 100644 index ecf4227..0000000 --- a/hosts/nix-desktop.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, lib, modulesPath, ... }: -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - boot.kernelParams = [ - "quiet" - "splash" - "boot.shell_on_fail" - "udev.log_priority=3" - "rd.systemd.show_status=auto" - ]; - - disko.devices.disk.main.content.partitions.swap.size = "16G"; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} diff --git a/hosts/nix-laptop.nix b/hosts/nix-laptop.nix deleted file mode 100644 index 8435be2..0000000 --- a/hosts/nix-laptop.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ config, lib, modulesPath, ... }: - -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - boot.kernelParams = [ - "quiet" - "splash" - "boot.shell_on_fail" - "udev.log_priority=3" - "rd.systemd.show_status=auto" - "i915.enable_psr=0" - "i915.enable_dc=0" - "i915.enable_fbc=0" - ]; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - - # Suspend / logind behavior - services.upower.enable = true; - services.logind.settings = { - Login = { - HandleLidSwitch = "suspend"; - HandleLidSwitchExternalPower = "suspend"; - HandleLidSwitchDocked = "ignore"; - }; - }; - -} diff --git a/hosts/nix-surface.nix b/hosts/nix-surface.nix deleted file mode 100644 index 39943d8..0000000 --- a/hosts/nix-surface.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ config, lib, pkgs, inputs, modulesPath, ... }: -let - refSystem = inputs.nixpkgs-old-kernel.lib.nixosSystem { - system = pkgs.stdenv.hostPlatform.system; - modules = [ inputs.nixos-hardware.nixosModules.microsoft-surface-go ]; - }; - refKernelPackages = refSystem.config.boot.kernelPackages; -in -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - boot.kernelParams = [ - "quiet" - "splash" - "boot.shell_on_fail" - "udev.log_priority=3" - "rd.systemd.show_status=auto" - "intel_ipu3_imgu" - "intel_ipu3_isys" - "fbcon=map:1" - "i915.enable_psr=0" # Panel Self Refresh breaks resume on Surface - "i915.enable_dc=0" - ]; - - boot.kernelPackages = lib.mkForce refKernelPackages; - - disko.devices.disk.main.content.partitions.swap.size = "8G"; - disko.devices.disk.main.device = "/dev/mmcblk0"; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} diff --git a/hosts/types/nix-desktop.nix b/hosts/types/nix-desktop.nix new file mode 100644 index 0000000..9720162 --- /dev/null +++ b/hosts/types/nix-desktop.nix @@ -0,0 +1,24 @@ +{ inputs, ... }: [ + ({ config, lib, modulesPath, ... }: { + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + boot.kernelParams = [ + "quiet" + "splash" + "boot.shell_on_fail" + "udev.log_priority=3" + "rd.systemd.show_status=auto" + ]; + + host.filesystem.swapSize = lib.mkDefault "16G"; + host.filesystem.device = lib.mkDefault "/dev/nvme0n1"; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + }) + { modules.sw.enable = true; modules.sw.type = "desktop"; } +] diff --git a/hosts/types/nix-laptop.nix b/hosts/types/nix-laptop.nix new file mode 100644 index 0000000..a1f361d --- /dev/null +++ b/hosts/types/nix-laptop.nix @@ -0,0 +1,37 @@ +{ inputs, ... }: [ + ({ config, lib, modulesPath, ... }: { + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + boot.kernelParams = [ + "quiet" + "splash" + "boot.shell_on_fail" + "udev.log_priority=3" + "rd.systemd.show_status=auto" + "i915.enable_psr=0" + "i915.enable_dc=0" + "i915.enable_fbc=0" + ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + host.filesystem.device = lib.mkDefault "/dev/nvme0n1"; + host.filesystem.swapSize = lib.mkDefault "34G"; + + # Suspend / logind behavior + services.upower.enable = true; + services.logind.settings = { + Login = { + HandleLidSwitch = "suspend"; + HandleLidSwitchExternalPower = "suspend"; + HandleLidSwitchDocked = "ignore"; + }; + }; + }) + { modules.sw.enable = true; modules.sw.type = "desktop"; } +] diff --git a/hosts/types/nix-surface.nix b/hosts/types/nix-surface.nix new file mode 100644 index 0000000..89d84af --- /dev/null +++ b/hosts/types/nix-surface.nix @@ -0,0 +1,40 @@ +{ inputs, ... }: [ + ({ config, lib, pkgs, modulesPath, ... }: + let + refSystem = inputs.nixpkgs-old-kernel.lib.nixosSystem { + system = pkgs.stdenv.hostPlatform.system; + modules = [ inputs.nixos-hardware.nixosModules.microsoft-surface-go ]; + }; + refKernelPackages = refSystem.config.boot.kernelPackages; + in + { + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + boot.kernelParams = [ + "quiet" + "splash" + "boot.shell_on_fail" + "udev.log_priority=3" + "rd.systemd.show_status=auto" + "intel_ipu3_imgu" + "intel_ipu3_isys" + "fbcon=map:1" + "i915.enable_psr=0" # Panel Self Refresh breaks resume on Surface + "i915.enable_dc=0" + ]; + + boot.kernelPackages = lib.mkForce refKernelPackages; + + host.filesystem.swapSize = lib.mkDefault "8G"; + host.filesystem.device = lib.mkDefault "/dev/mmcblk0"; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + }) + inputs.nixos-hardware.nixosModules.microsoft-surface-go + { modules.sw.enable = true; modules.sw.type = "kiosk"; } +] diff --git a/hosts/user-config.nix b/hosts/user-config.nix new file mode 100644 index 0000000..8d0993a --- /dev/null +++ b/hosts/user-config.nix @@ -0,0 +1,79 @@ +{ pkgs, config, lib, ... }: +let + userSubmodule = lib.types.submodule { + options = { + isNormalUser = lib.mkOption { type = lib.types.bool; default = true; }; + description = lib.mkOption { type = lib.types.str; default = ""; }; + extraGroups = lib.mkOption { type = lib.types.listOf lib.types.str; default = []; }; + hashedPassword = lib.mkOption { type = lib.types.str; default = "!"; }; + extraPackages = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; }; + excludePackages = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; }; + homePackages = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; }; + extraImports = lib.mkOption { type = lib.types.listOf lib.types.path; default = []; }; + flakeUrl = lib.mkOption { type = lib.types.str; default = ""; description = "URL of a flake to import Home Manager configuration from (e.g. github:user/dotfiles)."; }; + opensshKeys = lib.mkOption { type = lib.types.listOf lib.types.str; default = []; description = "List of SSH public keys for the user."; }; + }; + }; +in +{ + options.modules.users = { + shell = lib.mkOption { + type = lib.types.package; + default = pkgs.zsh; + description = "The default shell for users."; + }; + accounts = lib.mkOption { + type = lib.types.attrsOf userSubmodule; + default = {}; + description = "User accounts configuration."; + }; + enabledUsers = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "List of users to enable on this system."; + }; + }; + + config = { + modules.users.enabledUsers = [ "root" "engr-ugaif" ]; + + # Generate NixOS users + users.users = + let + enabledAccounts = lib.filterAttrs (name: _: lib.elem name config.modules.users.enabledUsers) config.modules.users.accounts; + in + lib.mapAttrs (name: user: + let + isPlasma6 = config.services.desktopManager.plasma6.enable; + defaultPackages = lib.optionals (isPlasma6 && name != "root") [ pkgs.kdePackages.kate ]; + finalPackages = lib.subtractLists user.excludePackages (defaultPackages ++ user.extraPackages); + in + { + inherit (user) isNormalUser description extraGroups hashedPassword; + openssh.authorizedKeys.keys = user.opensshKeys; + packages = finalPackages; + shell = config.modules.users.shell; + } + ) enabledAccounts; + + # Home Manager configs per user + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + extraSpecialArgs = { inherit osConfig; }; + + users = + let + enabledAccounts = lib.filterAttrs (name: _: lib.elem name config.modules.users.enabledUsers) config.modules.users.accounts; + in + lib.mapAttrs (name: user: { ... }: { + imports = user.extraImports ++ + (lib.optional (user.flakeUrl != "") (builtins.getFlake user.flakeUrl).homeManagerModules.default); + home.username = name; + home.homeDirectory = if name == "root" then "/root" else "/home/${name}"; + home.stateVersion = "25.11"; + home.packages = user.homePackages; + }) enabledAccounts; + }; + }; +} diff --git a/inventory.nix b/inventory.nix new file mode 100644 index 0000000..3540b8a --- /dev/null +++ b/inventory.nix @@ -0,0 +1,26 @@ +{ + # Laptop Configuration + # Base specs: NVMe drive, 34G Swap + nix-laptop = { + count = 2; + devices = { + # Override example: + # "2" = { swapSize = "64G"; }; + + # Enable specific users for this device index + "1" = { extraUsers = [ "hdh20267" ]; }; + }; + }; + + # Desktop Configuration + # Base specs: NVMe drive, 16G Swap + nix-desktop = { + count = 1; + }; + + # Surface Tablet Configuration (Kiosk Mode) + # Base specs: eMMC drive, 8G Swap + nix-surface = { + count = 3; + }; +} diff --git a/sw.nix b/sw.nix deleted file mode 100644 index a9c2037..0000000 --- a/sw.nix +++ /dev/null @@ -1,91 +0,0 @@ -{ pkgs, inputs, ... }: - -{ - # Enable the KDE Plasma Desktop Environment. - services.displayManager.sddm.enable = true; - services.desktopManager.plasma6.enable = true; - - # Enable CUPS to print documents. - services.printing.enable = true; - - # Enable networking - networking.networkmanager.enable = true; - - # Enable sound with pipewire. - services.pulseaudio.enable = false; - security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - }; - - # Allow unfree packages - nixpkgs.config.allowUnfree = true; - - # List packages installed in system profile. To search, run: - environment.systemPackages = with pkgs; [ - tmux - htop - binutils - man - (chromium.override { - commandLineArgs = [ "--enable-features=TouchpadOverscrollHistoryNavigation" ]; - }) - lm_sensors - oh-my-posh - zsh - git - zoom-us - teams-for-linux - wpsoffice - inputs.lazyvim-nixvim.packages.${stdenv.hostPlatform.system}.nvim - ]; - - programs.zsh.enable = true; - programs.nix-ld.enable = true; - - fonts.packages = with pkgs; [ - nerd-fonts.fira-code - corefonts - noto-fonts - ]; - fonts.fontconfig = { - enable = true; - defaultFonts.monospace = [ "FiraCode Nerd Font Mono" ]; - }; - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - programs.mtr.enable = true; - programs.gnupg.agent = { - enable = true; - enableSSHSupport = true; - }; - - # Bluetooth - hardware.bluetooth.enable = true; - services.blueman.enable = true; - - # Firewall - networking.firewall.enable = true; - - # Flatpak + portals - services.flatpak.enable = true; - xdg.portal.enable = true; - xdg.portal.extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde ]; - - # Browsers - programs.firefox.enable = true; - - # Virtualization - virtualisation.libvirtd.enable = true; - programs.virt-manager.enable = true; - - # Sensors - services.thermald.enable = true; - - # Enable the OpenSSH daemon. - services.openssh.enable = true; -} diff --git a/sw/default.nix b/sw/default.nix new file mode 100644 index 0000000..b90dabd --- /dev/null +++ b/sw/default.nix @@ -0,0 +1,69 @@ +{ config, lib, pkgs, inputs, ... }: + +with lib; + +let + cfg = config.modules.sw; +in +{ + imports = [ + ./python.nix + ]; + + options.modules.sw = { + enable = mkEnableOption "Standard Workstation Configuration"; + + type = mkOption { + type = types.enum [ "desktop" "kiosk" ]; + default = "desktop"; + description = "Type of system configuration: 'desktop' for normal OS, 'kiosk' for tablet/kiosk mode."; + }; + + extraPackages = mkOption { + type = types.listOf types.package; + default = []; + description = "Extra packages to install."; + }; + + excludePackages = mkOption { + type = types.listOf types.package; + default = []; + description = "Packages to exclude from the default list."; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + nixpkgs.config.allowUnfree = true; + + programs.zsh.enable = true; + programs.nix-ld.enable = true; + + environment.systemPackages = with pkgs; subtractLists cfg.excludePackages [ + htop + binutils + zsh + git + oh-my-posh + inputs.lazyvim-nixvim.packages.${stdenv.hostPlatform.system}.nvim + (writeShellScriptBin "update-system" '' + HOSTNAME=$(hostname) + FLAKE_URI="github:UGA-Innovation-Factory/nixos-systems" + + # Pass arguments like --impure to nixos-rebuild + EXTRA_ARGS="$@" + + if [[ "$HOSTNAME" == nix-surface* ]]; then + echo "Detected Surface tablet. Using remote build host." + sudo nixos-rebuild switch --flake "$FLAKE_URI" --build-host engr-ugaif@192.168.11.133 --refresh $EXTRA_ARGS + else + echo "Updating local system..." + sudo nixos-rebuild switch --flake "$FLAKE_URI" --refresh $EXTRA_ARGS + fi + '') + ]; + } + (mkIf (cfg.type == "desktop") (import ./desktop { inherit config lib pkgs inputs; })) + (mkIf (cfg.type == "kiosk") (import ./kiosk { inherit config lib pkgs inputs; })) + ]); +} diff --git a/sw/desktop/default.nix b/sw/desktop/default.nix new file mode 100644 index 0000000..5a48d54 --- /dev/null +++ b/sw/desktop/default.nix @@ -0,0 +1,5 @@ +{ config, lib, pkgs, inputs, ... }: +lib.mkMerge [ + (import ./programs.nix { inherit config lib pkgs inputs; }) + (import ./services.nix { inherit config lib pkgs inputs; }) +] diff --git a/sw/desktop/programs.nix b/sw/desktop/programs.nix new file mode 100644 index 0000000..77433cd --- /dev/null +++ b/sw/desktop/programs.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, inputs, ... }: + +with lib; + +let + cfg = config.modules.sw; + basePackages = with pkgs; [ + tmux + man + (chromium.override { + commandLineArgs = [ "--enable-features=TouchpadOverscrollHistoryNavigation" ]; + }) + lm_sensors + zoom-us + teams-for-linux + wpsoffice + ]; +in { + environment.systemPackages = subtractLists cfg.excludePackages (basePackages ++ cfg.extraPackages); + + programs.mtr.enable = true; + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + programs.firefox.enable = true; + programs.virt-manager.enable = true; +} diff --git a/sw/desktop/services.nix b/sw/desktop/services.nix new file mode 100644 index 0000000..1511f80 --- /dev/null +++ b/sw/desktop/services.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +{ + modules.sw.python.enable = lib.mkDefault true; + + services.displayManager.sddm.enable = true; + services.desktopManager.plasma6.enable = true; + + services.printing.enable = true; + + networking.networkmanager.enable = true; + + services.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + fonts.packages = with pkgs; [ + nerd-fonts.fira-code + corefonts + noto-fonts + ]; + fonts.fontconfig = { + enable = true; + defaultFonts.monospace = [ "FiraCode Nerd Font Mono" ]; + }; + + hardware.bluetooth.enable = true; + services.blueman.enable = true; + + networking.firewall.enable = true; + + services.flatpak.enable = true; + xdg.portal.enable = true; + xdg.portal.extraPortals = [ pkgs.kdePackages.xdg-desktop-portal-kde ]; + + virtualisation.libvirtd.enable = true; + + services.thermald.enable = true; + + services.fwupd.enable = true; + + services.openssh = { + enable = true; + settings.PermitRootLogin = "no"; + }; +} diff --git a/sw/kiosk/default.nix b/sw/kiosk/default.nix new file mode 100644 index 0000000..cb3cf84 --- /dev/null +++ b/sw/kiosk/default.nix @@ -0,0 +1,6 @@ +{ config, lib, pkgs, inputs, ... }: +lib.mkMerge [ + (import ./programs.nix { inherit config lib pkgs inputs; }) + (import ./services.nix { inherit config lib pkgs inputs; }) + (import ./gsettings.nix { inherit config lib pkgs inputs; }) +] diff --git a/sw/kiosk/gsettings.nix b/sw/kiosk/gsettings.nix new file mode 100644 index 0000000..7bb5b31 --- /dev/null +++ b/sw/kiosk/gsettings.nix @@ -0,0 +1,52 @@ +{ config, lib, inputs, ... }: + +let + cfg = config.modules.sw; +in { + config = lib.mkIf (cfg.enable && cfg.type == "kiosk") { + programs.dconf = { + enable = true; + profiles.user = { + databases = [{ + settings = { + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + clock-format = "12h"; + clock-show-weekday = true; + show-battery-percentage = true; + }; + "org/gnome/desktop/media-handling" = { + automount = false; + automount-open = false; + autorun-never = true; + }; + "org/gnome/settings-daemon/plugins/power" = { + sleep-inactive-ac-type = "nothing"; + }; + "org/gnome/desktop/lockdown" = { + disable-lock-screen = true; + }; + "org/gnome/desktop/screensaver" = { + lock-enabled = false; + }; + "org/gnome/desktop/session" = { + idle-delay = inputs.nixpkgs.lib.gvariant.mkUint32 0; + }; + "org/gnome/desktop/input-sources" = { + sources = "[('ibus', 'xkb:us::eng')]"; + }; + "org/gnome/desktop/mru-sources" = { + sources = "[('ibus', 'xkb:us::eng')]"; + }; + "sm/puri/phosh" = { + lock-enabled = false; + }; + "org/gnome/desktop/a11y/applications" = { + screen-keyboard-enabled = true; + }; + }; + }]; + }; + }; + }; +} diff --git a/sw/kiosk/programs.nix b/sw/kiosk/programs.nix new file mode 100644 index 0000000..25bd5ed --- /dev/null +++ b/sw/kiosk/programs.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, inputs, ... }: + +with lib; + +let + cfg = config.modules.sw; + basePackages = with pkgs; [ + libcamera + chromium + glib + squeekboard + dconf + phoc + gsettings-desktop-schemas + ]; +in { + environment.systemPackages = subtractLists cfg.excludePackages (basePackages ++ cfg.extraPackages); + + programs.chromium = { + enable = true; + }; +} diff --git a/sw-kiosk.nix b/sw/kiosk/services.nix similarity index 57% rename from sw-kiosk.nix rename to sw/kiosk/services.nix index 28b7ebd..d73e077 100644 --- a/sw-kiosk.nix +++ b/sw/kiosk/services.nix @@ -1,4 +1,4 @@ -{ pkgs, inputs, ... }: +{ config, lib, pkgs, ... }: { services.xserver = { @@ -10,65 +10,18 @@ }; }; - services.displayManager = { - gdm = { - enable = true; - autoSuspend = false; - }; - autoLogin = { - enable = true; - user = "engr-ugaif"; - }; + services.displayManager.gdm = { + enable = true; + autoSuspend = false; + }; + services.displayManager.autoLogin = { + enable = true; + user = "engr-ugaif"; }; services.dbus.enable = true; - programs.dconf = { - enable = true; - profiles.user = { - databases = [{ - settings = { - "org/gnome/desktop/interface" = { - color-scheme = "prefer-dark"; - clock-format = "12h"; - clock-show-weekday = true; - }; - "org/gnome/desktop/media-handling" = { - automount = false; - automount-open = false; - autorun-never = true; - }; - "org/gnome/settings-daemon/plugins/power" = { - sleep-inactive-ac-type = "nothing"; - }; - "org/gnome/desktop/lockdown" = { - disable-lock-screen = true; - }; - "org/gnome/desktop/screensaver" = { - lock-enabled = false; - }; - "org/gnome/desktop/session" = { - idle-delay = inputs.nixpkgs.lib.gvariant.mkUint32 0; - }; - "org/gnome/desktop/interface" = { - show-battery-percentage = true; - }; - "org/gnome/desktop/input-sources" = { - sources = "[('ibus', 'xkb:us::eng')]"; - }; - "org/gnome/desktop/mru-sources" = { - sources = "[('ibus', 'xkb:us::eng')]"; - }; - "sm/puri/phosh" = { - lock-enabled = false; - }; - "org/gnome/desktop/a11y/applications" = { - screen-keyboard-enabled = true; - }; - }; - }]; - }; - }; + services.fwupd.enable = true; i18n.inputMethod = { type = "ibus"; @@ -76,18 +29,7 @@ ibus.engines = [ pkgs.ibus-engines.m17n ]; }; - services.gnome.gnome-keyring.enable = inputs.nixpkgs.lib.mkForce false; - - systemd.user.services.squeekboard = { - description = "Squeekboard on-screen keyboard"; - wantedBy = [ "graphical-session.target" ]; - partOf = [ "graphical-session.target" ]; - - serviceConfig = { - ExecStart = "${pkgs.squeekboard}/bin/squeekboard"; - Restart = "on-failure"; - }; - }; + services.gnome.gnome-keyring.enable = lib.mkForce false; environment.sessionVariables = { GDK_SCALE = "1.25"; @@ -103,6 +45,59 @@ CHASSIS=handset ''; + services.logind.settings.Login = { + HandlePowerKey="ignore"; + HandleSuspendKey="ignore"; + HandleHibernateKey="ignore"; + HandleLidSwitch="ignore"; + HandleLidSwitchExternalPower="ignore"; + IdleAction="ignore"; + }; + + # Enable networking + networking.networkmanager.enable = false; + networking.wireless = { + enable = true; + networks = { + "IOT_vr" = { + ssid = "IOT_vr"; + pskRaw = "849a13f095b73a3d038a904576fd8ad4b83da81d285acaf435b545c1560c7e27"; + authProtocols = [ "WPA-PSK" ]; + }; + "IOT_sensors".psk = "aaaaaaaa"; + }; + }; + + # Enable sound with pipewire. + services.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + wireplumber.enable = true; + }; + + fonts.packages = with pkgs; [ + nerd-fonts.fira-code + ]; + fonts.fontconfig = { + enable = true; + defaultFonts.monospace = [ "FiraCode Nerd Font Mono" ]; + }; + + systemd.user.services.squeekboard = { + description = "Squeekboard on-screen keyboard"; + wantedBy = [ "graphical-session.target" ]; + partOf = [ "graphical-session.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.squeekboard}/bin/squeekboard"; + Restart = "on-failure"; + }; + }; + systemd.user.services."force-osk" = { description = "Force the OSK to Enable"; wantedBy = [ "chromium-kiosk.service" ]; @@ -110,10 +105,10 @@ serviceConfig = { ExecStartPre = '' - /run/current-system/sw/bin/sleep 5 + /run/current-system/sw/bin/sleep 5 ''; ExecStart = '' - /run/current-system/sw/bin/dconf reset /org/gnome/desktop/a11y/applications/screen-keyboard-enabled + /run/current-system/sw/bin/dconf reset /org/gnome/desktop/a11y/applications/screen-keyboard-enabled ''; Type = "simple"; }; @@ -126,13 +121,13 @@ serviceConfig = { ExecStartPre = '' - /run/current-system/sw/bin/sleep 5 + /run/current-system/sw/bin/sleep 5 ''; ExecStart = '' - /run/current-system/sw/bin/dconf reset /org/gnome/desktop/input-sources/sources + /run/current-system/sw/bin/dconf reset /org/gnome/desktop/input-sources/sources ''; ExecStartPost = '' - /run/current-system/sw/bin/dconf reset /org/gnome/desktop/mru-sources/sources + /run/current-system/sw/bin/dconf reset /org/gnome/desktop/mru-sources/sources ''; Type = "simple"; @@ -158,83 +153,4 @@ ''; }; }; - - services.logind.settings.Login = { - HandlePowerKey="ignore"; - HandleSuspendKey="ignore"; - HandleHibernateKey="ignore"; - HandleLidSwitch="ignore"; - HandleLidSwitchExternalPower="ignore"; - IdleAction="ignore"; - }; - - - # Enable networking - networking.networkmanager.enable = false; - networking.wireless = { - enable = true; - networks = { - "IOT_vr" = { - ssid = "IOT_vr"; - pskRaw = "849a13f095b73a3d038a904576fd8ad4b83da81d285acaf435b545c1560c7e27"; - authProtocols = [ "WPA-PSK" ]; - }; - "IOT_sensors".psk = "aaaaaaaa"; - }; - }; - - # Enable sound with pipewire. - services.pulseaudio.enable = false; - security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - wireplumber.enable = true; - }; - - # Allow unfree packages - nixpkgs.config.allowUnfree = true; - - # List packages installed in system profile. To search, run: - environment.systemPackages = with pkgs; [ - htop - binutils - libcamera - chromium - oh-my-posh - zsh - git - glib - squeekboard - dconf - phoc - gsettings-desktop-schemas - inputs.lazyvim-nixvim.packages.${stdenv.hostPlatform.system}.nvim - ]; - - programs.chromium = { - enable = true; - }; - - programs.zsh.enable = true; - programs.nix-ld.enable = true; - - fonts.packages = with pkgs; [ - nerd-fonts.fira-code - ]; - fonts.fontconfig = { - enable = true; - defaultFonts.monospace = [ "FiraCode Nerd Font Mono" ]; - }; - - # Bluetooth - hardware.bluetooth.enable = true; - - # Firewall - networking.firewall.enable = true; - - # Enable the OpenSSH daemon. - services.openssh.enable = true; } diff --git a/sw/nvim.nix b/sw/nvim.nix new file mode 100644 index 0000000..d4e7c99 --- /dev/null +++ b/sw/nvim.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + # https://github.com/nvim-treesitter/nvim-treesitter#i-get-query-error-invalid-node-type-at-position + xdg.configFile."nvim/parser".source = + let + parsers = pkgs.symlinkJoin { + name = "treesitter-parsers"; + paths = (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: with plugins; [ + c + lua + ])).dependencies; + }; + in + "${parsers}/parser"; +} diff --git a/sw/python.nix b/sw/python.nix new file mode 100644 index 0000000..2fcdae9 --- /dev/null +++ b/sw/python.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.modules.sw.python; +in { + options.modules.sw.python = { + enable = mkEnableOption "Python development tools (pixi, uv)"; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ + (pkgs.buildFHSEnv { + name = "pixi"; + runScript = "pixi"; + targetPkgs = pkgs: with pkgs; [ pixi ]; + }) + pkgs.uv + ]; + }; +} diff --git a/sw/theme.nix b/sw/theme.nix new file mode 100644 index 0000000..5cfbb4a --- /dev/null +++ b/sw/theme.nix @@ -0,0 +1,71 @@ +{ pkgs, config, osConfig, lib, ... }: + +let + # Fetch upstream OMP theme once + jyumppTheme = pkgs.fetchurl { + url = "https://raw.githubusercontent.com/Jyumpp/jyumpp-zsh-theme/refs/heads/master/.jyumpp.omp.json"; + hash = "sha256-jsN3hkyT0dJNTYEmDHQPp++oscQLgYGNj7PZAcIW2TA="; + }; + + # Make a root variant with red username (wraps {{ .UserName }} with ANSI red) + jyumppRootTheme = pkgs.runCommand "jyumpp-root.omp.json" {} '' + sed -E 's|\{\{[[:space:]]*\.UserName[[:space:]]*\}\}|<#FF3B30>{{ .UserName }}|g' \ + ${jyumppTheme} > $out + ''; + + isRoot = config.home.username == "root"; + themeFile = if isRoot then jyumppRootTheme else jyumppTheme; + + isZsh = osConfig.modules.users.shell == pkgs.zsh; +in +{ + config = lib.mkIf isZsh { + programs.zsh = { + enable = true; + + # Plugins + historySubstringSearch = { + enable = true; + searchDownKey = "^[[B"; + searchUpKey = "^[[A"; + }; + + zplug = lib.mkIf (!isRoot) { + enable = true; + plugins = [ + { + name = "jeffreytse/zsh-vi-mode"; + } + { + name = "BronzeDeer/zsh-completion-sync"; + } + ]; + }; + + history = { + append = true; + }; + + autosuggestion.enable = true; + + syntaxHighlighting.enable = true; + }; + + programs.zoxide = lib.mkIf (!isRoot) { + enable = true; + enableZshIntegration = true; + }; + + programs.lsd = lib.mkIf (!isRoot) { + enable = true; + enableZshIntegration = true; + }; + + programs.oh-my-posh = { + enable = true; + enableZshIntegration = true; + enableBashIntegration = true; + settings = builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile themeFile)); + }; + }; +} diff --git a/users.nix b/users.nix new file mode 100644 index 0000000..cca44a9 --- /dev/null +++ b/users.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: +{ + # Define the users here using the new option + # To generate a password hash, run: mkpasswd -m sha-512 + modules.users.accounts = { + root = { + isNormalUser = false; + hashedPassword = "!"; + extraImports = [ ./sw/theme.nix ]; + opensshKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBC7xzHxY2BfFUybMvG4wHSF9oEAGzRiLTFEndLvWV/X hdh20267@engr733847d.engr.uga.edu" ]; + }; + engr-ugaif = { + description = "UGA Innovation Factory"; + extraGroups = [ "networkmanager" "wheel" "video" "input" ]; + hashedPassword = "$6$El6e2NhPrhVFjbFU$imlGZqUiizWw5fMP/ib0CeboOcFhYjIVb8oR1V1dP2NjDeri3jMoUm4ZABOB2uAF8UEDjAGHhFuZxhtbHg647/"; + extraImports = [ ./sw/theme.nix ./sw/nvim.nix ]; + opensshKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBC7xzHxY2BfFUybMvG4wHSF9oEAGzRiLTFEndLvWV/X hdh20267@engr733847d.engr.uga.edu" ]; + }; + hdh20267 = { + description = "Hunter Halloran"; + extraGroups = [ "networkmanager" "wheel" ]; + homePackages = [ pkgs.ghostty ]; + extraImports = [ ./sw/theme.nix ./sw/nvim.nix ]; + # Example of using an external flake for configuration: + # flakeUrl = "github:hdh20267/dotfiles"; + }; + }; +} diff --git a/users/default.nix b/users/default.nix deleted file mode 100644 index 50b5695..0000000 --- a/users/default.nix +++ /dev/null @@ -1,41 +0,0 @@ -{ pkgs, ... }: -let - pythonPkgs = import ./python.nix { inherit pkgs; }; -in -{ - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users = { - root.hashedPassword = "!"; - engr-ugaif = { - isNormalUser = true; - description = "UGA Innovation Factory"; - extraGroups = [ "networkmanager" "wheel" "video" "input" ]; - packages = with pkgs; [ - kdePackages.kate - ] ++ pythonPkgs; - hashedPassword = "$6$El6e2NhPrhVFjbFU$imlGZqUiizWw5fMP/ib0CeboOcFhYjIVb8oR1V1dP2NjDeri3jMoUm4ZABOB2uAF8UEDjAGHhFuZxhtbHg647/"; - }; - - hdh20267 = { - isNormalUser = true; - description = "Hunter Halloran"; - extraGroups = [ "networkmanager" "wheel" ]; - packages = with pkgs; [ - kdePackages.kate - ] ++ pythonPkgs; - shell = pkgs.zsh; - }; - }; - - # Home Manager configs per user - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - - users = { - "engr-ugaif" = import ./engr-ugaif.nix; - "hdh20267" = import ./hdh20267.nix; - "root" = import ./root.nix; - }; - }; -} diff --git a/users/engr-ugaif.nix b/users/engr-ugaif.nix deleted file mode 100644 index 29bd11a..0000000 --- a/users/engr-ugaif.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ pkgs, ... }: -let - # Fetch upstream OMP theme once - jyumppTheme = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/Jyumpp/jyumpp-zsh-theme/refs/heads/master/.jyumpp.omp.json"; - # After first build Nix will show the wanted hash; add it here for reproducibility: - hash = "sha256-jsN3hkyT0dJNTYEmDHQPp++oscQLgYGNj7PZAcIW2TA="; - }; -in -{ - home.username = "engr-ugaif"; - home.homeDirectory = "/home/engr-ugaif"; - home.stateVersion = "25.11"; - - home.packages = []; - - programs.zsh = { - enable = true; - - # Plugins - historySubstringSearch = { - enable = true; - searchDownKey = "^[[B"; - searchUpKey = "^[[A"; - }; - - zplug = { - enable = true; - plugins = [ - { - name = "jeffreytse/zsh-vi-mode"; - } - { - name = "BronzeDeer/zsh-completion-sync"; - } - ]; - }; - - history = { - append = true; - }; - - autosuggestion.enable = true; - - syntaxHighlighting.enable = true; - }; - - programs.zoxide = { - enable = true; - enableZshIntegration = true; - }; - - programs.lsd = { - enable = true; - enableZshIntegration = true; - }; - - programs.oh-my-posh = { - enable = true; - enableZshIntegration = true; - enableBashIntegration = true; - settings = builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile(jyumppTheme))); - }; - - # https://github.com/nvim-treesitter/nvim-treesitter#i-get-query-error-invalid-node-type-at-position - xdg.configFile."nvim/parser".source = - let - parsers = pkgs.symlinkJoin { - name = "treesitter-parsers"; - paths = (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: with plugins; [ - c - lua - ])).dependencies; - }; - in - "${parsers}/parser"; - -} diff --git a/users/hdh20267.nix b/users/hdh20267.nix deleted file mode 100644 index 728979e..0000000 --- a/users/hdh20267.nix +++ /dev/null @@ -1,80 +0,0 @@ -{ pkgs, ... }: -let - # Fetch upstream OMP theme once - jyumppTheme = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/Jyumpp/jyumpp-zsh-theme/refs/heads/master/.jyumpp.omp.json"; - # After first build Nix will show the wanted hash; add it here for reproducibility: - hash = "sha256-jsN3hkyT0dJNTYEmDHQPp++oscQLgYGNj7PZAcIW2TA="; - }; -in -{ - home.username = "hdh20267"; - home.homeDirectory = "/home/hdh20267"; - home.stateVersion = "25.11"; - - home.packages = with pkgs; [ - ghostty - ]; - - programs.zsh = { - enable = true; - - # Plugins - historySubstringSearch = { - enable = true; - searchDownKey = "^[[B"; - searchUpKey = "^[[A"; - }; - - zplug = { - enable = true; - plugins = [ - { - name = "jeffreytse/zsh-vi-mode"; - } - { - name = "BronzeDeer/zsh-completion-sync"; - } - ]; - }; - - history = { - append = true; - }; - - autosuggestion.enable = true; - - syntaxHighlighting.enable = true; - }; - - programs.zoxide = { - enable = true; - enableZshIntegration = true; - }; - - programs.lsd = { - enable = true; - enableZshIntegration = true; - }; - - programs.oh-my-posh = { - enable = true; - enableZshIntegration = true; - enableBashIntegration = true; - settings = builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile(jyumppTheme))); - }; - - # https://github.com/nvim-treesitter/nvim-treesitter#i-get-query-error-invalid-node-type-at-position - xdg.configFile."nvim/parser".source = - let - parsers = pkgs.symlinkJoin { - name = "treesitter-parsers"; - paths = (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: with plugins; [ - c - lua - ])).dependencies; - }; - in - "${parsers}/parser"; - -} diff --git a/users/python.nix b/users/python.nix deleted file mode 100644 index d53a5ab..0000000 --- a/users/python.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ pkgs, ... }: -[ - (pkgs.buildFHSEnv { - name = "pixi"; - runScript = "pixi"; - targetPkgs = pkgs: with pkgs; [ pixi ]; - }) - pkgs.uv -] diff --git a/users/root.nix b/users/root.nix deleted file mode 100644 index cbe62be..0000000 --- a/users/root.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ pkgs, ... }: - -let - # Fetch upstream OMP theme once - jyumppTheme = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/Jyumpp/jyumpp-zsh-theme/refs/heads/master/.jyumpp.omp.json"; - # After first build Nix will show the wanted hash; add it here for reproducibility: - sha256 = "sha256-jsN3hkyT0dJNTYEmDHQPp++oscQLgYGNj7PZAcIW2TA="; - }; - - # Make a root variant with red username (wraps {{ .UserName }} with ANSI red) - jyumppRootTheme = pkgs.runCommand "jyumpp-root.omp.json" {} '' - sed -E 's|\{\{[[:space:]]*\.UserName[[:space:]]*\}\}|<#FF3B30>{{ .UserName }}|g' \ - ${jyumppTheme} > $out -''; -in -{ - home.username = "root"; - home.homeDirectory = "/root"; - home.stateVersion = "25.05"; - - programs.zsh = { - enable = true; - - # Plugins - historySubstringSearch = { - enable = true; - searchDownKey = "^[[B"; - searchUpKey = "^[[A"; - }; - - history = { - append = true; - }; - - autosuggestion.enable = true; - - syntaxHighlighting.enable = true; - }; - - programs.oh-my-posh = { - enable = true; - enableBashIntegration = true; - enableZshIntegration = true; - settings = builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile(jyumppRootTheme))); - - }; - - # Add any root-specific HM packages if desired - home.packages = [ ]; -}