commit fbc31450de92aefac57f0763ba64bd1c95475bad Author: m3ta-chiron Date: Sat May 2 09:08:40 2026 +0200 feat: initial m3ta-home structure - flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs - lib/mkHome.nix: compose HM config from user + identity + context + sets - profiles/base: shell, cli-tools, secrets (always loaded) - profiles/contexts/desktop: WM, apps, theme, ghostty - profiles/contexts/server: minimal headless - profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents - profiles/sets/gaming: steam, gamescope, gpu - profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp - users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity) - users/m3tam3re/preferences: cliphist, difftastic, base packages diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..726d2d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +.direnv diff --git a/README.md b/README.md new file mode 100644 index 0000000..42cbea6 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# m3ta-home — Portable User Profiles + +Centralized home-manager configurations for NixOS systems. +Separates user identity, preferences, and feature sets for portable deployment. + +## Structure + +``` +m3ta-home/ +├── lib/ ← mkHome, mkDevShell +├── modules/ ← Home-Manager module exports +├── profiles/ ← base, contexts, sets +├── users/ ← identity, preferences, secrets +└── secrets/ ← Agenix-encrypted user secrets +``` + +## Usage in nixos-config + +```nix +inputs.m3ta-home = { + url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home.git"; + inputs.nixpkgs.follows = "nixpkgs"; +}; +``` + +```nix +# hosts/common/users/m3tam3re.nix +home-manager.users.m3tam3re = { + imports = [ + (inputs.m3ta-home.lib.mkHome { + user = "m3tam3re"; + identity = "private"; + context = "desktop"; + sets = [ "coding" "gaming" "media" ]; + }) + ]; +}; +``` diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..4b600b4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,43 @@ +{ + description = "m3ta-home — portable user profiles and home-manager configurations"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + nix-colors.url = "github:misterio77/nix-colors"; + + m3ta-nixpkgs = { + url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-nixpkgs.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + agenix.url = "github:ryantm/agenix"; + + nur.url = "github:nix-community/NUR"; + }; + + outputs = { + self, + nixpkgs, + ... + } @ inputs: let + lib = nixpkgs.lib; + in { + # Home-Manager modules — import in nixos-config via: + # imports = [ inputs.m3ta-home.homeManagerModules.default ]; + homeManagerModules = import ./modules inputs; + + # Library functions — use in nixos-config via: + # m3ta-lib = inputs.m3ta-home.lib; + # imports = [ (m3ta-lib.mkHome { ... }) ]; + lib = import ./lib {inherit inputs;}; + + # Overlays (re-exports from m3ta-nixpkgs) + overlays = inputs.m3ta-nixpkgs.overlays; + }; +} diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..e7c0173 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,11 @@ +# lib/default.nix — Entry point for m3ta-home library functions. +# +# Provides: +# mkHome — compose a complete HM config from user + identity + context + sets +# mkDevShell — create project-level dev shells from language sets +{inputs}: { + mkHome = import ./mkHome.nix {inherit inputs;}; + + # TODO: mkDevShell for project-level flake devShells + # mkDevShell = import ./mkDevShell.nix { inherit inputs; }; +} diff --git a/lib/mkHome.nix b/lib/mkHome.nix new file mode 100644 index 0000000..5776d79 --- /dev/null +++ b/lib/mkHome.nix @@ -0,0 +1,103 @@ +# lib/mkHome.nix — Compose a complete home-manager configuration. +# +# This is the central function that replaces the old mkHomeConfig from nixos-config. +# It assembles imports based on three dimensions: +# +# WHO you are → user + identity (preferences + git/ssh/jj config) +# WHAT you do → context (desktop|server) + sets (coding, gaming, media) +# WHERE you are → host (handled by nixos-config, only overrides here) +# +# Usage: +# imports = [ (m3ta-lib.mkHome { +# user = "m3tam3re"; +# identity = "private"; # or "work" +# context = "desktop"; # or "server" +# sets = [ "coding" "gaming" "media" ]; +# }) ]; +# +# Then override host-specific settings in the consuming module: +# m3ta.home.sets.coding.languages.python.extra = true; +# wayland.windowManager.hyprland.settings.monitor = [ ... ]; +# +{inputs}: +{lib ? inputs.nixpkgs.lib}: +let + # --- Module path helpers --- + profilePath = ../profiles; + userPath = ../users; + + # Always loaded — CLI tools, shell, secrets, overlays + baseModule = "${profilePath}/base"; + + # Context modules — mutually exclusive (desktop or server) + contextModuleMap = { + desktop = "${profilePath}/contexts/desktop"; + server = "${profilePath}/contexts/server"; + }; + + # Feature sets — freely combinable, some have context guards + setModuleMap = { + coding = "${profilePath}/sets/coding"; + gaming = "${profilePath}/sets/gaming"; + media = "${profilePath}/sets/media"; + }; + + # Sets that require desktop context + desktopOnlySets = ["gaming" "media"]; +in { + mkHome = { + user ? "m3tam3re", + identity ? "private", + context ? null, + sets ? [], + }: let + # User preferences — always loaded (shell style, editor config, etc.) + preferencesPath = "${userPath}/${user}/preferences"; + + # Identity — git name/email, SSH match blocks, jj config + identityPath = "${userPath}/${user}/identities/${identity}.nix"; + + # Resolve context module + contextImport = + if context == null + then [] + else if builtins.hasAttr context contextModuleMap + then [contextModuleMap.${context}] + else throw "m3ta-home: unknown context '${context}'. Valid: desktop, server"; + + # Resolve set modules + setImports = + map + (s: + if builtins.hasAttr s setModuleMap + then setModuleMap.${s} + else throw "m3ta-home: unknown set '${s}'. Valid: ${lib.concatStringsSep ", " (builtins.attrNames setModuleMap)}") + sets; + + # Validation: desktop-only sets + usedDesktopOnlySets = + builtins.filter (s: builtins.elem s desktopOnlySets) sets; + in { + imports = + [ + baseModule + preferencesPath + identityPath + ] + ++ contextImport + ++ setImports; + + assertions = + [ + { + assertion = builtins.elem context ["desktop" "server" null]; + message = "m3ta-home: context must be 'desktop', 'server', or null (got: '${toString context}')"; + } + ] + ++ map (s: { + assertion = context == "desktop"; + message = "m3ta-home: set '${s}' requires context = 'desktop'"; + }) + usedDesktopOnlySets; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..f662a1e --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,33 @@ +# modules/default.nix — Export all m3ta-home modules as a HM module set. +# +# This allows nixos-config to import all modules at once: +# imports = [ inputs.m3ta-home.homeManagerModules.default ]; +# +# Individual modules declare their own options (mkEnableOption etc.) +# and are activated by mkHome's import mechanism. +inputs: let + lib = inputs.nixpkgs.lib; + + # Collect all .nix files recursively from a directory + collectModules = dir: + builtins.filterSource (path: _type: + lib.hasSuffix ".nix" (builtins.baseNameOf path)) + dir; +in { + default = { + imports = [ + # Profiles + ./../profiles/base + ./../profiles/contexts/desktop + ./../profiles/contexts/server + ./../profiles/sets/coding + ./../profiles/sets/gaming + ./../profiles/sets/media + + # Users + ./../users/m3tam3re/preferences + ./../users/m3tam3re/identities/private.nix + ./../users/m3tam3re/identities/work.nix + ]; + }; +} diff --git a/profiles/base/cli-tools/bat.nix b/profiles/base/cli-tools/bat.nix new file mode 100644 index 0000000..9a0e213 --- /dev/null +++ b/profiles/base/cli-tools/bat.nix @@ -0,0 +1,145 @@ +# Bat — cat replacement with nix-colors syntax highlighting theme. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.base.cliTools.bat; + palette = config.colorScheme.palette; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.bat.enable = (mkEnableOption "enable bat with nix-colors theme") // {default = true;}; + + config = mkIf cfg.enable { + programs.bat = { + enable = true; + config = {theme = "universal";}; + themes = { + universal = { + src = pkgs.writeText "universal.tmTheme" '' + + + + + name + Universal (nix-colors) + settings + + + settings + + background + #${palette.base00} + foreground + #${palette.base05} + caret + #${palette.base05} + selection + #${palette.base02} + selectionForeground + #${palette.base05} + lineHighlight + #${palette.base01} + + + + name + Comment + scope + comment + settings + + foreground + #${palette.base03} + fontStyle + italic + + + + name + String + scope + string + settings + + foreground + #${palette.base0A} + + + + name + Number + scope + constant.numeric + settings + + foreground + #${palette.base0E} + + + + name + Keyword + scope + keyword + settings + + foreground + #${palette.base08} + + + + name + Function + scope + entity.name.function + settings + + foreground + #${palette.base0B} + + + + name + Type + scope + entity.name.type, storage.type + settings + + foreground + #${palette.base0D} + + + + name + Variable + scope + variable + settings + + foreground + #${palette.base05} + + + + name + Constant + scope + constant + settings + + foreground + #${palette.base0E} + + + + + + ''; + }; + }; + }; + }; +} diff --git a/profiles/base/cli-tools/carapace.nix b/profiles/base/cli-tools/carapace.nix new file mode 100644 index 0000000..ea9194e --- /dev/null +++ b/profiles/base/cli-tools/carapace.nix @@ -0,0 +1,21 @@ +# Carapace — multi-shell completion engine with Fish, Nushell, and Bash integration. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.carapace; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.carapace.enable = (mkEnableOption "enable carapace completion engine") // {default = true;}; + + config = mkIf cfg.enable { + programs.carapace = { + enable = true; + enableFishIntegration = true; + enableNushellIntegration = true; + enableBashIntegration = true; + }; + }; +} diff --git a/profiles/base/cli-tools/default.nix b/profiles/base/cli-tools/default.nix new file mode 100644 index 0000000..3125597 --- /dev/null +++ b/profiles/base/cli-tools/default.nix @@ -0,0 +1,17 @@ +# CLI tools aggregator — imports all base command-line utilities. +{...}: { + imports = [ + ./bat.nix + ./carapace.nix + ./direnv.nix + ./eza.nix + ./fzf.nix + ./lf.nix + ./nitch.nix + ./packages.nix + ./television.nix + ./zellij.nix + ./zellij-ps.nix + ./zoxide.nix + ]; +} diff --git a/profiles/base/cli-tools/direnv.nix b/profiles/base/cli-tools/direnv.nix new file mode 100644 index 0000000..4ca206a --- /dev/null +++ b/profiles/base/cli-tools/direnv.nix @@ -0,0 +1,20 @@ +# Direnv — automatic environment loading with nix-direnv integration. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.direnv; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.direnv.enable = (mkEnableOption "enable direnv with nix-direnv") // {default = true;}; + + config = mkIf cfg.enable { + programs.direnv = { + enable = true; + enableNushellIntegration = true; + nix-direnv.enable = true; + }; + }; +} diff --git a/profiles/base/cli-tools/eza.nix b/profiles/base/cli-tools/eza.nix new file mode 100644 index 0000000..2e432a8 --- /dev/null +++ b/profiles/base/cli-tools/eza.nix @@ -0,0 +1,21 @@ +# Eza — modern ls replacement with icons, git status, and long format by default. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.eza; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.eza.enable = (mkEnableOption "enable eza modern ls replacement") // {default = true;}; + + config = mkIf cfg.enable { + programs.eza = { + enable = true; + enableFishIntegration = true; + enableBashIntegration = true; + extraOptions = ["-l" "--icons" "--git" "-a"]; + }; + }; +} diff --git a/profiles/base/cli-tools/fzf.nix b/profiles/base/cli-tools/fzf.nix new file mode 100644 index 0000000..4093298 --- /dev/null +++ b/profiles/base/cli-tools/fzf.nix @@ -0,0 +1,41 @@ +# Fuzzy finder with nix-colors palette and Wayland clipboard integration. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.fzf; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.fzf.enable = (mkEnableOption "enable fuzzy finder") // {default = true;}; + + config = mkIf cfg.enable { + programs.fzf = { + enable = true; + enableFishIntegration = true; + colors = { + "fg" = "#${config.colorScheme.palette.base05}"; + "bg" = "#${config.colorScheme.palette.base00}"; + "hl" = "#${config.colorScheme.palette.base0E}"; + "fg+" = "#${config.colorScheme.palette.base05}"; + "bg+" = "#${config.colorScheme.palette.base02}"; + "hl+" = "#${config.colorScheme.palette.base0E}"; + "info" = "#${config.colorScheme.palette.base09}"; + "prompt" = "#${config.colorScheme.palette.base0B}"; + "pointer" = "#${config.colorScheme.palette.base08}"; + "marker" = "#${config.colorScheme.palette.base08}"; + "spinner" = "#${config.colorScheme.palette.base09}"; + "header" = "#${config.colorScheme.palette.base03}"; + }; + defaultOptions = [ + "--preview='bat --color=always -n {}'" + "--bind 'ctrl-/:toggle-preview'" + "--header 'Press CTRL-Y to copy command into clipboard'" + "--bind 'ctrl-y:execute-silent(echo -n {2..} | wl-copy)+abort'" + ]; + defaultCommand = "fd --type f --exclude .git --follow --hidden"; + changeDirWidgetCommand = "fd --type d --exclude .git --follow --hidden"; + }; + }; +} diff --git a/profiles/base/cli-tools/lf.nix b/profiles/base/cli-tools/lf.nix new file mode 100644 index 0000000..50ff740 --- /dev/null +++ b/profiles/base/cli-tools/lf.nix @@ -0,0 +1,28 @@ +# Lf — terminal file manager with bat preview and Dracula theme. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.base.cliTools.lf; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.lf.enable = (mkEnableOption "enable lf terminal file manager") // {default = true;}; + + config = mkIf cfg.enable { + home.packages = [pkgs.lf]; + + programs.lf = { + enable = true; + settings = { + preview = true; + drawbox = true; + hidden = true; + icons = true; + previewer = "bat"; + }; + }; + }; +} diff --git a/profiles/base/cli-tools/nitch.nix b/profiles/base/cli-tools/nitch.nix new file mode 100644 index 0000000..eac4d62 --- /dev/null +++ b/profiles/base/cli-tools/nitch.nix @@ -0,0 +1,17 @@ +# Nitch — minimal system information display tool. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.base.cliTools.nitch; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.nitch.enable = (mkEnableOption "enable nitch") // {default = true;}; + + config = mkIf cfg.enable { + home.packages = [pkgs.nitch]; + }; +} diff --git a/profiles/base/cli-tools/packages.nix b/profiles/base/cli-tools/packages.nix new file mode 100644 index 0000000..aee3c41 --- /dev/null +++ b/profiles/base/cli-tools/packages.nix @@ -0,0 +1,62 @@ +# Essential CLI packages — core utilities always available on every host. +# NOTE: `lazylib` does not exist in nixpkgs. `lazygit` is the correct package +# (Git TUI) and is intentionally used here instead. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.base.cliTools.essentials; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.essentials.enable = (mkEnableOption "enable essential CLI packages") // {default = true;}; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + # Core utilities + coreutils + fd + htop + jq + ripgrep + + # Nix + alejandra + comma + nixd + nix-diff + nix-index + nix-update + + # Dev tools + bc + cmake + devenv + gcc + gnumake + go + httpie + just + lazygit + progress + sqlite + sqlite-vec + tldr + + # AI tools + fabric-ai + llm + + # Misc + basecamp + hyprpaper-random + libnotify + trash-cli + unzip + yazi + zip + ]; + }; +} diff --git a/profiles/base/cli-tools/television.nix b/profiles/base/cli-tools/television.nix new file mode 100644 index 0000000..3a74203 --- /dev/null +++ b/profiles/base/cli-tools/television.nix @@ -0,0 +1,60 @@ +# Television — fuzzy finder with custom channels for tldr, git-diff, and git-log. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.television; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.television.enable = (mkEnableOption "enable television") // {default = true;}; + + config = mkIf cfg.enable { + programs.television = { + enable = true; + channels = { + tldr = { + metadata = { + description = "Browse TLDR pages"; + name = "tldr"; + requirements = ["tldr"]; + }; + preview = { + command = "tldr '{}'"; + }; + source = { + command = "tldr --list"; + }; + }; + git-diff = { + metadata = { + description = "A channel to select files from git diff commands"; + name = "git-diff"; + requirements = ["git"]; + }; + preview = { + command = "git diff HEAD --color=always -- '{}'"; + }; + source = { + command = "git diff --name-only HEAD"; + }; + }; + git-log = { + metadata = { + description = "A channel to select from git log entries"; + name = "git-log"; + requirements = ["git"]; + }; + preview = { + command = "git show -p --stat --pretty=fuller --color=always '{0}'"; + }; + source = { + command = "git log --oneline --date=short --pretty=\"format:%h %s %an %cd\" \"$@\""; + output = "{split: :0}"; + }; + }; + }; + }; + }; +} diff --git a/profiles/base/cli-tools/zellij-ps.nix b/profiles/base/cli-tools/zellij-ps.nix new file mode 100644 index 0000000..8dac702 --- /dev/null +++ b/profiles/base/cli-tools/zellij-ps.nix @@ -0,0 +1,30 @@ +# Zellij-ps — project-aware Zellij session manager from m3ta-nixpkgs. +# Delegates to `cli.zellij-ps` — the home-manager module namespace provided by +# m3ta-nixpkgs (inputs.m3ta-nixpkgs.nixosModules.default). This is intentional; +# `cli.*` is the convention used by m3ta-nixpkgs home-manager modules. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.zellijPs; +in { + options.base.cliTools.zellijPs = { + # Enabled by default — base modules are always-on. + enable = (mkEnableOption "enable zellij-ps project session manager") // {default = true;}; + + projectFolders = mkOption { + type = types.listOf types.path; + description = "Project root folders scanned by zellij-ps."; + default = ["${config.home.homeDirectory}/p"]; + }; + }; + + config = mkIf cfg.enable { + cli.zellij-ps = { + enable = true; + projectFolders = cfg.projectFolders; + }; + }; +} diff --git a/profiles/base/cli-tools/zellij.nix b/profiles/base/cli-tools/zellij.nix new file mode 100644 index 0000000..efe2c6c --- /dev/null +++ b/profiles/base/cli-tools/zellij.nix @@ -0,0 +1,34 @@ +# Zellij terminal multiplexer with nix-colors theming. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.zellij; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.zellij.enable = (mkEnableOption "enable zellij multiplexer") // {default = true;}; + + config = mkIf cfg.enable { + programs.zellij = { + enable = true; + settings = { + theme = "universal"; + themes.universal = { + bg = "#${config.colorScheme.palette.base00}"; + fg = "#${config.colorScheme.palette.base05}"; + black = "#${config.colorScheme.palette.base01}"; + red = "#${config.colorScheme.palette.base08}"; + green = "#${config.colorScheme.palette.base0B}"; + yellow = "#${config.colorScheme.palette.base0A}"; + blue = "#${config.colorScheme.palette.base0D}"; + magenta = "#${config.colorScheme.palette.base0E}"; + cyan = "#${config.colorScheme.palette.base0C}"; + white = "#${config.colorScheme.palette.base07}"; + orange = "#${config.colorScheme.palette.base09}"; + }; + }; + }; + }; +} diff --git a/profiles/base/cli-tools/zoxide.nix b/profiles/base/cli-tools/zoxide.nix new file mode 100644 index 0000000..bc3e80e --- /dev/null +++ b/profiles/base/cli-tools/zoxide.nix @@ -0,0 +1,20 @@ +# Zoxide — smarter cd with Fish and Nushell integration. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.cliTools.zoxide; +in { + # Enabled by default — base modules are always-on. + options.base.cliTools.zoxide.enable = (mkEnableOption "enable zoxide smarter cd") // {default = true;}; + + config = mkIf cfg.enable { + programs.zoxide = { + enable = true; + enableFishIntegration = true; + enableNushellIntegration = true; + }; + }; +} diff --git a/profiles/base/default.nix b/profiles/base/default.nix new file mode 100644 index 0000000..0f220a2 --- /dev/null +++ b/profiles/base/default.nix @@ -0,0 +1,68 @@ +# profiles/base/default.nix — Always loaded on every host. +# +# Provides: +# - nixpkgs overlays and config (unfree, nix-colors, m3ta-nixpkgs) +# - Shell (nushell, fish, starship) with enable options +# - CLI tools (bat, carapace, direnv, eza, fzf, lf, nitch, television, zellij, zoxide) +# - Secrets management (pass-wayland) +# - Base packages (libgtop) +{ + inputs, + lib, + outputs, + pkgs, + system, + ... +}: { + imports = [ + inputs.nix-colors.homeManagerModules.default + inputs.m3ta-nixpkgs.homeManagerModules.default + + ./shell + ./cli-tools + ./secrets + ]; + + # ── nixpkgs configuration ── + nixpkgs = { + overlays = [ + outputs.overlays.temp-packages + outputs.overlays.stable-packages + outputs.overlays.locked-packages + outputs.overlays.pinned-packages + outputs.overlays.master-packages + + inputs.nur.overlays.default + inputs.m3ta-nixpkgs.overlays.default + inputs.m3ta-nixpkgs.overlays.modifications + (outputs.lib.mkLlmAgentsOverlay system) + ]; + config = { + allowUnfree = true; + allowUnfreePredicate = _: true; + }; + }; + + # ── Nix settings ── + nix = { + package = lib.mkDefault pkgs.nix; + settings = { + experimental-features = ["nix-command" "flakes"]; + warn-dirty = false; + }; + }; + + # ── Color scheme ── + colorScheme = inputs.nix-colors.colorSchemes.dracula; + + # ── Base packages ── + home.packages = with pkgs; [ + libgtop + ]; + + # ── Home Manager self-management ── + programs.home-manager.enable = true; + + # ── Default home state version ── + home.stateVersion = lib.mkDefault "26.05"; +} diff --git a/profiles/base/secrets/secrets.nix b/profiles/base/secrets/secrets.nix new file mode 100644 index 0000000..324546b --- /dev/null +++ b/profiles/base/secrets/secrets.nix @@ -0,0 +1,24 @@ +# Password store and secrets management via pass-wayland with OTP and import extensions. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.base.secrets; +in { + # Enabled by default — base modules are always-on. + options.base.secrets.enable = (mkEnableOption "enable secrets management") // {default = true;}; + + config = mkIf cfg.enable { + programs.password-store = { + enable = true; + package = + pkgs.pass-wayland.withExtensions + (exts: [exts.pass-otp exts.pass-import]); + settings = {PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store";}; + }; + home.packages = [pkgs.pinentry-gnome3]; + }; +} diff --git a/profiles/base/shell/default.nix b/profiles/base/shell/default.nix new file mode 100644 index 0000000..0b02d43 --- /dev/null +++ b/profiles/base/shell/default.nix @@ -0,0 +1,8 @@ +# Shell aggregator — imports Nushell (primary), Fish, and Starship prompt. +{...}: { + imports = [ + ./nushell.nix + ./fish.nix + ./starship.nix + ]; +} diff --git a/profiles/base/shell/fish.nix b/profiles/base/shell/fish.nix new file mode 100644 index 0000000..6c6e3ad --- /dev/null +++ b/profiles/base/shell/fish.nix @@ -0,0 +1,118 @@ +# Fish shell configuration exposed under the new base namespace. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.shell.fish; +in { + # Enabled by default — base modules are always-on. + options.base.shell.fish.enable = (mkEnableOption "enable fish shell") // {default = true;}; + + config = mkIf cfg.enable { + programs.fish = { + enable = true; + interactiveShellInit = '' + # Fish colors using universal nix-colors palette + # Text colors + set -g fish_color_normal ${config.colorScheme.palette.base05} # text + set -g fish_color_param ${config.colorScheme.palette.base05} # text + set -g fish_color_comment ${config.colorScheme.palette.base03} # muted + set -g fish_color_autosuggestion ${config.colorScheme.palette.base03} # muted + + # Command colors + set -g fish_color_command ${config.colorScheme.palette.base0D} # accent6 (blue) + set -g fish_color_quote ${config.colorScheme.palette.base0A} # accent3 (yellow) + set -g fish_color_redirection ${config.colorScheme.palette.base0E} # accent7 (purple) + set -g fish_color_end ${config.colorScheme.palette.base08} # accent1 (red) + set -g fish_color_error ${config.colorScheme.palette.base08} # accent1 (red) + set -g fish_color_operator ${config.colorScheme.palette.base0C} # accent5 (cyan) + set -g fish_color_escape ${config.colorScheme.palette.base09} # accent2 (orange) + + # Path colors + set -g fish_color_cwd ${config.colorScheme.palette.base0B} # accent4 (green) + set -g fish_color_cwd_root ${config.colorScheme.palette.base08} # accent1 (red) + set -g fish_color_valid_path --underline + + # Interactive colors + set -g fish_color_match ${config.colorScheme.palette.base0B} # accent4 (green) + set -g fish_color_selection --background=${config.colorScheme.palette.base02} # overlay + set -g fish_color_search_match --background=${config.colorScheme.palette.base02} # overlay + set -g fish_color_history_current --bold + set -g fish_color_user ${config.colorScheme.palette.base0B} # accent4 (green) + set -g fish_color_host ${config.colorScheme.palette.base0D} # accent6 (blue) + set -g fish_color_cancel -r + + # Pager colors + set -g fish_pager_color_completion normal + set -g fish_pager_color_description ${config.colorScheme.palette.base03} # muted + set -g fish_pager_color_prefix ${config.colorScheme.palette.base0E} # accent7 (purple) + set -g fish_pager_color_progress ${config.colorScheme.palette.base0B} # accent4 (green) + ''; + loginShellInit = '' + set -x NIX_PATH nixpkgs=channel:nixos-unstable + set -x NIX_LOG info + set -x WEBKIT_DISABLE_COMPOSITING_MODE 1 + set -x TERMINAL ghostty + set -x EDITOR nvim + set -x VISUAL zed + set -x XDG_DATA_HOME $HOME/.local/share + set -x FZF_CTRL_R_OPTS " + --preview='bat --color=always -n {}' + --preview-window up:3:hidden:wrap + --bind 'ctrl-/:toggle-preview' + --bind 'ctrl-y:execute-silent(echo -n {2..} | wl-copy)+abort' + --color header:bold + --header 'Press CTRL-Y to copy command into clipboard'" + set -x FZF_DEFAULT_COMMAND fd --type f --exclude .git --follow --hidden + set -x FZF_CTRL_T_COMMAND "$FZF_DEFAULT_COMMAND" + set -x FLAKE $HOME/p/nixos/nixos-config + source /run/agenix/${config.home.username}-secrets + + if test (tty) = "/dev/tty1" + exec uwsm start -F /run/current-system/sw/bin/Hyprland + end + if test (tty) = "/dev/tty2" + exec gamescope -O HDMI-A-1 -W 1920 -H 1080 --adaptive-sync --hdr-enabled --rt --steam -- steam -pipewire-dmabuf -tenfoot + end + ''; + shellAbbrs = { + ".." = "cd .."; + "..." = "cd ../.."; + b = "yazi"; + ls = "eza"; + l = "eza -l --icons --git -a"; + lt = "eza --tree --level=2 --long --icons --git"; + grep = "rg"; + ps = "procs"; + just = "just --unstable"; + node = "bun"; + npx = "bunx"; + fs = "du -ah . | sort -hr | head -n 10"; + + n = "nix"; + nd = "nix develop -c $SHELL"; + ns = "nix shell"; + nsn = "nix shell nixpkgs#"; + nb = "nix build"; + nbn = "nix build nixpkgs#"; + nf = "nix flake"; + + nr = "sudo nixos-rebuild --flake ."; + nrs = "sudo nixos-rebuild switch --flake .#(uname -n)"; + snr = "sudo nixos-rebuild --flake ."; + snrs = "sudo nixos-rebuild --flake . switch"; + hm = "home-manager --flake ."; + hms = "home-manager --flake . switch"; + hmr = "cd ~/projects/nix-configurations; nix flake lock --update-input dotfiles; home-manager --flake .#(whoami)@(hostname) switch"; + + tsu = "sudo tailscale up"; + tsd = "sudo tailscale down"; + + vi = "nvim"; + vim = "nvim"; + }; + }; + }; +} diff --git a/profiles/base/shell/nushell.nix b/profiles/base/shell/nushell.nix new file mode 100644 index 0000000..fccb7f0 --- /dev/null +++ b/profiles/base/shell/nushell.nix @@ -0,0 +1,86 @@ +# Primary shell configuration — Nushell with environment, aliases, and integrations. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.shell.nushell; +in { + # Enabled by default — base modules are always-on. + options.base.shell.nushell.enable = (mkEnableOption "enable nushell") // {default = true;}; + + config = mkIf cfg.enable { + programs.nushell = { + enable = true; + envFile.text = '' + $env.config.show_banner = false + $env.NIX_PATH = "nixpkgs=channel:nixos-unstable" + $env.NIX_LOG = "iunfo" + $env.WEBKIT_DISABLE_COMPOSITING_MODE = "1" + $env.TERMINAL = "ghostty" + $env.EDITOR = "nvim" + $env.VISUAL = "zeditor" + $env.FZF_DEFAULT_COMMAND = "fd --type f --exclude .git --follow --hidden" + $env.FZF_DEFAULT_OPTS = "--preview='bat --color=always -n {}' --bind 'ctrl-/:toggle-preview' --header 'Press CTRL-Y to copy command into clipboard' --bind 'ctrl-y:execute-silent(echo -n {2..} | wl-copy)+abort' --color bg:#282a36,bg+:#44475a,fg:#f8f8f2,fg+:#f8f8f2,header:#6272a4,hl:#bd93f9,hl+:#bd93f9,info:#ffb86c,marker:#ff79c6,pointer:#ff79c6,prompt:#50fa7b,spinner:#ffb86c" + $env.XDG_DATA_HOME = $"($env.HOME)/.local/share" + $env.SSH_AUTH_SOCK = "/run/user/1000/gnupg/S.gpg-agent.ssh" + $env.PATH = ($env.PATH | split row (char esep) | append $"($env.HOME)/.cache/.bun/bin" | append $"($env.HOME)/.npm-global/bin" | uniq) + $env.NPM_CONFIG_PREFIX = $"($env.HOME)/.npm-global" + $env.FLAKE = $"($env.HOME)/p/NIX/nixos-config" + + # Load kestractl-env from agenix + if ("/run/agenix/kestractl-env" | path exists) { + open /run/agenix/kestractl-env + | lines + | where {($in | str trim | str length) > 0} + | parse "{key}={value}" + | update value {str trim -c '"'} + | transpose -r -d + | load-env + } + ''; + + configFile.text = '' + # Aliases + alias .. = cd .. + alias ... = cd ... + alias h = cd $env.HOME + alias b = yazi + alias lt = eza --tree --level=2 --long --icons --git + alias grep = rg + alias just = just --unstable + + alias node = bun + alias npx = bunx + + alias n = nix + alias nd = nix develop -c $nu.current-shell + alias ns = nix shell + alias nsn = nix shell nixpkgs# + alias nb = nix build + alias nbn = nix build nixpkgs# + alias nf = nix flake + + alias nr = sudo nixos-rebuild --flake . + alias nrs = sudo nixos-rebuild switch --flake .#(sys host | get hostname) + alias snr = sudo nixos-rebuild --flake . + alias snrs = sudo nixos-rebuild --flake . switch + alias hm = home-manager --flake . + alias hms = home-manager --flake . switch + alias hmr = do { cd ~/projects/nix-configurations; nix flake lock --update-input dotfiles; home-manager --flake .#(whoami)@(hostname) switch } + + alias tsu = sudo tailscale up + alias tsd = sudo tailscale down + + alias vi = nvim + alias vim = nvim + + if (which tv | is-not-empty) { + mkdir ($nu.data-dir | path join "vendor/autoload") + tv init nu | save -f ($nu.data-dir | path join "vendor/autoload/tv.nu") + } + ''; + }; + }; +} diff --git a/profiles/base/shell/starship.nix b/profiles/base/shell/starship.nix new file mode 100644 index 0000000..5d467d6 --- /dev/null +++ b/profiles/base/shell/starship.nix @@ -0,0 +1,70 @@ +# Starship cross-shell prompt with nix-colors theming. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.base.shell.starship; +in { + # Enabled by default — base modules are always-on. + options.base.shell.starship.enable = (mkEnableOption "enable starship prompt") // {default = true;}; + + config = mkIf cfg.enable { + programs.starship = { + enable = true; + enableFishIntegration = true; + enableNushellIntegration = true; + settings = { + format = "$all$character"; + palette = "universal"; + + palettes.universal = { + background = "#${config.colorScheme.palette.base00}"; + surface = "#${config.colorScheme.palette.base01}"; + muted = "#${config.colorScheme.palette.base03}"; + text = "#${config.colorScheme.palette.base05}"; + bright = "#${config.colorScheme.palette.base07}"; + accent1 = "#${config.colorScheme.palette.base08}"; + accent2 = "#${config.colorScheme.palette.base09}"; + accent3 = "#${config.colorScheme.palette.base0A}"; + accent4 = "#${config.colorScheme.palette.base0B}"; + accent5 = "#${config.colorScheme.palette.base0C}"; + accent6 = "#${config.colorScheme.palette.base0D}"; + accent7 = "#${config.colorScheme.palette.base0E}"; + }; + + character = { + success_symbol = "[❯](accent7)"; + error_symbol = "[❯](accent1)"; + }; + + directory = { + style = "accent6"; + truncation_length = 3; + truncate_to_repo = false; + }; + + git_branch = { + style = "accent7"; + }; + + git_status = { + style = "accent5"; + }; + + cmd_duration = { + style = "accent3"; + }; + + hostname = { + style = "accent4"; + }; + + username = { + style_user = "accent2"; + }; + }; + }; + }; +} diff --git a/profiles/contexts/desktop/apps/crypto.nix b/profiles/contexts/desktop/apps/crypto.nix new file mode 100644 index 0000000..56b0ad8 --- /dev/null +++ b/profiles/contexts/desktop/apps/crypto.nix @@ -0,0 +1,16 @@ +# Cryptocurrency applications — Bisq, Monero GUI, and Trezor Suite. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.desktop.apps.crypto; +in { + options.desktop.apps.crypto.enable = mkEnableOption "enable crypto applications"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [bisq2 monero-gui trezor-suite]; + }; +} diff --git a/profiles/contexts/desktop/apps/default.nix b/profiles/contexts/desktop/apps/default.nix new file mode 100644 index 0000000..0888cfc --- /dev/null +++ b/profiles/contexts/desktop/apps/default.nix @@ -0,0 +1,10 @@ +# Desktop apps aggregator — Obsidian, Office, web apps, crypto tools, and productivity. +{...}: { + imports = [ + ./obsidian.nix + ./office.nix + ./webapps.nix + ./crypto.nix + ./productivity.nix + ]; +} diff --git a/profiles/contexts/desktop/apps/obsidian.nix b/profiles/contexts/desktop/apps/obsidian.nix new file mode 100644 index 0000000..588cb98 --- /dev/null +++ b/profiles/contexts/desktop/apps/obsidian.nix @@ -0,0 +1,25 @@ +# Obsidian knowledge base with markdown MIME association. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.desktop.apps.obsidian; +in { + options.desktop.apps.obsidian.enable = mkEnableOption "enable Obsidian knowledge base"; + + config = mkIf cfg.enable { + programs.obsidian.enable = true; + + xdg.mimeApps = { + enable = true; + associations.added = { + "text/markdown" = ["obsidian.desktop"]; + }; + defaultApplications = { + "text/markdown" = ["obsidian.desktop"]; + }; + }; + }; +} diff --git a/profiles/contexts/desktop/apps/office.nix b/profiles/contexts/desktop/apps/office.nix new file mode 100644 index 0000000..3d9c062 --- /dev/null +++ b/profiles/contexts/desktop/apps/office.nix @@ -0,0 +1,16 @@ +# Office and productivity applications — LibreOffice and document tools. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.desktop.apps.office; +in { + options.desktop.apps.office.enable = mkEnableOption "install office and paperwork apps"; + + config = mkIf cfg.enable { + home.packages = [pkgs.libreoffice-fresh]; + }; +} diff --git a/profiles/contexts/desktop/apps/productivity.nix b/profiles/contexts/desktop/apps/productivity.nix new file mode 100644 index 0000000..dd0c134 --- /dev/null +++ b/profiles/contexts/desktop/apps/productivity.nix @@ -0,0 +1,18 @@ +# Productivity tools — Pomodoro timer and focus utilities. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.desktop.apps.productivity; +in { + options.desktop.apps.productivity.enable = mkEnableOption "enable productivity tools"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + pomodoro-timer + ]; + }; +} diff --git a/profiles/contexts/desktop/apps/webapps.nix b/profiles/contexts/desktop/apps/webapps.nix new file mode 100644 index 0000000..8c34b96 --- /dev/null +++ b/profiles/contexts/desktop/apps/webapps.nix @@ -0,0 +1,56 @@ +# Web application desktop entries — Teams, Outlook, Basecamp, and OpenCode launchers. +{ + config, + pkgs, + ... +}: let + icons = { + teams = pkgs.fetchurl { + url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/microsoft-teams.svg"; + sha256 = "sha256-Pr9QS8nnXJq97r4/G3c6JXi34zxHl0ps9gcyI8cN/s8="; + }; + outlook = pkgs.fetchurl { + url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/microsoft-outlook.svg"; + sha256 = "sha256-3u8t5QNHFZvrAegxBiGicO4PjtMWhEaQSCv7MSSfLLc="; + }; + opencode = pkgs.fetchurl { + url = "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/opencode-dark.svg"; + sha256 = "1lms4f8habamvdh2qqqz9psx4py9wx23mmlkkds44pvrbq3bkj3n"; + }; + }; +in { + xdg.desktopEntries = { + teams = { + name = "Microsoft Teams"; + exec = "launch-webapp https://teams.microsoft.com"; + comment = "Open Microsoft Teams as a Desktop App"; + categories = ["Application" "Network" "Chat"]; + terminal = false; + icon = icons.teams; + }; + outlook = { + name = "Microsoft Outlook"; + exec = "launch-webapp https://outlook.office.com/mail/"; + comment = "Open Microsoft Outlook as a Desktop App"; + categories = ["Application" "Network"]; + terminal = false; + icon = icons.outlook; + }; + basecamp = { + name = "Basecamp"; + exec = "launch-webapp https://3.basecamp.com/5996442/"; + comment = "Open Basecamp as a Desktop App"; + categories = ["Application" "Network"]; + terminal = false; + icon = "${config.home.homeDirectory}/.local/share/icons/basecamp-logo.png"; + }; + opencode = { + name = "Opencode"; + exec = "rofi-project-opener"; + comment = "Open Opencode Terminal App"; + categories = ["Application" "Development"]; + terminal = false; + icon = icons.opencode; + }; + }; +} diff --git a/profiles/contexts/desktop/default.nix b/profiles/contexts/desktop/default.nix new file mode 100644 index 0000000..ac73f43 --- /dev/null +++ b/profiles/contexts/desktop/default.nix @@ -0,0 +1,125 @@ +# Desktop environment aggregator — only loaded when context=desktop. +# Includes window manager, applications, theming, and desktop session config. +{ + config, + pkgs, + ... +}: { + imports = [ + ./wm + ./apps + ./theme + ]; + + xdg = { + enable = true; + configFile."mimeapps.list".force = true; + mimeApps = { + enable = true; + associations.added = { + "application/zip" = ["org.gnome.FileRoller.desktop"]; + "application/csv" = ["calc.desktop"]; + "application/pdf" = ["okularApplication_pdf.desktop"]; + }; + defaultApplications = { + "application/zip" = ["org.gnome.FileRoller.desktop"]; + "application/csv" = ["calc.desktop"]; + "application/pdf" = ["okularApplication_pdf.desktop"]; + "application/md" = ["nvim.desktop"]; + "application/text" = ["nvim.desktop"]; + "x-scheme-handler/http" = ["io.github.zen_browser.zen"]; + "x-scheme-handler/https" = ["io.github.zen_browser.zen"]; + }; + }; + userDirs = { + enable = true; + createDirectories = true; + setSessionVariables = true; + }; + }; + + home.sessionVariables = { + WEBKIT_DISABLE_COMPOSITING_MODE = "1"; + NIXOS_OZONE_WL = "1"; + TERMINAL = "ghostty"; + QT_QPA_PLATFORM = "wayland"; + XDG_CURRENT_DESKTOP = "Hyprland"; + XDG_SESSION_TYPE = "wayland"; + XDG_SESSION_DESKTOP = "Hyprland"; + }; + + home.sessionPath = [ + "\${XDG_BIN_HOME}" + "\${HOME}/.cargo/bin" + "$HOME/.npm-global/bin" + "$HOME/.cache/.bun/bin" + ]; + + fonts.fontconfig.enable = true; + + programs.ghostty = { + enable = true; + enableFishIntegration = true; + enableBashIntegration = true; + settings = { + font-family = "Fira Code"; + copy-on-select = true; + foreground = "#${config.colorScheme.palette.base05}"; + background = "#${config.colorScheme.palette.base00}"; + selection-foreground = "#${config.colorScheme.palette.base07}"; + selection-background = "#${config.colorScheme.palette.base02}"; + cursor-color = "#${config.colorScheme.palette.base05}"; + palette = [ + "0=#${config.colorScheme.palette.base01}" + "1=#${config.colorScheme.palette.base08}" + "2=#${config.colorScheme.palette.base0B}" + "3=#${config.colorScheme.palette.base0A}" + "4=#${config.colorScheme.palette.base0D}" + "5=#${config.colorScheme.palette.base0E}" + "6=#${config.colorScheme.palette.base0C}" + "7=#${config.colorScheme.palette.base05}" + "8=#${config.colorScheme.palette.base03}" + "9=#${config.colorScheme.palette.base08}" + "10=#${config.colorScheme.palette.base0B}" + "11=#${config.colorScheme.palette.base0A}" + "12=#${config.colorScheme.palette.base0D}" + "13=#${config.colorScheme.palette.base0E}" + "14=#${config.colorScheme.palette.base0C}" + "15=#${config.colorScheme.palette.base07}" + ]; + }; + }; + + home.pointerCursor = { + gtk.enable = true; + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Ice"; + size = 20; + }; + + home.packages = with pkgs; [ + appimage-run + bemoji + brave + distrobox + eigent + (element-desktop.override { + commandLineArgs = "--password-store=gnome-libsecret"; + }) + launch-webapp + file-roller + hyprpanel + seahorse + sushi + ksnip + msty-studio + nwg-look + rose-pine-hyprcursor + remmina + slack + telegram-desktop + vivaldi + vivaldi-ffmpeg-codecs + vibetyper + ]; +} diff --git a/profiles/contexts/desktop/theme/default.nix b/profiles/contexts/desktop/theme/default.nix new file mode 100644 index 0000000..8445fe5 --- /dev/null +++ b/profiles/contexts/desktop/theme/default.nix @@ -0,0 +1,8 @@ +# Theme aggregator — fonts, GTK/Qt theming, and wallpapers. +{...}: { + imports = [ + ./fonts.nix + ./theme.nix + ./wallpapers.nix + ]; +} diff --git a/profiles/contexts/desktop/theme/fonts.nix b/profiles/contexts/desktop/theme/fonts.nix new file mode 100644 index 0000000..95eb69c --- /dev/null +++ b/profiles/contexts/desktop/theme/fonts.nix @@ -0,0 +1,24 @@ +# Font packages — Fira Code, JetBrains Mono Nerd Font, and supporting icon fonts. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.desktop.theme.fonts; +in { + options.desktop.theme.fonts.enable = mkEnableOption "install desktop fonts"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + fira-code + fira-code-symbols + nerd-fonts.fira-code + nerd-fonts.jetbrains-mono + font-manager + font-awesome_5 + noto-fonts + ]; + }; +} diff --git a/profiles/contexts/desktop/theme/theme.nix b/profiles/contexts/desktop/theme/theme.nix new file mode 100644 index 0000000..c78c598 --- /dev/null +++ b/profiles/contexts/desktop/theme/theme.nix @@ -0,0 +1,24 @@ +# GTK and Qt theming — Dracula theme with matching icons and cursor. +{ + pkgs, + config, + ... +}: { + qt = { + enable = true; + platformTheme.name = "gtk"; + }; + + gtk = { + enable = true; + theme = { + name = "Dracula"; + package = pkgs.dracula-theme; + }; + iconTheme = { + name = "Dracula"; + package = pkgs.dracula-icon-theme; + }; + gtk4.theme = config.gtk.theme; + }; +} diff --git a/profiles/contexts/desktop/theme/wallpapers.nix b/profiles/contexts/desktop/theme/wallpapers.nix new file mode 100644 index 0000000..bcf6c34 --- /dev/null +++ b/profiles/contexts/desktop/theme/wallpapers.nix @@ -0,0 +1,19 @@ +# Wallpaper collection — copies wallpapers to Hyprland config directory. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.desktop.theme.wallpapers.enable; +in { + options.desktop.theme.wallpapers.enable = mkEnableOption "wallpapers for Hyprland"; + + config = mkIf cfg { + xdg.configFile."hypr/wallpapers" = { + # Wallpapers are stored relative to the home/m3tam3re directory. + source = ../../m3tam3re/wallpapers; + recursive = true; + }; + }; +} diff --git a/profiles/contexts/desktop/wm/default.nix b/profiles/contexts/desktop/wm/default.nix new file mode 100644 index 0000000..796b018 --- /dev/null +++ b/profiles/contexts/desktop/wm/default.nix @@ -0,0 +1,8 @@ +# Window manager aggregator — Hyprland, Wayland tools, and Rofi launcher. +{...}: { + imports = [ + ./hyprland.nix + ./wayland.nix + ./rofi.nix + ]; +} diff --git a/profiles/contexts/desktop/wm/hyprland.nix b/profiles/contexts/desktop/wm/hyprland.nix new file mode 100644 index 0000000..75e3cd8 --- /dev/null +++ b/profiles/contexts/desktop/wm/hyprland.nix @@ -0,0 +1,318 @@ +# Hyprland window manager with keybindings, window rules, idle/lock, and hyprpaper. +{ + config, + lib, + ... +}: +with lib; let + cfg = config.desktop.wm.hyprland; +in { + options.desktop.wm.hyprland.enable = mkEnableOption "Hyprland window manager"; + + config = mkIf cfg.enable { + wayland.windowManager.hyprland = { + settings = { + xwayland = { + force_zero_scaling = true; + }; + + exec-once = [ + "hyprpanel" + "while ! hyprpaper-random; do sleep 0.5; done" + "wl-paste --type text --watch cliphist store" + "wl-paste --type image --watch cliphist store" + "vibetyper" + ]; + + env = [ + "XCURSOR_SIZE,32" + "HYPRCURSOR_THEME,Bibata-Modern-Ice" + "WLR_NO_HARDWARE_CURSORS,1" + "GTK_THEME,Dracula" + "XDG_CURRENT_DESKTOP,Hyprland" + "XDG_SESSION_TYPE,wayland" + "XDG_SESSION_DESKTOP,Hyprland" + "XKB_DEFAULT_LAYOUT,de" + "NIXOS_OZONE_WL,1" + ]; + + input = { + kb_layout = "de,us"; + kb_variant = ""; + kb_model = ""; + kb_rules = ""; + kb_options = "ctrl:nocaps"; + follow_mouse = 1; + }; + + general = { + gaps_in = 5; + gaps_out = 5; + border_size = 1; + "col.active_border" = "rgba(9742b5ee) rgba(9742b5ee) 45deg"; + "col.inactive_border" = "rgba(${config.colorScheme.palette.base03}aa)"; + layout = "dwindle"; + }; + + decoration = { + shadow = { + enabled = true; + range = 60; + render_power = 3; + color = "rgba(${config.colorScheme.palette.base00}66)"; + offset = "1 2"; + scale = 0.97; + }; + rounding = 8; + blur = { + enabled = true; + size = 3; + passes = 3; + }; + active_opacity = 0.9; + inactive_opacity = 0.5; + }; + + animations = { + enabled = true; + bezier = "myBezier, 0.05, 0.9, 0.1, 1.05"; + animation = [ + "windows, 1, 7, myBezier" + "windowsOut, 1, 7, default, popin 80%" + "border, 1, 10, default" + "borderangle, 1, 8, default" + "fade, 1, 7, default" + "workspaces, 1, 6, default" + ]; + }; + + dwindle = { + pseudotile = true; + preserve_split = true; + }; + + master = { + new_status = "master"; + }; + + device = [ + { + name = "epic-mouse-v1"; + sensitivity = -0.5; + } + { + name = "zsa-technology-labs-moonlander-mark-i"; + kb_layout = "us"; + } + { + name = "keychron-keychron-k7"; + kb_layout = "us"; + } + ]; + + windowrule = [ + "match:class file_progress, float on" + "match:class confirm, float on" + "match:class dialog, float on" + "match:class download, float on" + "match:class notification, float on" + "match:class error, float on" + "match:class splash, float on" + "match:class confirmreset, float on" + "match:title Open File, float on" + "match:title branchdialog, float on" + "match:class pavucontrol-qt, float on" + "match:class pavucontrol, float on" + "match:class class:^(espanso)$, float on" + "match:class wlogout, fullscreen on" + "match:title wlogout, float on" + "match:title wlogout, fullscreen on" + "match:class mpv, float on" + "match:class mpv, idle_inhibit focus" + "match:class mpv, opacity 1.0 override" + "match:title ^(Media viewer)$, float on" + "match:title ^(Volume Control)$, float on" + "match:title ^(Picture-in-Picture)$, float on" + "match:title ^(floating-pomodoro)$, float on" + "match:title ^(floating-pomodoro)$, size 250 50" + "match:title ^(floating-pomodoro)$, move 12 (monitor_h-150)" + "match:title ^(floating-pomodoro)$, pin on" + "match:initial_title .*streamlabs.com.*, float on" + "match:initial_title .*streamlabs.com.*, pin on" + "match:initial_title .*streamlabs.com.*, size 800 400" + "match:initial_title .*alert-box.*, move 100%-820 102" + "match:initial_title .*chat-box.*, move 100%-820 512" + "match:initial_title .*streamlabs.com.*, opacity 0.5 override" + "match:initial_title .*streamlabs.com.*, idle_inhibit focus" + "match:initial_title .*streamlabs.com.*, no_anim on" + "match:initial_title .*streamlabs.com.*, decorate off" + "match:initial_title .*streamlabs.com.*, no_shadow on" + "match:initial_title .*streamlabs.com.*, no_blur on" + "match:class ^vibe-typer$, match:title ^Recording Indicator$, no_blur on" + "border_color rgb(ffffff), match:xwayland 1" + ]; + + "$mainMod" = "SUPER"; + "$terminal" = "ghostty"; + + bind = [ + "$mainMod, return, exec, $terminal nu -c zellij-ps" + "$mainMod, t, exec, $terminal -e nu -c 'nitch; exec nu'" + "$mainMod SHIFT, t, exec, launch-timer" + "$mainMod, n, exec, $terminal -e nvim" + "$mainMod, z, exec, uwsm app -- zeditor" + "$mainMod, o, exec, hyprctl dispatch setprop activewindow opaque toggle" + "$mainMod, r, exec, hyprctl dispatch focuswindow \"initialtitle:.*alert-box.*\" && hyprctl dispatch moveactive exact 4300 102 && hyprctl dispatch focuswindow \"initialtitle:.*chat-box.*\" && hyprctl dispatch moveactive exact 4300 512" + "$mainMod, b, exec, uwsm app -- thunar" + "$mainMod SHIFT, B, exec, uwsm app -- vivaldi" + "$mainMod, Escape, exec, uwsm app -- wlogout -p layer-shell" + "$mainMod, Space, togglefloating" + "$mainMod, q, killactive" + "$mainMod, M, exit" + "$mainMod, F, fullscreen" + "$mainMod SHIFT, V, togglefloating" + "$mainMod, D, exec, uwsm app -- rofi -show drun -run-command \"uwsm app -- {cmd}\"" + "$mainMod, V, exec, uwsm app -- cliphist list | rofi -dmenu | cliphist decode | wl-copy" + "$mainMod, C, exec, bash -c 'FILE=/tmp/screenshot_$(date +%s).png; grim -g \"$(slurp)\" \"$FILE\" && ksnip \"$FILE\"'" + "$mainMod SHIFT, S, exec, uwsm app -- rofi -show emoji" + "$mainMod, P, exec, uwsm app -- rofi-pass" + "$mainMod SHIFT, P, pseudo" + "$mainMod, R, exec, stt-ptt start" + "$mainMod, S, exec, stt-ptt start" + "$mainMod, J, togglesplit" + "$mainMod, h, movefocus, l" + "$mainMod, l, movefocus, r" + "$mainMod, k, movefocus, u" + "$mainMod, j, movefocus, d" + "$mainMod, 1, workspace, 1" + "$mainMod, 2, workspace, 2" + "$mainMod, 3, workspace, 3" + "$mainMod, 4, workspace, 4" + "$mainMod, 5, workspace, 5" + "$mainMod, 6, workspace, 6" + "$mainMod, 7, workspace, 7" + "$mainMod, 8, workspace, 8" + "$mainMod, 9, workspace, 9" + "$mainMod, 0, workspace, 10" + "$mainMod SHIFT, 1, movetoworkspace, 1" + "$mainMod SHIFT, 2, movetoworkspace, 2" + "$mainMod SHIFT, 3, movetoworkspace, 3" + "$mainMod SHIFT, 4, movetoworkspace, 4" + "$mainMod SHIFT, 5, movetoworkspace, 5" + "$mainMod SHIFT, 6, movetoworkspace, 6" + "$mainMod SHIFT, 7, movetoworkspace, 7" + "$mainMod SHIFT, 8, movetoworkspace, 8" + "$mainMod SHIFT, 9, movetoworkspace, 9" + "$mainMod SHIFT, 0, movetoworkspace, 10" + "$mainMod, mouse_down, workspace, e+1" + "$mainMod, mouse_up, workspace, e-1" + ]; + + bindr = [ + "$mainMod, R, exec, stt-ptt stop" + "$mainMod, S, exec, stt-ptt format-stop" + ]; + + bindm = [ + "$mainMod, mouse:272, movewindow" + "$mainMod, mouse:273, resizewindow" + ]; + }; + }; + + services.hypridle = { + enable = true; + settings = { + general = { + before_sleep_cmd = "hyprlock"; + after_sleep_cmd = "hyprctl dispatch dpms on"; + inhibit_sleep = 3; + }; + listener = [ + { + timeout = 300; + on-timeout = "hyprlock"; + } + { + timeout = 420; + on-timeout = "hyprctl dispatch dpms off"; + on-resume = "hyprctl dispatch dpms on"; + } + ]; + }; + }; + + services.hyprpaper.enable = true; + + programs.hyprlock = { + enable = true; + settings = { + "$font" = "JetBrainsMono Nerd Font"; + "$base" = "rgb(${config.colorScheme.palette.base00})"; + "$text" = "rgb(${config.colorScheme.palette.base05})"; + "$textAlpha" = "${config.colorScheme.palette.base05}"; + "$accentAlpha" = "${config.colorScheme.palette.base0D}"; + "$red" = "rgb(${config.colorScheme.palette.base08})"; + "$yellow" = "rgb(${config.colorScheme.palette.base0A})"; + + general = { + hide_cursor = true; + }; + + background = { + monitor = ""; + path = "${config.home.homeDirectory}/.config/hypr/wallpapers/wallhaven-lmmo8r.jpg"; + blur_passes = 0; + color = "rgb(${config.colorScheme.palette.base00})"; + }; + + label = [ + { + monitor = ""; + text = "$TIME"; + color = "$text"; + font_size = 90; + font_family = "$font"; + position = "30, 0"; + halign = "left"; + valign = "top"; + } + { + monitor = ""; + text = ''cmd[update:43200000] echo "$(date +"%A, %d %B %Y")"''; + color = "$text"; + font_size = 25; + font_family = "$font"; + position = "30, -150"; + halign = "left"; + valign = "top"; + } + ]; + + input-field = [ + { + monitor = ""; + size = "300, 60"; + outline_thickness = 4; + dots_size = 0.2; + dots_spacing = 0.2; + dots_center = true; + outer_color = "rgb(${config.colorScheme.palette.base0D})"; + inner_color = "rgb(${config.colorScheme.palette.base00})"; + font_color = "rgb(${config.colorScheme.palette.base05})"; + fade_on_empty = false; + placeholder_text = ''󰌾 Logged in as $USER''; + hide_input = false; + check_color = "rgb(${config.colorScheme.palette.base0D})"; + fail_color = "rgb(${config.colorScheme.palette.base08})"; + fail_text = ''$FAIL ($ATTEMPTS)''; + capslock_color = "rgb(${config.colorScheme.palette.base0A})"; + position = "0, -35"; + halign = "center"; + valign = "center"; + } + ]; + }; + }; + }; +} diff --git a/profiles/contexts/desktop/wm/rofi.nix b/profiles/contexts/desktop/wm/rofi.nix new file mode 100644 index 0000000..d3c3a76 --- /dev/null +++ b/profiles/contexts/desktop/wm/rofi.nix @@ -0,0 +1,207 @@ +# Rofi application launcher with nix-colors theme, pass integration, and project opener. +{ + config, + pkgs, + lib, + ... +}: +with lib; let + cfg = config.desktop.wm.rofi; +in { + options.desktop.wm.rofi.enable = mkEnableOption "enable rofi"; + + config = mkIf cfg.enable { + programs.rofi = { + enable = true; + package = pkgs.rofi.override { + plugins = [ + pkgs.rofi-calc + pkgs.rofi-emoji + pkgs.stable.rofi-file-browser + ]; + }; + pass = { + enable = true; + package = pkgs.rofi-pass-wayland; + }; + terminal = "${pkgs.ghostty}/bin/ghostty"; + font = "Fira Code"; + extraConfig = { + show-icons = true; + disable-history = false; + modi = "drun,calc,emoji,filebrowser"; + kb-primary-paste = "Control+V,Shift+Insert"; + kb-secondary-paste = "Control+v,Insert"; + }; + theme = let + inherit (config.colorScheme) palette; + in + builtins.toString (pkgs.writeText "rofi-universal-theme.rasi" '' + * { + /* Universal theme colors from nix-colors */ + background: #${palette.base00}; + surface: #${palette.base01}; + overlay: #${palette.base02}; + muted: #${palette.base03}; + subtle: #${palette.base04}; + text: #${palette.base05}; + bright-text: #${palette.base06}; + highlight: #${palette.base07}; + accent1: #${palette.base08}; + accent2: #${palette.base09}; + accent3: #${palette.base0A}; + accent4: #${palette.base0B}; + accent5: #${palette.base0C}; + accent6: #${palette.base0D}; + accent7: #${palette.base0E}; + accent8: #${palette.base0F}; + + /* Global properties */ + background-color: @background; + text-color: @text; + font: "Fira Code 12"; + border: 0; + margin: 0; + padding: 0; + spacing: 0; + } + + window { + background-color: @background; + border: 1px; + border-color: @accent7; + border-radius: 6px; + width: 40%; + padding: 16px; + } + + inputbar { + children: [ prompt, entry ]; + spacing: 12px; + padding: 8px; + border-radius: 4px; + background-color: @surface; + } + + prompt { + text-color: @accent7; + background-color: transparent; + } + + entry { + placeholder: "Search..."; + placeholder-color: @subtle; + text-color: @text; + background-color: transparent; + cursor-color: @accent7; + } + + message { + background-color: @surface; + border-radius: 4px; + padding: 8px; + margin: 8px 0; + } + + textbox { + text-color: @text; + background-color: transparent; + } + + listview { + background-color: transparent; + margin: 8px 0 0; + lines: 10; + columns: 1; + fixed-height: true; + scrollbar: false; + } + + element { + background-color: transparent; + text-color: @text; + padding: 8px; + border-radius: 4px; + spacing: 8px; + } + + element normal.normal { + background-color: transparent; + text-color: @text; + } + + element selected.normal { + background-color: @accent7; + text-color: @background; + } + + element alternate.normal { + background-color: transparent; + text-color: @text; + } + + element-icon { + background-color: transparent; + size: 24px; + } + + element-text { + background-color: transparent; + text-color: inherit; + vertical-align: 0.5; + } + + mode-switcher { + spacing: 0; + background-color: @surface; + border-radius: 4px; + margin: 8px 0 0; + } + + button { + padding: 8px 16px; + background-color: transparent; + text-color: @text; + border-radius: 4px; + } + + button selected { + background-color: @accent7; + text-color: @background; + } + + scrollbar { + width: 4px; + border: 0; + handle-color: @accent7; + handle-width: 4px; + padding: 0; + } + ''); + }; + + cli.rofi-project-opener = { + enable = true; + projectDirs = { + AI = { + path = "~/p/AI"; + args = ""; + }; + CHAT = { + path = "~/p/CHAT"; + args = "--agent chiron"; + }; + MISC = { + path = "~/p/MISC"; + args = "--agent chiron-forge"; + }; + NIX = { + path = "~/p/NIX"; + args = ""; + }; + }; + terminal = pkgs.ghostty; + terminalCommand = "opencode %a"; + }; + }; +} diff --git a/profiles/contexts/desktop/wm/wayland.nix b/profiles/contexts/desktop/wm/wayland.nix new file mode 100644 index 0000000..1429d35 --- /dev/null +++ b/profiles/contexts/desktop/wm/wayland.nix @@ -0,0 +1,30 @@ +# Wayland extra tooling — screenshot, clipboard, cursor, and display utilities. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.desktop.wm.wayland; +in { + options.desktop.wm.wayland.enable = mkEnableOption "wayland extra tools and config"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + grim + hyprcursor + hyprlock + hyprpaper + qt6.qtwayland + slurp + waypipe + wl-clipboard + wf-recorder + wl-mirror + wlogout + wtype + ydotool + ]; + }; +} diff --git a/profiles/contexts/server/default.nix b/profiles/contexts/server/default.nix new file mode 100644 index 0000000..2c6d8ea --- /dev/null +++ b/profiles/contexts/server/default.nix @@ -0,0 +1,6 @@ +# Server context home-manager configuration — minimal headless setup. +# Loaded on server hosts: m3-atlas, m3-helios, m3-aether. +{...}: { + # Server hosts use the base and coding modules directly. + # No desktop environment or GUI applications. +} diff --git a/profiles/sets/coding/agents/agents.nix b/profiles/sets/coding/agents/agents.nix new file mode 100644 index 0000000..ed4d6a5 --- /dev/null +++ b/profiles/sets/coding/agents/agents.nix @@ -0,0 +1,85 @@ +# AI agent system — OpenCode, Pi, and MCP server configuration. +# Relies on coding.agents options provided by home/common/default.nix +# (inputs.m3ta-nixpkgs.homeManagerModules.default). +{ + config, + inputs, + lib, + pkgs, + videoDrivers ? [], + ... +}: { + # Agent Git Identity configuration + # Note: Uses existing gitea SSH key (m3tam3re identity) for push auth + coding.agents.gitIdentity = { + enable = true; + name = "m3ta-chiron"; + email = "m3ta-chiron@agentmail.to"; + sshKey = "/home/m3tam3re/.ssh/gitea"; + }; + + imports = [ + # OpenCode and Pi agent configurations + ./opencode.nix + ./pi.nix + ]; + + coding.agents.skills = { + agentsInput = inputs.agents; + externalSkills = [ + { + src = inputs.skills-anthropic; + selectSkills = ["pdf" "docx" "frontend-design"]; + } + {src = inputs.skills-superpowers;} + {src = inputs.skills-vercel;} + {src = inputs.skills-basecamp;} + {src = inputs.skills-kestra;} + ]; + }; + + programs.mcp = { + enable = true; + servers = { + DeepWiki = { + url = "https://mcp.deepwiki.com/mcp"; + }; + Ref = { + command = "bash"; + args = ["-c" "REF_API_KEY=$(cat /run/agenix/ref-key) exec bunx ref-tools-mcp@latest"]; + }; + Exa = { + command = "bash"; + args = ["-c" "EXA_API_KEY=$(cat /run/agenix/exa-key) exec bunx exa-mcp-server@latest tools=web_search_exa"]; + }; + Outline = { + url = "https://wiki.az-gruppe.com/mcp"; + }; + ContextMode = { + command = "bash"; + args = ["-c" "exec bunx context-mode@latest"]; + }; + Honcho = { + command = "bash"; + args = [ + "-c" + ''exec bunx mcp-remote@latest https://mcp.honcho.dev --header "Authorization:Bearer $(cat /run/agenix/honcho-key)" --header "X-Honcho-User-Name:m3tam3re"'' + ]; + }; + }; + }; + + home.packages = with pkgs; [ + agenix-cli + agent-browser + beads + pi + (qmd.override { + vulkanSupport = videoDrivers == ["amdgpu"]; + cudaSupport = videoDrivers == ["nvidia"]; + }) + # opencode-desktop + openshell + openspec + ]; +} diff --git a/profiles/sets/coding/agents/opencode.nix b/profiles/sets/coding/agents/opencode.nix new file mode 100644 index 0000000..5f13825 --- /dev/null +++ b/profiles/sets/coding/agents/opencode.nix @@ -0,0 +1,260 @@ +{ + inputs, + lib, + ... +}: { + coding.agents.opencode = { + enable = true; + agentsInput = inputs.agents; + }; + + coding.opencode = { + enable = true; + + ohMyOpencodeSettings = { + agents = { + sisyphus.model = "litellm/claude-opus-4-6"; + oracle.model = "litellm/claude-sonnet-4-6"; + librarian.model = "litellm/claude-sonnet-4-6"; + explore.model = "litellm/claude-haiku-4-5"; + multimodal-looker.model = "litellm/gpt-5.3-codex"; + prometheus.model = "litellm/claude-opus-4-6"; + metis.model = "litellm/claude-opus-4-6"; + momus.model = "litellm/claude-opus-4-6"; + atlas.model = "litellm/claude-sonnet-4-6"; + }; + categories = { + visual-engineering.model = "zai-coding-plan/glm-5.1"; + ultrabrain.model = "litellm/claude-opus-4-6"; + deep.model = "litellm/claude-sonnet-4-6"; + artistry.model = "zai-coding-plan/glm-5.1"; + quick.model = "litellm/claude-haiku-4-5"; + unspecified-low.model = "litellm/claude-sonnet-4-6"; + unspecified-high.model = "litellm/claude-opus-4-6"; + writing.model = "zai-coding-plan/glm-5.1"; + }; + }; + }; + + # Keep TUI settings in programs.opencode.tui to satisfy OpenCode v1.2.15+. + programs.opencode.tui.theme = "opencode"; + + # Override legacy default settings to avoid deprecated TUI keys in settings. + programs.opencode.settings = lib.mkForce { + plugin = ["oh-my-openagent"]; + formatter = { + alejandra = { + command = ["alejandra" "-q" "-"]; + extensions = [".nix"]; + }; + }; + + # Security: permission hardening for OpenCode + # Last matching rule wins. Glob patterns: * = any chars, ? = single char. + # ~ and $HOME are expanded to the user's home directory. + # external_directory gates paths outside the working directory. + permission = { + # External directory access: ask by default, allow safe paths + "external_directory" = { + "*" = "ask"; + "/nix/store/**" = "allow"; + "/tmp/**" = "allow"; + }; + + # Read access: allow by default, deny sensitive paths + "read" = { + "*" = "allow"; + "~/.ssh/**" = "deny"; + "~/.gnupg/**" = "deny"; + "~/.aws/**" = "deny"; + "~/.kube/**" = "deny"; + "~/.config/gh/**" = "deny"; + "~/.config/gcloud/**" = "deny"; + "~/.config/op/**" = "deny"; + "~/.config/sops/**" = "deny"; + "/run/agenix/**" = "deny"; + "~/.pi/agent/auth.json" = "deny"; + "~/.pi/agent/sessions/**" = "deny"; + "*.env" = "deny"; + "*.env.*" = "deny"; + "*.pem" = "deny"; + "*.key" = "deny"; + "*.p12" = "deny"; + "*.pfx" = "deny"; + "*id_rsa*" = "deny"; + "*id_ed25519*" = "deny"; + "*id_ecdsa*" = "deny"; + "*.example.env" = "allow"; + "*.sample.env" = "allow"; + "*.test.env" = "allow"; + ".env.example" = "allow"; + ".env.sample" = "allow"; + ".env.test" = "allow"; + "~/.ssh/*.pub" = "allow"; + "*.pub" = "allow"; + "*.csr" = "allow"; + }; + + # Edit access: ask by default, deny sensitive paths + "edit" = { + "*" = "ask"; + "~/.ssh/**" = "deny"; + "~/.gnupg/**" = "deny"; + "~/.aws/**" = "deny"; + "~/.kube/**" = "deny"; + "~/.config/gh/**" = "deny"; + "~/.config/gcloud/**" = "deny"; + "~/.config/op/**" = "deny"; + "~/.config/sops/**" = "deny"; + "/run/agenix/**" = "deny"; + "~/.pi/agent/auth.json" = "deny"; + "~/.pi/agent/sessions/**" = "deny"; + "*.env" = "deny"; + "*.env.*" = "deny"; + "*.pem" = "deny"; + "*.key" = "deny"; + "*.p12" = "deny"; + "*.pfx" = "deny"; + "*id_rsa*" = "deny"; + "*id_ed25519*" = "deny"; + "*id_ecdsa*" = "deny"; + "~/.ssh/*.pub" = "allow"; + "*.pub" = "allow"; + "*.csr" = "allow"; + }; + + # Glob patterns: same rules as read for file matching + "glob" = { + "*" = "allow"; + "~/.ssh/**" = "deny"; + "~/.gnupg/**" = "deny"; + "/run/agenix/**" = "deny"; + "*.env" = "deny"; + "*.env.*" = "deny"; + "*.pem" = "deny"; + "*.key" = "deny"; + "*.p12" = "deny"; + "*.pfx" = "deny"; + }; + + # Grep: allow search, but deny searching for secrets + "grep" = { + "*" = "allow"; + "~/.ssh/**" = "deny"; + "~/.gnupg/**" = "deny"; + "/run/agenix/**" = "deny"; + "*PASSWORD*" = "ask"; + "*SECRET*" = "ask"; + "*API_KEY*" = "ask"; + "*PRIVATE_KEY*" = "ask"; + }; + + # Bash: ask by default, deny dangerous and env-leak commands + "bash" = { + "*" = "ask"; + "git status*" = "allow"; + "git diff*" = "allow"; + "git log*" = "allow"; + "git branch*" = "allow"; + "git show*" = "allow"; + "git remote*" = "allow"; + "nix --version" = "allow"; + "nix eval*" = "allow"; + "nix build*" = "allow"; + "nix develop*" = "allow"; + "nix shell*" = "allow"; + "nix search*" = "allow"; + "alejandra*" = "allow"; + "git add*" = "allow"; + "git commit*" = "allow"; + "git push*" = "ask"; + "git pull*" = "allow"; + "rm *" = "ask"; + "rm -rf *" = "deny"; + "sudo *" = "ask"; + "env" = "deny"; + "printenv" = "deny"; + "cat /proc/*/environ" = "deny"; + "gpg *--export-secret*" = "deny"; + "ssh-add -D" = "deny"; + "docker run --privileged*" = "deny"; + "curl *| *sh" = "deny"; + "wget *| *sh" = "deny"; + }; + + # Web fetch: ask for sensitive URLs + "webfetch" = { + "*" = "ask"; + "https://api.github.com*" = "allow"; + "https://search.nixos.org*" = "allow"; + }; + + # Doom loop guard + "doom_loop" = "ask"; + }; + + # AZ-Gruppe LiteLLM endpoint + available models + provider = { + litellm = { + npm = "@ai-sdk/openai-compatible"; + name = "LiteLLM (AZ-Gruppe)"; + options.baseURL = "https://llm.az-gruppe.com/v1"; + models = { + "gpt-5.2" = { + name = "GPT-5.2"; + limit = { + context = 400000; + output = 128000; + }; + }; + "gpt-5.3-codex" = { + name = "GPT-5.3 Codex"; + limit = { + context = 400000; + output = 128000; + }; + }; + "claude-haiku-4-5" = { + name = "Claude Haiku 4.5"; + options = { + thinking = { + type = "enabled"; + budget_tokens = 16000; + }; + }; + limit = { + context = 200000; + output = 64000; + }; + }; + "claude-sonnet-4-6" = { + name = "Claude Sonnet 4.6"; + options = { + thinking = { + type = "enabled"; + budget_tokens = 16000; + }; + }; + limit = { + context = 200000; + output = 64000; + }; + }; + "claude-opus-4-6" = { + name = "Claude Opus 4.6"; + options = { + thinking = { + type = "enabled"; + budget_tokens = 16000; + }; + }; + limit = { + context = 200000; + output = 128000; + }; + }; + }; + }; + }; + }; +} diff --git a/profiles/sets/coding/agents/pi.nix b/profiles/sets/coding/agents/pi.nix new file mode 100644 index 0000000..2cada13 --- /dev/null +++ b/profiles/sets/coding/agents/pi.nix @@ -0,0 +1,269 @@ +{inputs, ...}: { + coding.agents.pi = { + enable = true; + agentsInput = inputs.agents; + + modelOverrides = { + chiron = "minimax/MiniMax-M2.7"; + chiron-forge = "minimax/MiniMax-M2.7"; + }; + + # Coding rules for Pi agent + # Rules sourced from AGENTS repo + codingRules = { + # Language-specific rules + languages = [ + "nix" # Nix language conventions + ]; + + # Standard concerns from AGENTS repo + concerns = [ + "coding-style" # General coding principles + "naming" # Naming conventions (camelCase, snake_case, etc.) + "documentation" # Documentation standards + "testing" # Testing guidelines (Arrange-Act-Assert) + "git-workflow" # Conventional commits, branch naming + "git-identity" # Git identity configuration for agents + "project-structure" # Project layout conventions + ]; + + # No framework-specific rules for NixOS config + frameworks = []; + }; + + settings = { + packages = [ + "npm:@dreadedzombie/pi-init" + "npm:@plannotator/pi-extension" + "npm:@thesethrose/pi-zai-provider" + "npm:pi-agent-browser-native" + "npm:pi-beads-extension" + "npm:pi-lens" + "npm:pi-markdown-preview" + "npm:pi-mcp-adapter" + "npm:pi-powerline-footer" + "npm:pi-prompt-template-model" + "npm:pi-subagents" + "npm:pi-tool-display" + "npm:pi-web-access" + "git:github.com/hk-vk/pi-connect" + ]; + + defaultProvider = "minimax"; + defaultModel = "MiniMax-M2.7"; + defaultThinkingLevel = "high"; + }; + + # pi-guardrails: strict security config + # NOTE: Path access checks are lexical (not symlink-safe). + # NOTE: Local project .pi/extensions/guardrails.json can override same rule IDs. + # For immutable global policies, consider a wrapper or upstream patch. + guardrails = { + enable = true; + config = { + enabled = true; + applyBuiltinDefaults = true; + + onboarding = { + completed = true; + }; + + features = { + policies = true; + permissionGate = true; + pathAccess = true; + }; + + pathAccess = { + mode = "ask"; + allowedPaths = [ + "/nix/store/" + "/tmp/" + ]; + }; + + policies = { + rules = [ + # ── SSH keys ─────────────────────────────────────────── + { + id = "home-ssh"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.ssh/**";} + {pattern = "~/.ssh/*_rsa";} + {pattern = "~/.ssh/*_ed25519";} + {pattern = "~/.ssh/*.pem";} + ]; + allowedPatterns = [ + {pattern = "~/.ssh/*.pub";} + ]; + } + + # ── GPG keys ───────────────────────────────────────── + { + id = "home-gpg"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.gnupg/**";} + {pattern = "~/*.gpg";} + {pattern = "~/.gpg-agent.conf";} + ]; + } + + # ── AWS credentials ──────────────────────────────────── + { + id = "home-aws"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.aws/**";} + {pattern = "~/.aws/credentials";} + {pattern = "~/.aws/config";} + ]; + } + + # ── Kubernetes configs ──────────────────────────────── + { + id = "home-kube"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.kube/**";} + {pattern = "*kubeconfig*";} + ]; + } + + # ── Cloud CLI configs ──────────────────────────────── + { + id = "home-config"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.config/gh/**";} + {pattern = "~/.config/gcloud/**";} + {pattern = "~/.config/op/**";} + {pattern = "~/.config/sops/**";} + ]; + } + + # ── agenix secrets ─────────────────────────────────── + { + id = "agenix-secrets"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "/run/agenix/**";} + ]; + } + + # ── Pi auth and sessions ──────────────────────────── + { + id = "pi-auth-sessions"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "~/.pi/agent/auth.json";} + {pattern = "~/.pi/agent/sessions/**";} + ]; + } + + # ── Environment files ───────────────────────────────── + { + id = "secret-files"; + enabled = true; + protection = "noAccess"; + onlyIfExists = true; + patterns = [ + {pattern = ".env";} + {pattern = ".env.*";} + {pattern = ".dev.vars";} + ]; + allowedPatterns = [ + {pattern = "*.example.env";} + {pattern = "*.sample.env";} + {pattern = "*.test.env";} + {pattern = ".env.example";} + {pattern = ".env.sample";} + {pattern = ".env.test";} + ]; + } + + # ── Private keys and certificates ─────────────────── + { + id = "private-keys"; + enabled = true; + protection = "noAccess"; + onlyIfExists = false; + patterns = [ + {pattern = "*.pem";} + {pattern = "*.key";} + {pattern = "*.p12";} + {pattern = "*.pfx";} + {pattern = "*id_rsa*";} + {pattern = "*id_ed25519*";} + {pattern = "*id_ecdsa*";} + ]; + allowedPatterns = [ + {pattern = "*.pub";} + {pattern = "*.csr";} + ]; + } + ]; + }; + + permissionGate = { + explainCommands = false; + # Auto-deny patterns: env leakage and credential dumping + autoDenyPatterns = [ + { + pattern = "\\benv\\b"; + regex = true; + description = "env command (may dump environment)"; + } + { + pattern = "\\bprintenv\\b"; + regex = true; + description = "printenv command (dumps environment variables)"; + } + { + pattern = "/proc/[0-9]+/environ"; + regex = true; + description = "reading process environment files"; + } + { + pattern = "gpg\\s+--export-secret-keys"; + regex = true; + description = "GPG secret key export"; + } + { + pattern = "gpg\\s+--export-secret-subkeys"; + regex = true; + description = "GPG secret subkey export"; + } + { + pattern = "ssh-add\\s+-D"; + regex = true; + description = "delete all SSH identities"; + } + { + pattern = "\\b(op|pass)\\s+(read|show|get)"; + regex = true; + description = "password manager read operations"; + } + ]; + }; + }; + }; + + # MCP servers auto-inherited from programs.mcp in default.nix + }; +} diff --git a/profiles/sets/coding/core/default.nix b/profiles/sets/coding/core/default.nix new file mode 100644 index 0000000..b3ab1ac --- /dev/null +++ b/profiles/sets/coding/core/default.nix @@ -0,0 +1,16 @@ +# profiles/sets/coding/core/default.nix — Core coding tools (always loaded with coding set). +# +# Provides git (package + difftastic), direnv, and essential CLI dev tools. +# Git USER SETTINGS (name, email, signing) are managed by the identity module, +# NOT here — this module only handles git tooling. +# +# Note: git.nix is copied from nixos-config/home/coding/git/git.nix +# It handles git.enable, difftastic, jujutsu, etc. but identity-specific +# settings (user.name, user.email) should be set by the identity module. +{...}: { + imports = [ + ./git.nix + ./direnv.nix + ./packages.nix + ]; +} diff --git a/profiles/sets/coding/core/direnv.nix b/profiles/sets/coding/core/direnv.nix new file mode 100644 index 0000000..354e565 --- /dev/null +++ b/profiles/sets/coding/core/direnv.nix @@ -0,0 +1,8 @@ +# profiles/sets/coding/core/direnv.nix +# direnv + nix-direnv for automatic per-project environments. +{...}: { + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; +} diff --git a/profiles/sets/coding/core/git.nix b/profiles/sets/coding/core/git.nix new file mode 100644 index 0000000..4d91287 --- /dev/null +++ b/profiles/sets/coding/core/git.nix @@ -0,0 +1,41 @@ +# Git configuration with signing, aliases, and global ignore. +# Identity and host-specific SSH keys are set per-host in home/m3tam3re/. +{ + lib, + pkgs, + ... +}: +with lib; { + programs.git = { + enable = true; + signing.format = null; + settings = { + user = { + name = lib.mkDefault "m3tam3re"; + email = lib.mkDefault "p@m3ta.dev"; + }; + core.excludesfile = "~/.gitignore_global"; + init.defaultBranch = "master"; + alias = { + st = "status"; + logd = "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"; + }; + }; + }; + + programs.difftastic.enable = true; + + programs.jujutsu = { + enable = true; + settings = { + user = { + email = "m@m3tam3re.com"; + name = "Sascha Koenig"; + }; + }; + }; + + home.packages = with pkgs; [ + lazygit + ]; +} diff --git a/profiles/sets/coding/core/packages.nix b/profiles/sets/coding/core/packages.nix new file mode 100644 index 0000000..760a8db --- /dev/null +++ b/profiles/sets/coding/core/packages.nix @@ -0,0 +1,13 @@ +# profiles/sets/coding/core/packages.nix +# Essential CLI dev tools — always available when coding set is active. +{pkgs, ...}: { + home.packages = with pkgs; [ + curl + fd + file + hyperfine + jq + ripgrep + tree + ]; +} diff --git a/profiles/sets/coding/default.nix b/profiles/sets/coding/default.nix new file mode 100644 index 0000000..7085402 --- /dev/null +++ b/profiles/sets/coding/default.nix @@ -0,0 +1,22 @@ +# profiles/sets/coding/default.nix — Coding environment aggregator. +# +# Imports all coding sub-modules. Individual features are controlled +# via enable options (e.g. coding.editors.neovim.enable = true). +# +# Structure: +# core/ — Always-on when coding set is active (git, direnv, core packages) +# editor/ — Neovim (both contexts), Zed (desktop only) +# lsp/ — Language server protocol tools +# languages/ — Python, JS, Rust, Go, TypeScript (each with enable option) +# agents/ — AI coding agents (opencode, etc.) +# packages — Optional extra packages (bruno, insomnia) +{...}: { + imports = [ + ./core + ./editor + ./lsp + ./agents/agents.nix + ./languages + ./packages.nix + ]; +} diff --git a/profiles/sets/coding/editor/default.nix b/profiles/sets/coding/editor/default.nix new file mode 100644 index 0000000..2f18bca --- /dev/null +++ b/profiles/sets/coding/editor/default.nix @@ -0,0 +1,6 @@ +# Editor aggregator — delegates to m3ta-nixpkgs editor modules. +{...}: { + imports = [ + ./neovim.nix + ]; +} diff --git a/profiles/sets/coding/editor/neovim.nix b/profiles/sets/coding/editor/neovim.nix new file mode 100644 index 0000000..79c101e --- /dev/null +++ b/profiles/sets/coding/editor/neovim.nix @@ -0,0 +1,7 @@ +# NeoVim base configuration via m3ta-nixpkgs coding.editors module. +# The option `coding.editors.neovim.enable` is declared by +# inputs.m3ta-nixpkgs.homeManagerModules.default — no re-declaration here. +{...}: { + # Placeholder for host-agnostic NeoVim overrides. + # Set coding.editors.neovim.enable = true in per-host files to activate. +} diff --git a/profiles/sets/coding/languages/default.nix b/profiles/sets/coding/languages/default.nix new file mode 100644 index 0000000..586848d --- /dev/null +++ b/profiles/sets/coding/languages/default.nix @@ -0,0 +1,10 @@ +# Language runtimes — Python, JavaScript, Rust, Go, TypeScript. +{...}: { + imports = [ + ./python.nix + ./javascript.nix + ./rust-toolchain.nix + ./go.nix + ./typescript.nix + ]; +} diff --git a/profiles/sets/coding/languages/go.nix b/profiles/sets/coding/languages/go.nix new file mode 100644 index 0000000..c373f59 --- /dev/null +++ b/profiles/sets/coding/languages/go.nix @@ -0,0 +1,19 @@ +# Go toolchain — compiler and language server. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.languages.go; +in { + options.coding.languages.go.enable = mkEnableOption "Go toolchain"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + go + gopls + ]; + }; +} diff --git a/profiles/sets/coding/languages/javascript.nix b/profiles/sets/coding/languages/javascript.nix new file mode 100644 index 0000000..86ccf2e --- /dev/null +++ b/profiles/sets/coding/languages/javascript.nix @@ -0,0 +1,25 @@ +# JavaScript/TypeScript runtime — Node.js and Bun. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.languages.javascript; + npmGlobalPrefix = "${config.home.homeDirectory}/.npm-global"; +in { + options.coding.languages.javascript.enable = mkEnableOption "JavaScript runtime (Node.js + Bun)"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + nodejs + bun + ]; + + home.file.".npmrc".text = '' + prefix=${npmGlobalPrefix} + ''; + home.sessionVariables.NPM_CONFIG_PREFIX = npmGlobalPrefix; + }; +} diff --git a/profiles/sets/coding/languages/python.nix b/profiles/sets/coding/languages/python.nix new file mode 100644 index 0000000..fa0d1bc --- /dev/null +++ b/profiles/sets/coding/languages/python.nix @@ -0,0 +1,35 @@ +# Python runtime with pip and uv. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.languages.python; +in { + options.coding.languages.python = { + enable = mkEnableOption "Python runtime with pip and uv"; + extraPackages = mkOption { + type = types.listOf types.package; + default = []; + example = literalExpression "[ pkgs.python3Packages.numpy ]"; + description = "Additional Python packages to include"; + }; + }; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + (pkgs.python3.withPackages (ps: + with ps; + [ + uv + ] + ++ cfg.extraPackages)) + (writeShellScriptBin "pip" "exec uv pip $@") + (writeShellScriptBin "pip3" "exec uv pip $@") + pyrefly + ruff + ]; + }; +} diff --git a/profiles/sets/coding/languages/rust-toolchain.nix b/profiles/sets/coding/languages/rust-toolchain.nix new file mode 100644 index 0000000..823a28c --- /dev/null +++ b/profiles/sets/coding/languages/rust-toolchain.nix @@ -0,0 +1,20 @@ +# Rust toolchain — compiler, package manager, and language server. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.languages.rustToolchain; +in { + options.coding.languages.rustToolchain.enable = mkEnableOption "Rust toolchain"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + rustc + cargo + rust-analyzer + ]; + }; +} diff --git a/profiles/sets/coding/languages/typescript.nix b/profiles/sets/coding/languages/typescript.nix new file mode 100644 index 0000000..58a791e --- /dev/null +++ b/profiles/sets/coding/languages/typescript.nix @@ -0,0 +1,19 @@ +# TypeScript support — language server and type checking tools. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.languages.typescript; +in { + options.coding.languages.typescript.enable = mkEnableOption "TypeScript support"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + typescript + typescript-language-server + ]; + }; +} diff --git a/profiles/sets/coding/lsp/default.nix b/profiles/sets/coding/lsp/default.nix new file mode 100644 index 0000000..c8e11b0 --- /dev/null +++ b/profiles/sets/coding/lsp/default.nix @@ -0,0 +1,6 @@ +# LSP aggregator — language server protocol tooling. +{...}: { + imports = [ + ./servers.nix + ]; +} diff --git a/profiles/sets/coding/lsp/servers.nix b/profiles/sets/coding/lsp/servers.nix new file mode 100644 index 0000000..77bc732 --- /dev/null +++ b/profiles/sets/coding/lsp/servers.nix @@ -0,0 +1,23 @@ +# LSP server configuration — language servers for the development environment. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.lsp; +in { + options.coding.lsp.enable = mkEnableOption "enable LSP servers"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + # Nix + nixd + # General + typescript-language-server + tailwindcss-language-server + pyrefly + ]; + }; +} diff --git a/profiles/sets/coding/packages.nix b/profiles/sets/coding/packages.nix new file mode 100644 index 0000000..2501cd6 --- /dev/null +++ b/profiles/sets/coding/packages.nix @@ -0,0 +1,20 @@ +# Additional coding packages — API clients and GUI development tools. +# Opt-in since not all coding hosts need these desktop-oriented tools. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.coding.packages; +in { + options.coding.packages.enable = mkEnableOption "additional coding packages (bruno, insomnia)"; + + config = mkIf cfg.enable { + home.packages = [ + pkgs.bruno + pkgs.insomnia + ]; + }; +} diff --git a/profiles/sets/gaming/default.nix b/profiles/sets/gaming/default.nix new file mode 100644 index 0000000..7b1f663 --- /dev/null +++ b/profiles/sets/gaming/default.nix @@ -0,0 +1,8 @@ +# Gaming profile aggregator — Steam platform, Gamescope session, and AMD GPU tools. +{...}: { + imports = [ + ./steam.nix + ./gamescope.nix + ./gpu.nix + ]; +} diff --git a/profiles/sets/gaming/gamescope.nix b/profiles/sets/gaming/gamescope.nix new file mode 100644 index 0000000..6f975cd --- /dev/null +++ b/profiles/sets/gaming/gamescope.nix @@ -0,0 +1,16 @@ +# Gamescope — Valve's micro-compositor for Steam gaming sessions. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.gaming.gamescope; +in { + options.profiles.gaming.gamescope.enable = mkEnableOption "enable Gamescope session"; + + config = mkIf cfg.enable { + home.packages = [pkgs.gamescope]; + }; +} diff --git a/profiles/sets/gaming/gpu.nix b/profiles/sets/gaming/gpu.nix new file mode 100644 index 0000000..ad8c85c --- /dev/null +++ b/profiles/sets/gaming/gpu.nix @@ -0,0 +1,21 @@ +# AMD GPU tools — ROCm runtime, monitoring, and Vulkan utilities for gaming. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.gaming.gpu; +in { + options.profiles.gaming.gpu.enable = mkEnableOption "enable AMD GPU tools"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + rocmPackages.rocm-runtime + rocmPackages.rocm-smi + rocmPackages.rocminfo + vulkan-tools + ]; + }; +} diff --git a/profiles/sets/gaming/steam.nix b/profiles/sets/gaming/steam.nix new file mode 100644 index 0000000..92a24c1 --- /dev/null +++ b/profiles/sets/gaming/steam.nix @@ -0,0 +1,21 @@ +# Steam gaming platform with Steam Deck compatibility tools and gaming utilities. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.gaming.steam; +in { + options.profiles.gaming.steam.enable = mkEnableOption "enable Steam gaming"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + gamemode + goverlay + mangohud + protonplus + ]; + }; +} diff --git a/profiles/sets/media/default.nix b/profiles/sets/media/default.nix new file mode 100644 index 0000000..0f453a5 --- /dev/null +++ b/profiles/sets/media/default.nix @@ -0,0 +1,10 @@ +# Media profile aggregator — OBS, FFmpeg, yt-dlp, Kdenlive, and HandBrake. +{...}: { + imports = [ + ./obs.nix + ./ffmpeg.nix + ./yt-dlp.nix + ./kdenlive.nix + ./handbrake.nix + ]; +} diff --git a/profiles/sets/media/ffmpeg.nix b/profiles/sets/media/ffmpeg.nix new file mode 100644 index 0000000..287e32c --- /dev/null +++ b/profiles/sets/media/ffmpeg.nix @@ -0,0 +1,24 @@ +# FFmpeg — full-featured multimedia processing toolchain. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.media.ffmpeg; +in { + options.profiles.media.ffmpeg.enable = mkEnableOption "enable FFmpeg tools"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + amf + ffmpeg_6-full + gst_all_1.gstreamer + gst_all_1.gst-vaapi + pamixer + pavucontrol + qpwgraph + ]; + }; +} diff --git a/profiles/sets/media/handbrake.nix b/profiles/sets/media/handbrake.nix new file mode 100644 index 0000000..f14ff5d --- /dev/null +++ b/profiles/sets/media/handbrake.nix @@ -0,0 +1,21 @@ +# HandBrake — open-source video transcoder. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.media.handbrake; +in { + options.profiles.media.handbrake.enable = mkEnableOption "enable HandBrake transcoder"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + handbrake + gimp + inkscape + libation + ]; + }; +} diff --git a/profiles/sets/media/kdenlive.nix b/profiles/sets/media/kdenlive.nix new file mode 100644 index 0000000..f3a4dbd --- /dev/null +++ b/profiles/sets/media/kdenlive.nix @@ -0,0 +1,16 @@ +# Kdenlive — KDE non-linear video editor. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.media.kdenlive; +in { + options.profiles.media.kdenlive.enable = mkEnableOption "enable Kdenlive video editor"; + + config = mkIf cfg.enable { + home.packages = [pkgs.kdePackages.kdenlive]; + }; +} diff --git a/profiles/sets/media/obs.nix b/profiles/sets/media/obs.nix new file mode 100644 index 0000000..2a6f22c --- /dev/null +++ b/profiles/sets/media/obs.nix @@ -0,0 +1,21 @@ +# OBS Studio — open broadcaster software for streaming and recording. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.media.obs; +in { + options.profiles.media.obs.enable = mkEnableOption "enable OBS Studio"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + v4l-utils + ]; + + # OBS is managed via NixOS programs.obs-studio at the system level. + # Home-manager only installs supporting tools. + }; +} diff --git a/profiles/sets/media/yt-dlp.nix b/profiles/sets/media/yt-dlp.nix new file mode 100644 index 0000000..5c9e088 --- /dev/null +++ b/profiles/sets/media/yt-dlp.nix @@ -0,0 +1,32 @@ +# yt-dlp and media playback — YouTube downloader with MPV integration. +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.profiles.media.ytDlp; +in { + options.profiles.media.ytDlp.enable = mkEnableOption "enable yt-dlp and media playback"; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + plexamp + unimatrix + webcord + ]; + + programs.mpv = { + enable = true; + bindings = { + WHEEL_UP = "seek 10"; + WHEEL_DOWN = "seek -10"; + }; + config = { + profile = "gpu-hq"; + ytdl-format = "bestvideo+bestaudio"; + }; + }; + }; +} diff --git a/users/m3tam3re/identities/private.nix b/users/m3tam3re/identities/private.nix new file mode 100644 index 0000000..00ffb55 --- /dev/null +++ b/users/m3tam3re/identities/private.nix @@ -0,0 +1,148 @@ +# users/m3tam3re/identities/private.nix — Private identity (m3tam3re). +# +# Sets git identity, jujutsu identity, and SSH match blocks for private infrastructure. +# This module is loaded when identity = "private" in mkHome. +{ + config, + lib, + ... +}: { + # ── User identity ── + home.username = lib.mkForce "m3tam3re"; + home.homeDirectory = lib.mkForce "/home/m3tam3re"; + + # ── Git configuration ── + programs.git = { + enable = true; + signing.format = null; + settings = { + user = { + name = "m3tm3re"; + email = "p@m3ta.dev"; + }; + core.excludesfile = "~/.gitignore_global"; + init.defaultBranch = "master"; + alias = { + st = "status"; + logd = "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"; + }; + }; + }; + + # ── Jujutsu configuration ── + programs.jujutsu = { + enable = true; + settings = { + user = { + email = "m@m3tam3re.com"; + name = "Sascha Koenig"; + }; + }; + }; + + # ── SSH configuration ── + programs.ssh = { + enable = true; + enableDefaultConfig = false; + matchBlocks = { + "github.com" = { + hostname = "github.com"; + user = "m3tam3re"; + port = 22; + identityFile = "~/.ssh/github"; + }; + "code.m3ta.dev" = { + hostname = "code.m3ta.dev"; + user = "m3tam3re"; + identityFile = "~/.ssh/gitea"; + }; + "nikhil" = { + hostname = "91.99.176.80"; + user = "nikhilmaddirala"; + identityFile = "~/.ssh/m3tam3re"; + }; + "lkk-nix-1" = { + hostname = "89.58.10.189"; + user = "lkk-admin"; + identityFile = "~/.ssh/lkk-admin"; + }; + "m3-r1" = { + hostname = "202.61.226.110"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "lkk-prod-test" = { + hostname = "192.168.122.215"; + user = "root"; + identityFile = "~/.ssh/m3tam3re"; + }; + "lkk-prod-1" = { + hostname = "192.168.0.24"; + user = "root"; + identityFile = "~/.ssh/m3tam3re"; + }; + "lkk-prod-2" = { + hostname = "192.168.0.20"; + user = "root"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-deck" = { + hostname = "192.168.178.193"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-kratos-vm" = { + hostname = "192.168.122.43"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-helios" = { + hostname = "192.168.178.210"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-ares" = { + hostname = "192.168.1.30"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-atlas" = { + hostname = "152.53.85.162"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-hermes" = { + hostname = "204.168.229.93"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-zelda" = { + hostname = "95.217.189.186"; + user = "m3tam3re"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-skynet" = { + hostname = "m3-skynet"; + user = "admin"; + identityFile = "~/.ssh/m3tam3re"; + }; + "m3-prox-1" = { + hostname = "192.168.1.110"; + user = "root"; + identityFile = "~/.ssh/m3tam3re"; + }; + "shp-old" = { + hostname = "95.217.3.250"; + port = 2222; + user = "m3tam3re"; + identityFile = "~/.ssh/self-host-playbook"; + }; + "shp-1" = { + hostname = "95.217.189.186"; + port = 2222; + user = "m3tam3re"; + identityFile = "~/.ssh/self-host-playbook"; + }; + }; + }; +} diff --git a/users/m3tam3re/identities/work.nix b/users/m3tam3re/identities/work.nix new file mode 100644 index 0000000..e33358c --- /dev/null +++ b/users/m3tam3re/identities/work.nix @@ -0,0 +1,68 @@ +# users/m3tam3re/identities/work.nix — Work identity (sascha.koenig). +# +# Sets git identity, jujutsu identity, and SSH match blocks for work infrastructure. +# This module is loaded when identity = "work" in mkHome. +{ + config, + lib, + ... +}: { + # ── User identity ── + home.username = lib.mkForce "sascha.koenig"; + home.homeDirectory = lib.mkForce "/home/sascha.koenig"; + + # ── Git configuration ── + programs.git = { + enable = true; + signing.format = null; + settings = { + user = { + name = "Sascha König"; + email = "sascha.koenig@azintec.com"; + }; + core.excludesfile = "~/.gitignore_global"; + init.defaultBranch = "master"; + alias = { + st = "status"; + logd = "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"; + }; + }; + }; + + # ── Jujutsu configuration ── + programs.jujutsu = { + enable = true; + settings = { + user = { + email = "sascha.koenig@azintec.com"; + name = "Sascha König"; + }; + }; + }; + + # ── SSH configuration (work servers) ── + programs.ssh = { + enable = true; + enableDefaultConfig = false; + matchBlocks = { + "AZ-CLD-1" = { + hostname = "152.53.186.119"; + user = "sascha.koenig"; + port = 2022; + identityFile = "~/.ssh/sascha.koenig"; + }; + "AZ-PRM-1" = { + hostname = "192.168.152.76"; + user = "sascha.koenig"; + port = 2022; + identityFile = "~/.ssh/sascha.koenig"; + }; + "git.az-gruppe.com" = { + hostname = "git.az-gruppe.com"; + port = 2022; + user = "sascha.koenig"; + identityFile = "~/.ssh/sascha.koenig"; + }; + }; + }; +} diff --git a/users/m3tam3re/preferences/default.nix b/users/m3tam3re/preferences/default.nix new file mode 100644 index 0000000..170e499 --- /dev/null +++ b/users/m3tam3re/preferences/default.nix @@ -0,0 +1,28 @@ +# users/m3tam3re/preferences/default.nix — User preferences (portable across identities). +# +# These settings are the same regardless of whether you're "private" or "work": +# - Shell style and aliases +# - Editor preferences +# - CLI appearance (starship theme, bat theme, etc.) +# - Clipboard manager +# - difftastic +{ + config, + pkgs, + lib, + ... +}: { + # ── Clipboard ── + services.cliphist = { + enable = true; + allowImages = true; + }; + + # ── Difftastic ── + programs.difftastic.enable = true; + + # ── Home username/directory defaults ── + # These are overridden by the identity module, but provide safe defaults. + home.username = lib.mkDefault "m3tam3re"; + home.homeDirectory = lib.mkDefault "/home/${config.home.username}"; +}