Compare commits

..

No commits in common. "8a69e60c6f6f8c393a43f1b6997526e9407beea5" and "cd32ad1c61f15289f2ff69ffb8a5eb1186283f6d" have entirely different histories.

18 changed files with 161 additions and 219 deletions

View file

@ -6,30 +6,22 @@
<br> <br>
## 🚧 State of development ## 🚧 State of development
All the basic functionality of v2 should be working correctly, including: Version 2.0 is still very much an experiment and not ready to be used in a production
environment. If you must, try running it within a VM using the provided deployment
- The custom lib implementation at self.lib, recursively built from the contents of the `lib` directory. instructions.
- Loading of systems from the `systems` directory, using easy-hosts.
- A basic workstation archetype for desktop systems.
- Creating users in your systems through ${self.namespace}.users,
automatically maps home-manager configurations from the `homes` directory to their corresponding users.
Nonetheless, one should still consider this implementation experimental,
once I start using this on my laptop,
I'll aim for production grade stability.
## 🚀 Deployment ## 🚀 Deployment
To deploy a system run the following command in your terminal of choice. To deploy a system run the following command in your terminal of choice.
```sh ```sh
sudo nixos-rebuild switch --flake .#hostname --accept-flake-config sudo nixos-rebuild switch --flake .#hostname
``` ```
If you're interested in a quick way to experiment with this configuration, If you're interested in a quick way to experiment with this configuration,
you may use the following command to build a VM. you may use the following command to build a VM.
```sh ```sh
sudo nixos-rebuild build-vm --flake .#hostname --accept-flake-config sudo nixos-rebuild build-vm --flake .#hostname
``` ```
## 📝 Goals and improvements ## 📝 Goals and improvements

View file

@ -1,6 +0,0 @@
{pkgs, ...}: {
home.packages = with pkgs; [
cowsay
cmatrix
];
}

View file

@ -1,7 +1,10 @@
{pkgs, ...}: { {
pkgs,
...
}: {
home.packages = with pkgs; [ home.packages = with pkgs; [
zed-editor vscodium
firefox cmatrix
]; ];
home.stateVersion = "25.05"; home.stateVersion = "25.05";

View file

@ -1,13 +1,8 @@
{ { lib, self, ... }: {
lib,
self,
...
}: {
# Create a NixOS module option on a single line. # Create a NixOS module option on a single line.
mkOpt = type: default: description: mkOpt = type: default: description:
lib.mkOption {inherit type default description;}; lib.mkOption {inherit type default description;};
# Create a simple bool options
mkBool = default: description: mkBool = default: description:
lib.mkOption { lib.mkOption {
inherit default description; inherit default description;
@ -15,17 +10,20 @@
}; };
# Create a module compliant with the NixOS module system. # Create a module compliant with the NixOS module system.
mkModule = { mkModule =
name ? "puzzlevision", {
class, name ? "puzzlevision",
modules, class,
}: { modules,
_class = class; }: {
# Template: "[path-to-flake]/flake.nix#[class-name]Modules.[module-name]" _class = class;
# Example: "[path-to-flake]/flake.nix#nixosModules.system.audio"
_file = "${self.outPath}/flake.nix#${class}Modules.${name}"; # Template: "[path-to-flake]/flake.nix#[class-name]Modules.[module-name]"
imports = modules; # Example: "[path-to-flake]/flake.nix#nixosModules.system.audio"
}; _file = "${self.outPath}/flake.nix#${class}Modules.${name}";
imports = modules;
};
# TODO: add mkIfElse function # TODO: add mkIfElse function
} }

View file

@ -6,7 +6,13 @@
# Automagically imports libs from "/lib/lib-name" and exposes them to the `flake.lib` output. # Automagically imports libs from "/lib/lib-name" and exposes them to the `flake.lib` output.
./lib.nix ./lib.nix
# Recursively imports overlays from "/overlays/overlay-name" and exposes them to the `flake.overlays` output.
#./overlays.nix
# Automagically imports systems from "/systems/arch-classname/system-name". # Automagically imports systems from "/systems/arch-classname/system-name".
./systems.nix ./systems.nix
# Automagically imports homes from "/homes/user-name".
#./homes.nix
]; ];
} }

View file

@ -1,10 +1,10 @@
{self, ...}: { { self, ... }:
{
flake = { flake = {
# TODO: figure out why this isn't working correctly #nixosModules.puzzlevision = self.lib.mkModule {
nixosModules.puzzlevision = self.lib.mkModule { # class = "nixos";
class = "nixos"; # modules = self.lib.dirToModuleList ../nixos;
modules = self.lib.dirToModuleList ../nixos; #};
};
homeModules.puzzlevision = self.lib.mkModule { homeModules.puzzlevision = self.lib.mkModule {
class = "home"; class = "home";

View file

@ -1,12 +1,10 @@
{ {
lib, lib,
self,
inputs, inputs,
self,
... ...
}: { }: {
imports = [ imports = [ inputs.easy-hosts.flakeModule ];
inputs.easy-hosts.flakeModule
];
easyHosts = { easyHosts = {
autoConstruct = true; autoConstruct = true;

View file

@ -1,2 +0,0 @@
{...}: {
}

View file

@ -0,0 +1,33 @@
{
lib,
pkgs,
self,
config,
osConfig,
...
}: let
inherit (lib) mkIf mkOption;
inherit (self) namespace;
cfg = config.${namespace}.desktop.gnome;
in {
options.${namespace}.desktop.gnome = with lib.types; {
enabled-extensions = mkOption {
type = listOf package;
default = with pkgs.gnomeExtensions; [dash-to-dock user-themes blur-my-shell appindicator unite color-picker clipboard-history];
example = [dash-to-dock blur-my-shell];
description = "Specify gnome extensions to install.";
};
};
config = mkIf osConfig.${namespace}.desktop.gnome.enable {
home.packages = cfg.enabled-extensions;
dconf.settings = {
"org/gnome/shell" = {
enabled-extensions = lib.forEach cfg.enabled-extensions (x: x.extensionUuid);
disabled-extensions = []; # Make sure none of our extensions are disabled on system rebuild
};
};
};
}

View file

@ -1,32 +0,0 @@
{
lib,
self,
config,
...
}: let
inherit (lib) mkEnableOption mkIf mkDefault;
inherit (self) namespace;
cfg = config.${namespace}.archetypes.workstation;
in {
options.${namespace}.archetypes.workstation = {
enable = mkEnableOption "the workstation archetype.";
};
config = mkIf cfg.enable {
${namespace} = {
# Basic system functionality
system.grub.enable = true;
system.networking.enable = true;
system.kernel.enable = true;
# Services
services.docker.enable = true;
# Desktop environment
desktop.gnome.enable = true;
};
time.timeZone = mkDefault "Europe/Berlin";
};
}

View file

@ -3,22 +3,21 @@
self, self,
config, config,
... ...
}: let }:
let
inherit (lib) mkEnableOption mkIf; inherit (lib) mkEnableOption mkIf;
inherit (self) namespace; inherit (self) namespace;
cfg = config.${namespace}.system.grub; cfg = config.${namespace}.common.grub;
in { in {
options.${namespace}.system.grub = { options.${namespace}.common.grub = { enable = mkEnableOption "grub"; };
enable = mkEnableOption "the grub bootloader.";
};
config = mkIf cfg.enable { config = mkIf cfg.enable {
boot.loader.systemd-boot.enable = false; boot.loader.systemd-boot.enable = false;
boot.loader.grub = { boot.loader.grub = {
enable = true; enable = true;
devices = ["nodev"]; devices = [ "nodev" ];
efiInstallAsRemovable = true; efiInstallAsRemovable = true;
efiSupport = true; efiSupport = true;

View file

@ -9,9 +9,7 @@
cfg = config.${namespace}.desktop.gnome; cfg = config.${namespace}.desktop.gnome;
in { in {
options.${namespace}.desktop.gnome = { options.${namespace}.desktop.gnome = {enable = mkEnableOption "Enable the gnome desktop environment ${namespace}";};
enable = mkEnableOption "the gnome desktop environment";
};
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.xserver.enable = true; services.xserver.enable = true;

View file

@ -1,20 +0,0 @@
{
lib,
self,
config,
...
}: let
inherit (lib) mkIf mkEnableOption;
inherit (self) namespace;
cfg = config.${namespace}.services.docker;
in {
options.${namespace}.services.docker = {
enable = mkEnableOption "the docker service.";
};
config = mkIf cfg.enable {
# Enable docker
virtualisation.docker.enable = true;
};
}

View file

@ -1,22 +0,0 @@
{
lib,
pkgs,
self,
config,
...
}: let
inherit (lib) mkEnableOption mkIf;
inherit (self) namespace;
inherit (self.lib) mkOpt;
cfg = config.${namespace}.system.kernel;
in {
options.${namespace}.system.kernel = {
enable = mkEnableOption "Modify the standard kernel settings";
version = mkOpt lib.types.str "linuxPackages_latest" "Set the kernel version to be used by your system";
};
config = mkIf cfg.enable {
boot.kernelPackages = pkgs.${cfg.version};
};
}

View file

@ -1,19 +0,0 @@
{
lib,
self,
config,
...
}: let
inherit (lib) mkEnableOption mkIf;
inherit (self) namespace;
cfg = config.${namespace}.system.networking;
in {
options.${namespace}.system.networking = {
enable = mkEnableOption "networking.";
};
config = mkIf cfg.enable {
networking.networkmanager.enable = true;
};
}

View file

@ -1,78 +1,81 @@
{ {
lib, lib,
config,
self, self,
pkgs, pkgs,
config,
... ...
}: let }: let
inherit (lib) types mkEnableOption mkOption mkIf; inherit (lib) mkEnableOption mkIf mkOption types;
inherit (self) namespace; inherit (self) namespace;
inherit (self.lib) dirToModuleList; inherit (self.lib) mkOpt dirToModuleList;
cfg = config.${namespace}.users;
# The identifier of the current system type, e.g. "x86_64-linux" or "aarch64-darwin" # The identifier of the current system type, e.g. "x86_64-linux" or "aarch64-darwin"
system = pkgs.system; system = pkgs.system;
cfg = config.${namespace}.users;
userSubmodule = types.submodule { # Type for a user configuration
userType = types.submodule {
options = { options = {
enable = mkEnableOption "this user."; enable = mkEnableOption "this user";
isNormalUser = self.lib.mkBool true "Whether this user is considered a normal user."; initialPassword = mkOpt (types.nullOr types.str) null "Initial password for the user";
isSystemUser = self.lib.mkBool false "Whether this user is considered a system user."; password = mkOpt (types.nullOr types.str) null "Plaintext password for the user";
initialPassword = self.lib.mkOpt (types.nullOr types.str) null "Plaintext insecure initial user password, only recommended for testing."; hashedPassword = mkOpt (types.nullOr types.str) null "Hashed password for the user";
password = self.lib.mkOpt (types.nullOr types.str) null "Plaintext insecure user password, only recommended for testing."; isNormalUser = mkOpt types.bool true "Whether this user is a normal user";
extraGroups = self.lib.mkOpt (types.listOf types.str) [] "List of additional groups this user belongs to."; extraGroups = mkOpt (types.listOf types.str) [] "Extra groups for the user";
}; };
}; };
# Function to get home configuration path for a username
getHomeConfigPath = username: "${self.outPath}/homes/${system}/${username}"; getHomeConfigPath = username: "${self.outPath}/homes/${system}/${username}";
homeConfigExists = username: let
path = getHomeConfigPath username;
in
builtins.pathExists "${path}/default.nix";
# Function to check if a home configuration exists for a username
homeConfigExists = username:
let path = getHomeConfigPath username;
in builtins.pathExists "${path}/default.nix";
# Import all home-manager modules
homeModules = dirToModuleList "${self.outPath}/modules/home"; homeModules = dirToModuleList "${self.outPath}/modules/home";
in { in {
options.${namespace}.users = mkOption { options.${namespace}.users = mkOption {
type = types.attrsOf userSubmodule; type = types.attrsOf userType;
default = {}; default = {};
description = "List of users to create. Also handles home configurations, placed in self.outPath/homes/[x86_64-linux, aarch64-linux, etc...], through home-manager."; description = "User configurations with auto-imported home-manager setup";
}; };
config = { config = {
# TODO: fix this # Ensure users are fully managed by NixOS
#nix.settings.trusted-users = ["root" (lib.forEach cfg (username: toString username))];
# Manage users declaratively and map userConfig to users.users by name;
users.mutableUsers = false; users.mutableUsers = false;
# Create the actual system users
users.users = lib.mapAttrs (username: userConfig: users.users = lib.mapAttrs (username: userConfig:
mkIf userConfig.enable { mkIf userConfig.enable {
name = username; name = username;
inherit (userConfig) isNormalUser isSystemUser initialPassword password extraGroups; inherit (userConfig) extraGroups initialPassword hashedPassword isNormalUser password;
}) }
cfg; ) cfg;
# Configure home-manager with auto-imported user configuration
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { extraSpecialArgs = {
inherit self system; inherit self;
namespace = self.namespace; namespace = self.namespace;
}; };
users = users = lib.mapAttrs (username: userConfig:
lib.mapAttrs ( mkIf (userConfig.enable && homeConfigExists username) (
username: userConfig: { ... }: {
mkIf (userConfig.enable && homeConfigExists username) ( imports = [
{osConfig, ...}: { (getHomeConfigPath username) # Import the user's specific home configuration
# Import user home configuration and general home modules ]; #++ homeModules; # Include all generalized home modules
imports = [(getHomeConfigPath username)] ++ homeModules;
home.stateVersion = lib.mkDefault osConfig.system.stateVersion; home.stateVersion = lib.mkDefault config.system.stateVersion;
} }
)
) )
cfg; ) cfg;
}; };
}; };
} }

View file

@ -0,0 +1,26 @@
{
lib,
config,
self,
...
}: let
inherit (lib) mkIf;
inherit (self) namespace;
cfg = config.${namespace}.utils.vm;
in {
options.${namespace}.utils.vm = {
enable = self.lib.mkBool true "Whether to enable custom vm presets";
preset = self.lib.mkOpt lib.types.str "performance" "Specify the prefered vm settings preset: performance, balance or powersave";
};
config = mkIf cfg.enable {
virtualisation.vmVariant = {
virtualisation = {
cores = 6;
memorySize = 4096;
graphics = true;
};
};
};
}

View file

@ -1,43 +1,30 @@
{pkgs, ...}: { {
pkgs,
...
}: {
imports = [ imports = [
./hardware.nix ./hardware.nix
]; ];
puzzlevision = { puzzlevision = {
users.cyn = { # TODO: improve home-manager configuration loading as development continues and make sure everything works correctly.
enable = true; users = {
password = "cynical"; # For testing only, replace with sops secret before production use jo = {
extraGroups = ["wheel"]; enable = true;
initialPassword = "balls";
extraGroups = [ "wheel" ];
};
}; };
users.jo = { desktop.gnome.enable = true;
enable = true; utils.vm.enable = true;
password = "jo"; # For testing only, replace with sops secret before production use common.grub.enable = true;
extraGroups = ["wheel"];
};
archetypes.workstation.enable = true;
}; };
# Configure 8GB SWAP partition environment.systemPackages = with pkgs; [
swapDevices = [ ghostty
{ firefox
device = "/swapfile";
size = 8 * 1024;
}
]; ];
boot = {
# Configure additional kernel modules.
extraModulePackages = [
pkgs.linuxPackages_latest.rtl8821ce # Use custom network-card driver.
];
blacklistedKernelModules = [
"rtw88_8821ce" # Block the default network-card driver.
];
};
networking.hostName = "puzzlevision";
system.stateVersion = "25.05"; system.stateVersion = "25.05";
} }