feat: implement profile system with mkHomeConfig and context constraints

- Add home/lib/default.nix with mkHomeConfig utility
  - Loads base + common modules always
  - Maps profiles (coding, gaming, media) to module imports
  - Enforces desktop/server mutual exclusion via assertion
  - Context must be 'desktop', 'server', or null

- Migrate all per-host home configs to new profile system
  - m3-ares: context=desktop, profiles=[coding, gaming, media]
  - m3-kratos: context=desktop, profiles=[coding, gaming, media]
  - m3-atlas: context=server, profiles=[coding]
  - m3-helios: context=server, profiles=[]
  - m3-hermes: context=server, profiles=[]
  - m3-aether: context=server, profiles=[]
  - m3-daedalus: context=desktop, profiles=[coding, media]

- Replace features.* options with new namespaces:
  - features.cli.* -> base.shell.* / base.cliTools.* / base.secrets
  - features.desktop.* -> desktop.wm.* / desktop.apps.* / desktop.theme.*
  - gaming/media moved to profiles.gaming.* / profiles.media.*

- Fix home/coding/editor/neovim.nix: remove duplicate option declaration
  (coding.editors.neovim.enable already declared by m3ta-nixpkgs)

- Fix home/coding/lsp/servers.nix: replace removed nodePackages.typescript-language-server
  with typescript-language-server

- Fix home/desktop/theme/wallpapers.nix: correct relative path
  (was ../../.. which resolved to project root, should be ../..)
This commit is contained in:
m3tm3re
2026-04-26 11:03:43 +02:00
parent 9908b9e335
commit f3749c5679
11 changed files with 422 additions and 181 deletions

View File

@@ -1,17 +1,7 @@
# NeoVim base configuration via m3ta-nixpkgs coding.editors module. # NeoVim base configuration via m3ta-nixpkgs coding.editors module.
{ # The option `coding.editors.neovim.enable` is declared by
config, # inputs.m3ta-nixpkgs.homeManagerModules.default — no re-declaration here.
lib, {...}: {
... # Placeholder for host-agnostic NeoVim overrides.
}: # Set coding.editors.neovim.enable = true in per-host files to activate.
with lib; let
cfg = config.coding.editors.neovim;
in {
# coding.editors.neovim is provided by inputs.m3ta-nixpkgs.homeManagerModules.default
options.coding.editors.neovim.enable = mkEnableOption "enable NeoVim editor";
config = mkIf cfg.enable {
# NeoVim configuration is managed by the m3ta-nixpkgs coding.editors module.
# Additional host-specific overrides can be added here.
};
} }

View File

@@ -15,7 +15,7 @@ in {
# Nix # Nix
nixd nixd
# General # General
nodePackages.typescript-language-server typescript-language-server
tailwindcss-language-server tailwindcss-language-server
]; ];
}; };

View File

@@ -12,7 +12,7 @@ in {
config = mkIf cfg { config = mkIf cfg {
xdg.configFile."hypr/wallpapers" = { xdg.configFile."hypr/wallpapers" = {
# Wallpapers are stored relative to the home/m3tam3re directory. # Wallpapers are stored relative to the home/m3tam3re directory.
source = ../../../m3tam3re/wallpapers; source = ../../m3tam3re/wallpapers;
recursive = true; recursive = true;
}; };
}; };

81
home/lib/default.nix Normal file
View File

@@ -0,0 +1,81 @@
# home/lib/default.nix
# Profile loading utilities for home-manager configurations.
#
# Usage:
# let homeLib = import ../lib { inherit lib; };
# in {
# imports = [
# (homeLib.mkHomeConfig { profiles = ["coding" "gaming"]; context = "desktop"; })
# ];
# }
{ lib }:
let
inherit (lib) optional;
# Infrastructure layer — nixpkgs overlays, nix-colors, m3ta-nixpkgs modules.
# Always loaded on every host.
commonModule = ../common;
# Base user environment — shell (nushell, starship), CLI tools, secrets.
# Always loaded on every host.
baseModule = ../base;
# Context-specific modules — desktop and server are mutually exclusive.
contextModuleMap = {
desktop = ../desktop;
server = ../server;
};
# Profile modules — freely combinable additions on top of base + context.
profileModuleMap = {
coding = ../coding;
gaming = ../profiles/gaming;
media = ../profiles/media;
};
in {
# Generate a home-manager module with imports based on profiles and context.
#
# Args:
# profiles: list of profile names (e.g. ["coding" "gaming" "media"])
# context: host context, one of "desktop" | "server" | null
#
# Returns: a home-manager module attrset with imports and assertions.
# Desktop and server contexts are mutually exclusive by design — passing
# any value other than "desktop", "server", or null causes an assertion
# failure at evaluation time.
mkHomeConfig = {
profiles ? [],
context ? null,
}:
let
contextImport =
if context == "desktop" then [ contextModuleMap.desktop ]
else if context == "server" then [ contextModuleMap.server ]
else [];
activeProfiles = builtins.filter
(profileName: builtins.hasAttr profileName profileModuleMap)
profiles;
profileImports = map (profileName: profileModuleMap.${profileName}) activeProfiles;
contextStr = if context == null then "null" else context;
in {
imports =
[ commonModule baseModule ]
++ contextImport
++ profileImports;
assertions = [
{
assertion = builtins.elem context [ "desktop" "server" null ];
message =
"m3ta home: context must be 'desktop', 'server', or null"
+ " (got: '${contextStr}')";
}
];
};
}

View File

@@ -1,17 +1,33 @@
# m3-aether — cloud VM.
# Context: server | Profiles: (none)
{ {
lib,
...
}:
let
homeLib = import ../lib { inherit lib; };
in {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
../features/cli profiles = [ ];
context = "server";
})
./home-server.nix ./home-server.nix
# Fish shell — no equivalent in new base module yet
../features/cli/fish.nix
]; ];
features = { # Base CLI tools (new namespace)
cli = { base = {
fish.enable = true; shell = {
fzf.enable = true;
nitch.enable = true;
secrets.enable = false;
starship.enable = true; starship.enable = true;
}; };
cliTools = {
fzf.enable = true;
nitch.enable = true;
};
}; };
# Fish shell (legacy — no new equivalent yet)
features.cli.fish.enable = true;
} }

View File

@@ -1,74 +1,115 @@
# m3-ares — TUXEDO laptop desktop workstation.
# Context: desktop | Profiles: coding, gaming, media
{ {
config, config,
lib, lib,
... ...
}: }:
let
homeLib = import ../lib { inherit lib; };
in
with lib; { with lib; {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
profiles = [ "coding" "gaming" "media" ];
context = "desktop";
})
./home.nix ./home.nix
../features/cli # Fish shell — no equivalent in new base module yet
../features/coding ../features/cli/fish.nix
../features/desktop
]; ];
config = mkMerge [ config = mkMerge [
{ {
# Base CLI tools (new namespace)
base = {
shell = {
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
television.enable = true;
};
secrets.enable = true;
};
# Fish shell (legacy — features namespace, no new equivalent yet)
features.cli.fish.enable = true;
# Desktop features (new namespace)
desktop = {
wm = {
hyprland.enable = true;
rofi.enable = true;
wayland.enable = true;
};
apps = {
crypto.enable = true;
obsidian.enable = true;
office.enable = true;
};
theme = {
fonts.enable = true;
wallpapers.enable = true;
};
};
# Coding environment
coding = {
editors = {
neovim.enable = true;
zed.enable = true;
};
lsp.enable = true;
};
# Gaming profile features
profiles.gaming = {
steam.enable = true;
gamescope.enable = true;
};
# Media profile features
profiles.media = {
obs.enable = true;
ffmpeg.enable = true;
kdenlive.enable = true;
ytDlp.enable = true;
};
xdg = { xdg = {
# TODO: better structure
enable = true; enable = true;
configFile."mimeapps.list".force = true; configFile."mimeapps.list".force = true;
mimeApps = { mimeApps = {
enable = true; enable = true;
associations.added = { associations.added = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
defaultApplications = { defaultApplications = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"application/md" = ["dev.zed.Zed.desktop"]; "application/md" = [ "dev.zed.Zed.desktop" ];
"application/text" = ["dev.zed.Zed.desktop"]; "application/text" = [ "dev.zed.Zed.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
}; };
}; };
features = {
cli = {
fish.enable = true;
nushell.enable = true;
fzf.enable = true;
nitch.enable = true;
secrets.enable = true;
starship.enable = true;
television.enable = true;
};
desktop = {
coding.enable = true;
crypto.enable = true;
gaming.enable = true;
hyprland.enable = true;
media.enable = true;
obsidian.enable = true;
office.enable = true;
rofi.enable = true;
fonts.enable = true;
wayland.enable = true;
wallpapers = true;
};
};
} }
(mkIf config.features.desktop.hyprland.enable { # Host-specific Hyprland monitor and workspace layout
(mkIf config.desktop.wm.hyprland.enable {
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
settings = { settings = {
exec-once = ["tuxedo-backlight"]; exec-once = [ "tuxedo-backlight" ];
monitor = [ monitor = [
"eDP-1,preferred,0x0,1.25" "eDP-1,preferred,0x0,1.25"
"HDMI-A-1,1920x1080@120,2560x0,1" "HDMI-A-1,1920x1080@120,2560x0,1"

View File

@@ -1,19 +1,33 @@
# m3-atlas — primary server, Traefik hub and container host.
# Context: server | Profiles: coding
{ {
lib,
...
}:
let
homeLib = import ../lib { inherit lib; };
in {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
../features/cli profiles = [ "coding" ];
../features/coding/opencode.nix context = "server";
})
./home-server.nix ./home-server.nix
]; ];
coding.editors.neovim.enable = true;
features = { # Base CLI tools (new namespace)
cli = { base = {
shell = {
nushell.enable = true; nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true; fzf.enable = true;
nitch.enable = true; nitch.enable = true;
secrets.enable = false;
starship.enable = true;
zellij.enable = true; zellij.enable = true;
}; };
}; };
# Coding environment
coding.editors.neovim.enable = true;
} }

View File

@@ -1,74 +1,105 @@
# m3-daedalus — portable laptop (standalone home-manager).
# Context: desktop | Profiles: coding, media
{ {
config, config,
lib, lib,
... ...
}: }:
with lib; let let
cfg = config.features.desktop.hyprland; homeLib = import ../lib { inherit lib; };
in { in
with lib; {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
profiles = [ "coding" "media" ];
context = "desktop";
})
./home.nix ./home.nix
../features/cli # Fish shell — no equivalent in new base module yet
../features/coding ../features/cli/fish.nix
../features/desktop
#./services/librechat.nix
]; ];
options.features.desktop.hyprland.enable =
mkEnableOption "enable Hyprland";
config = mkMerge [ config = mkMerge [
# Base configuration
{ {
# Base CLI tools (new namespace)
base = {
shell = {
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
television.enable = true;
};
secrets.enable = true;
};
# Fish shell (legacy — no new equivalent yet)
features.cli.fish.enable = true;
# Desktop features (new namespace)
desktop = {
wm = {
hyprland.enable = false;
rofi.enable = true;
wayland.enable = false;
};
apps = {
obsidian.enable = true;
office.enable = false;
crypto.enable = false;
};
theme = {
fonts.enable = true;
wallpapers.enable = false;
};
};
# Coding environment
coding = {
editors = {
neovim.enable = true;
zed.enable = true;
};
lsp.enable = true;
};
# Media profile features
profiles.media = {
obs.enable = false;
ffmpeg.enable = false;
kdenlive.enable = false;
ytDlp.enable = true;
};
xdg = { xdg = {
# TODO: better structure
enable = true; enable = true;
configFile."mimeapps.list".force = true; configFile."mimeapps.list".force = true;
mimeApps = { mimeApps = {
enable = true; enable = true;
associations.added = { associations.added = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
defaultApplications = { defaultApplications = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"application/md" = ["dev.zed.Zed.desktop"]; "application/md" = [ "dev.zed.Zed.desktop" ];
"application/text" = ["dev.zed.Zed.desktop"]; "application/text" = [ "dev.zed.Zed.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
}; };
}; };
features = {
cli = {
fish.enable = true;
nushell.enable = true;
fzf.enable = true;
nitch.enable = true;
secrets.enable = true;
starship.enable = true;
};
desktop = {
coding.enable = true;
crypto.enable = false;
gaming.enable = false;
hyprland.enable = false;
media.enable = true;
office.enable = false;
rofi.enable = true;
fonts.enable = true;
wayland.enable = false;
};
};
} }
(mkIf cfg.enable { # Host-specific Hyprland layout — only applies when hyprland is enabled
(mkIf config.desktop.wm.hyprland.enable {
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
settings = { settings = {

View File

@@ -1,17 +1,33 @@
# m3-helios — AdGuard DNS and internal routing server.
# Context: server | Profiles: (none)
{ {
lib,
...
}:
let
homeLib = import ../lib { inherit lib; };
in {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
../features/cli profiles = [ ];
context = "server";
})
./home-server.nix ./home-server.nix
# Fish shell — no equivalent in new base module yet
../features/cli/fish.nix
]; ];
features = { # Base CLI tools (new namespace)
cli = { base = {
fish.enable = true; shell = {
fzf.enable = true;
nitch.enable = true;
secrets.enable = false;
starship.enable = true; starship.enable = true;
}; };
cliTools = {
fzf.enable = true;
nitch.enable = true;
};
}; };
# Fish shell (legacy — no new equivalent yet)
features.cli.fish.enable = true;
} }

View File

@@ -1,17 +1,33 @@
# m3-hermes — secondary server.
# Context: server | Profiles: (none)
{ {
lib,
...
}:
let
homeLib = import ../lib { inherit lib; };
in {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
../features/cli profiles = [ ];
context = "server";
})
./home-server.nix ./home-server.nix
# Fish shell — no equivalent in new base module yet
../features/cli/fish.nix
]; ];
features = { # Base CLI tools (new namespace)
cli = { base = {
fish.enable = true; shell = {
fzf.enable = true;
nitch.enable = true;
secrets.enable = false;
starship.enable = true; starship.enable = true;
}; };
cliTools = {
fzf.enable = true;
nitch.enable = true;
};
}; };
# Fish shell (legacy — no new equivalent yet)
features.cli.fish.enable = true;
} }

View File

@@ -1,69 +1,106 @@
# m3-kratos — AMD desktop workstation.
# Context: desktop | Profiles: coding, gaming, media
{ {
config, config,
lib, lib,
... ...
}: }:
let
homeLib = import ../lib { inherit lib; };
in
with lib; { with lib; {
imports = [ imports = [
../common (homeLib.mkHomeConfig {
profiles = [ "coding" "gaming" "media" ];
context = "desktop";
})
./home.nix ./home.nix
../features/cli
../features/coding
../features/desktop
]; ];
config = mkMerge [ config = mkMerge [
{ {
# Base CLI tools (new namespace)
base = {
shell = {
nushell.enable = true;
starship.enable = true;
};
cliTools = {
fzf.enable = true;
nitch.enable = true;
television.enable = true;
};
secrets.enable = true;
};
# Desktop features (new namespace)
desktop = {
wm = {
hyprland.enable = true;
rofi.enable = true;
wayland.enable = true;
};
apps = {
crypto.enable = true;
obsidian.enable = true;
office.enable = true;
};
theme = {
fonts.enable = true;
wallpapers.enable = true;
};
};
# Coding environment
coding = {
editors = {
neovim.enable = true;
zed.enable = true;
};
lsp.enable = true;
};
# Gaming profile features
profiles.gaming = {
steam.enable = true;
gamescope.enable = true;
};
# Media profile features
profiles.media = {
obs.enable = true;
ffmpeg.enable = true;
kdenlive.enable = true;
ytDlp.enable = true;
};
xdg = { xdg = {
# TODO: better structure
enable = true; enable = true;
configFile."mimeapps.list".force = true; configFile."mimeapps.list".force = true;
mimeApps = { mimeApps = {
enable = true; enable = true;
associations.added = { associations.added = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
defaultApplications = { defaultApplications = {
"application/zip" = ["org.gnome.FileRoller.desktop"]; "application/zip" = [ "org.gnome.FileRoller.desktop" ];
"application/csv" = ["calc.desktop"]; "application/csv" = [ "calc.desktop" ];
"application/pdf" = ["vivaldi-stable.desktop"]; "application/pdf" = [ "vivaldi-stable.desktop" ];
"application/md" = ["dev.zed.Zed.desktop"]; "application/md" = [ "dev.zed.Zed.desktop" ];
"application/text" = ["dev.zed.Zed.desktop"]; "application/text" = [ "dev.zed.Zed.desktop" ];
"x-scheme-handler/http" = ["vivaldi-stable.desktop"]; "x-scheme-handler/http" = [ "vivaldi-stable.desktop" ];
"x-scheme-handler/https" = ["vivaldi-stable.desktop"]; "x-scheme-handler/https" = [ "vivaldi-stable.desktop" ];
}; };
}; };
}; };
features = {
cli = {
nushell.enable = true;
fzf.enable = true;
nitch.enable = true;
secrets.enable = true;
starship.enable = true;
television.enable = true;
};
desktop = {
crypto.enable = true;
coding.enable = true;
gaming.enable = true;
hyprland.enable = true;
media.enable = true;
obsidian.enable = true;
office.enable = true;
rofi.enable = true;
fonts.enable = true;
wayland.enable = true;
wallpapers = true;
};
};
} }
(mkIf config.features.desktop.hyprland.enable { # Host-specific Hyprland monitor and workspace layout (dual 1440p monitors)
(mkIf config.desktop.wm.hyprland.enable {
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
settings = { settings = {
@@ -80,7 +117,6 @@ with lib; {
"6, monitor:DP-2" "6, monitor:DP-2"
"7, monitor:DP-2" "7, monitor:DP-2"
]; ];
windowrule = [ windowrule = [
"match:class dev.zed.Zed, workspace 1" "match:class dev.zed.Zed, workspace 1"
"match:class Msty, workspace 1" "match:class Msty, workspace 1"