diff --git a/flake.nix b/flake.nix index 55126df..5808902 100644 --- a/flake.nix +++ b/flake.nix @@ -133,7 +133,7 @@ home-manager.users.johno = { imports = [ ./home/home-laptop-compact.nix ]; # Machine-specific overrides - home.i3_sway.extraSwayConfig = { + home.roles.i3_sway.extraSwayConfig = { output.eDP-1.scale = "1.75"; }; }; diff --git a/home/home-darwin-work.nix b/home/home-darwin-work.nix index be87239..2df450b 100644 --- a/home/home-darwin-work.nix +++ b/home/home-darwin-work.nix @@ -120,29 +120,25 @@ home.shell.enableShellIntegration = true; - # Enable aerospace window manager with autoraise - programs.aerospace = { - enable = true; - leader = "cmd"; - # Optional: Add per-machine userSettings overrides - # userSettings = { - # mode.main.binding."${leader}-custom" = "custom-command"; - # }; - }; - home.roles = { base.enable = true; development = { enable = true; allowArbitraryClaudeCodeModelSelection = true; }; + tmux.enable = true; + emacs.enable = true; + aerospace = { + enable = true; + leader = "cmd"; + # Optional: Add per-machine userSettings overrides + # userSettings = { + # mode.main.binding."${leader}-custom" = "custom-command"; + # }; + }; }; imports = [ ./roles - ./modules/emacs - ./modules/kubectl - ./modules/tmux - ./modules/aerospace ]; } diff --git a/home/home-desktop.nix b/home/home-desktop.nix index e6520c8..e4fdd10 100644 --- a/home/home-desktop.nix +++ b/home/home-desktop.nix @@ -17,6 +17,10 @@ sync.enable = true; kdeconnect.enable = true; kubectl.enable = true; + tmux.enable = true; + plasma-manager.enable = true; + emacs.enable = true; + i3_sway.enable = true; }; targets.genericLinux.enable = true; @@ -25,10 +29,5 @@ imports = [ ./roles - ./modules/emacs - ./modules/i3+sway - ./modules/kubectl - ./modules/plasma-manager - ./modules/tmux ]; } diff --git a/home/home-laptop-compact.nix b/home/home-laptop-compact.nix index 867a494..72353ae 100644 --- a/home/home-laptop-compact.nix +++ b/home/home-laptop-compact.nix @@ -18,6 +18,10 @@ media.enable = true; sync.enable = true; kubectl.enable = true; + tmux.enable = true; + plasma-manager.enable = true; + emacs.enable = true; + i3_sway.enable = true; # Launcher wrappers for excluded/optional packages launchers = { @@ -34,10 +38,5 @@ imports = [ ./roles - ./modules/emacs - ./modules/i3+sway - ./modules/kubectl - ./modules/plasma-manager - ./modules/tmux ]; } diff --git a/home/home-live-usb.nix b/home/home-live-usb.nix index af156cc..77b388f 100644 --- a/home/home-live-usb.nix +++ b/home/home-live-usb.nix @@ -12,8 +12,12 @@ home.roles = { base.enable = true; desktop.enable = true; + tmux.enable = true; + plasma-manager.enable = true; + emacs.enable = true; + i3_sway.enable = true; # development.enable = false; # Not needed for live USB - # communication.enable = false; # Not needed for live USB + # communication.enable = false; # Not needed for live USB # office.enable = false; # Not needed for live USB # media.enable = false; # Not needed for live USB # sync.enable = false; # No persistent sync on live USB @@ -26,11 +30,6 @@ imports = [ ./roles - ./modules/emacs - ./modules/i3+sway - ./modules/kubectl - ./modules/plasma-manager - ./modules/tmux ]; # Live USB specific overrides can go here if needed diff --git a/home/home-media-center.nix b/home/home-media-center.nix index ab19200..fe58c6e 100644 --- a/home/home-media-center.nix +++ b/home/home-media-center.nix @@ -16,6 +16,10 @@ communication.enable = true; kdeconnect.enable = true; development.enable = true; + tmux.enable = true; + plasma-manager.enable = true; + emacs.enable = true; + i3_sway.enable = true; # office.enable = false; # Not needed for media center # sync.enable = false; # Shared machine, no personal file sync }; @@ -26,11 +30,6 @@ imports = [ ./roles - ./modules/emacs - ./modules/i3+sway - ./modules/kubectl - ./modules/plasma-manager - ./modules/tmux ]; # Media center specific overrides can go here if needed diff --git a/home/modules/kubectl/default.nix b/home/modules/kubectl/default.nix deleted file mode 100644 index 0da3d8c..0000000 --- a/home/modules/kubectl/default.nix +++ /dev/null @@ -1,249 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.programs.kubectl-secure; -in -{ - options.programs.kubectl-secure = { - enable = mkEnableOption "secure kubectl configuration with Bitwarden integration"; - }; - - config = mkIf cfg.enable { - home.packages = with pkgs; [ - kubectl - kubernetes-helm - ]; - - programs.k9s.enable = true; - - programs.bash.initExtra = mkAfter '' - # Kubectl secure session management - export KUBECTL_SESSION_DIR="/dev/shm/kubectl-$$" - - kube-select() { - if [[ $# -ne 1 ]]; then - echo "Usage: kube-select " - echo "Available contexts: $(kube-list)" - return 1 - fi - - local context="$1" - - # Clean up any existing session first - kube-clear 2>/dev/null - - # Create new session directory - mkdir -p "$KUBECTL_SESSION_DIR" - chmod 700 "$KUBECTL_SESSION_DIR" - - # Set cleanup trap for this shell session - trap "rm -rf '$KUBECTL_SESSION_DIR' 2>/dev/null" EXIT - - # Set KUBECONFIG for this session - export KUBECONFIG="$KUBECTL_SESSION_DIR/config" - - # Load config from Bitwarden secure notes - if ! rbw get "kubectl-$context" > "$KUBECONFIG" 2>/dev/null; then - echo "Error: Could not retrieve kubectl-$context from Bitwarden" - echo "Make sure the entry exists with name: kubectl-$context" - kube-clear - return 1 - fi - - # Verify the kubeconfig is valid - if ! kubectl config view >/dev/null 2>&1; then - echo "Error: Invalid kubeconfig retrieved from Bitwarden" - kube-clear - return 1 - fi - - echo "✓ Loaded kubectl context: $context (session: $$)" - echo " Config location: $KUBECONFIG" - } - - kube-list() { - echo "Available kubectl contexts in Bitwarden:" - rbw search kubectl- 2>/dev/null | grep "^kubectl-" | sed 's/^kubectl-/ - /' || echo " (none found or rbw not accessible)" - } - - kube-clear() { - if [[ -n "$KUBECTL_TIMEOUT_PID" ]]; then - kill "$KUBECTL_TIMEOUT_PID" 2>/dev/null - unset KUBECTL_TIMEOUT_PID - fi - - if [[ -d "$KUBECTL_SESSION_DIR" ]]; then - rm -rf "$KUBECTL_SESSION_DIR" - echo "Cleared kubectl session ($$)" - fi - - unset KUBECONFIG - } - - kube-status() { - if [[ -f "$KUBECONFIG" ]]; then - local current_context - current_context=$(kubectl config current-context 2>/dev/null) - if [[ -n "$current_context" ]]; then - echo "Active kubectl context: $current_context" - echo "Session: $$ | Config: $KUBECONFIG" - - # Show cluster info - local cluster_server - cluster_server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null) - if [[ -n "$cluster_server" ]]; then - echo "Cluster: $cluster_server" - fi - else - echo "No active context in current session" - fi - else - echo "No kubectl session active in this shell" - echo "Use 'kube-select ' to start a session" - fi - } - - # Helper function to show available commands - kube-help() { - echo "Secure kubectl session management commands:" - echo "" - echo "Session management:" - echo " kube-select - Load kubeconfig from Bitwarden" - echo " kube-status - Show current session status" - echo " kube-clear - Clear current session" - echo "" - echo "Configuration management:" - echo " kube-list - List available contexts in Bitwarden" - echo "" - echo "Help:" - echo " kube-help - Show this help" - echo "" - echo "Examples:" - echo " kube-select prod # Loads from secure note" - echo " kubectl get pods" - echo " kube-clear" - echo "" - echo "Note: Kubeconfigs are stored as secure notes in Bitwarden" - } - ''; - - programs.zsh.initExtra = mkAfter '' - # Kubectl secure session management (zsh) - export KUBECTL_SESSION_DIR="/dev/shm/kubectl-$$" - - kube-select() { - if [[ $# -ne 1 ]]; then - echo "Usage: kube-select " - echo "Available contexts: $(kube-list)" - return 1 - fi - - local context="$1" - - # Clean up any existing session first - kube-clear 2>/dev/null - - # Create new session directory - mkdir -p "$KUBECTL_SESSION_DIR" - chmod 700 "$KUBECTL_SESSION_DIR" - - # Set cleanup trap for this shell session - trap "rm -rf '$KUBECTL_SESSION_DIR' 2>/dev/null" EXIT - - # Set KUBECONFIG for this session - export KUBECONFIG="$KUBECTL_SESSION_DIR/config" - - # Load config from Bitwarden secure notes - if ! rbw get "kubectl-$context" > "$KUBECONFIG" 2>/dev/null; then - echo "Error: Could not retrieve kubectl-$context from Bitwarden" - echo "Make sure the entry exists with name: kubectl-$context" - kube-clear - return 1 - fi - - # Verify the kubeconfig is valid - if ! kubectl config view >/dev/null 2>&1; then - echo "Error: Invalid kubeconfig retrieved from Bitwarden" - kube-clear - return 1 - fi - - echo "✓ Loaded kubectl context: $context (session: $$)" - echo " Config location: $KUBECONFIG" - - # Optional: Set timeout cleanup - if [[ ${toString cfg.sessionTimeout} -gt 0 ]]; then - (sleep ${toString cfg.sessionTimeout}; kube-clear 2>/dev/null) & - export KUBECTL_TIMEOUT_PID=$! - fi - } - - kube-list() { - echo "Available kubectl contexts in Bitwarden:" - rbw search kubectl- 2>/dev/null | grep "^kubectl-" | sed 's/^kubectl-/ - /' || echo " (none found or rbw not accessible)" - } - - kube-clear() { - if [[ -n "$KUBECTL_TIMEOUT_PID" ]]; then - kill "$KUBECTL_TIMEOUT_PID" 2>/dev/null - unset KUBECTL_TIMEOUT_PID - fi - - if [[ -d "$KUBECTL_SESSION_DIR" ]]; then - rm -rf "$KUBECTL_SESSION_DIR" - echo "Cleared kubectl session ($$)" - fi - - unset KUBECONFIG - } - - kube-status() { - if [[ -f "$KUBECONFIG" ]]; then - local current_context - current_context=$(kubectl config current-context 2>/dev/null) - if [[ -n "$current_context" ]]; then - echo "Active kubectl context: $current_context" - echo "Session: $$ | Config: $KUBECONFIG" - - # Show cluster info - local cluster_server - cluster_server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null) - if [[ -n "$cluster_server" ]]; then - echo "Cluster: $cluster_server" - fi - else - echo "No active context in current session" - fi - else - echo "No kubectl session active in this shell" - echo "Use 'kube-select ' to start a session" - fi - } - - # Helper function to show available commands - kube-help() { - echo "Secure kubectl session management commands:" - echo "" - echo "Session management:" - echo " kube-select - Load kubeconfig from Bitwarden" - echo " kube-status - Show current session status" - echo " kube-clear - Clear current session" - echo "" - echo "Configuration management:" - echo " kube-list - List available contexts in Bitwarden" - echo "" - echo "Help:" - echo " kube-help - Show this help" - echo "" - echo "Examples:" - echo " kube-select prod # Loads from secure note" - echo " kubectl get pods" - echo " kube-clear" - echo "" - echo "Note: Kubeconfigs are stored as secure notes in Bitwarden" - } - ''; - }; -} diff --git a/home/modules/plasma-manager/default.nix b/home/modules/plasma-manager/default.nix deleted file mode 100644 index 6513825..0000000 --- a/home/modules/plasma-manager/default.nix +++ /dev/null @@ -1,178 +0,0 @@ -{ config, lib, pkgs, ... }: - - -# The current KDE config can be output with the command: -# nix run github:nix-community/plasma-manager -# -# Plasma-manager options documentation -# https://nix-community.github.io/plasma-manager/options.xhtml -# -# TODO: (ambitious) Add Kmail support to plasma-manager -{ - programs.plasma = { - enable = true; - overrideConfig = true; - - hotkeys.commands."launch-ghostty" = { - name = "Launch Ghostty"; - key = "Meta+Return"; - command = "ghostty"; - }; - - shortcuts = { - kmix = { - "decrease_microphone_volume" = "Microphone Volume Down"; - "decrease_volume" = "Volume Down"; - "decrease_volume_small" = "Shift+Volume Down"; - "increase_microphone_volume" = "Microphone Volume Up"; - "increase_volume" = "Volume Up"; - "increase_volume_small" = "Shift+Volume Up"; - "mic_mute" = ["Microphone Mute" "Meta+Volume Mute,Microphone Mute" "Meta+Volume Mute,Mute Microphone"]; - "mute" = "Volume Mute"; - }; - - mediacontrol = { - "mediavolumedown" = "none,,Media volume down"; - "mediavolumeup" = "none,,Media volume up"; - "nextmedia" = "Media Next"; - "pausemedia" = "Media Pause"; - "playmedia" = "none,,Play media playback"; - "playpausemedia" = "Media Play"; - "previousmedia" = "Media Previous"; - "stopmedia" = "Media Stop"; - }; - - ksmserver = { - "Lock Session" = ["Meta+Ctrl+Q" "Screensaver" "Screensaver,Lock Session"]; - }; - - kwin = { - "Window Close" = "Meta+Shift+Q"; - "Kill Window" = "Meta+Ctrl+Esc"; - "Window Operations Menu" = "Alt+F3"; - "Window Resize" = "Meta+R,,Resize Window"; - - "Overview" = "Meta+Ctrl+W"; - "Grid View" = "Meta+G"; - "Edit Tiles" = "Meta+T"; - - "Activate Window Demanding Attention" = "Meta+Ctrl+A"; - - "Show Desktop" = "Meta+Ctrl+D"; - - "Walk Through Windows" = "Alt+Tab"; - "Walk Through Windows (Reverse)" = "Alt+Shift+Tab"; - "Walk Through Windows of Current Application" = "Alt+`"; - "Walk Through Windows of Current Application (Reverse)" = "Alt+~"; - - "Window Quick Tile Bottom" = "Meta+Down"; - "Window Quick Tile Left" = "Meta+Left"; - "Window Quick Tile Right" = "Meta+Right"; - "Window Quick Tile Top" = "Meta+Up"; - - "Switch to Desktop 1" = "Meta+1"; - "Switch to Desktop 2" = "Meta+2"; - "Switch to Desktop 3" = "Meta+3"; - "Switch to Desktop 4" = "Meta+4"; - "Switch to Desktop 5" = "Meta+5"; - "Switch to Desktop 6" = "Meta+6"; - "Switch to Desktop 7" = "Meta+7"; - "Switch to Desktop 8" = "Meta+8"; - "Switch to Desktop 9" = "Meta+9"; - "Switch to Desktop 10" = "Meta+0"; - - "Window to Desktop 1" = "Meta+!"; # Meta+Shift+1 - "Window to Desktop 2" = "Meta+@"; # Meta+Shift+2 - "Window to Desktop 3" = "Meta+#"; # Meta+Shift+3 - "Window to Desktop 4" = "Meta+$"; # Meta+Shift+4 - "Window to Desktop 5" = "Meta+%"; # Meta+Shift+5 - "Window to Desktop 6" = "Meta+^"; # Meta+Shift+6 - "Window to Desktop 7" = "Meta+&"; # Meta+Shift+7 - "Window to Desktop 8" = "Meta+*"; # Meta+Shift+8 - "Window to Desktop 9" = "Meta+("; # Meta+Shift+9 - "Window to Desktop 10" = "Meta+)"; # Meta+Shift+0 - - "view_actual_size" = "Meta+Ctrl+="; - "view_zoom_in" = ["Meta++" "Meta+=,Meta++" "Meta+=,Zoom In"]; - "view_zoom_out" = "Meta+-"; - }; - "org_kde_powerdevil"."Decrease Keyboard Brightness" = "Keyboard Brightness Down"; - "org_kde_powerdevil"."Decrease Screen Brightness" = "Monitor Brightness Down"; - "org_kde_powerdevil"."Decrease Screen Brightness Small" = "Shift+Monitor Brightness Down"; - "org_kde_powerdevil"."Hibernate" = "Hibernate"; - "org_kde_powerdevil"."Increase Keyboard Brightness" = "Keyboard Brightness Up"; - "org_kde_powerdevil"."Increase Screen Brightness" = "Monitor Brightness Up"; - "org_kde_powerdevil"."Increase Screen Brightness Small" = "Shift+Monitor Brightness Up"; - "org_kde_powerdevil"."PowerDown" = "Power Down"; - "org_kde_powerdevil"."PowerOff" = "Power Off"; - "org_kde_powerdevil"."Sleep" = "Sleep"; - "org_kde_powerdevil"."Toggle Keyboard Backlight" = "Keyboard Light On/Off"; - "org_kde_powerdevil"."Turn Off Screen" = [ ]; - "org_kde_powerdevil"."powerProfile" = ["Battery" "Meta+B,Battery" "Meta+B,Switch Power Profile"]; - - plasmashell = { - "activate application launcher" = ["Meta" "Alt+F1,Meta" "Alt+F1,Activate Application Launcher"]; - "activate task manager entry 1" = "none,,"; - "activate task manager entry 2" = "none,,"; - "activate task manager entry 3" = "none,,"; - "activate task manager entry 4" = "none,,"; - "activate task manager entry 5" = "none,,"; - "activate task manager entry 6" = "none,,"; - "activate task manager entry 7" = "none,,"; - "activate task manager entry 8" = "none,,"; - "activate task manager entry 9" = "none,,"; - "activate task manager entry 10" = "none,,"; - "show activity switcher" = "none,,"; - }; - }; - - configFile = { - kwinrc.Desktops.Number = { - value = 10; - immutable = true; - }; - - # Enable KWin tiling features - kwinrc.Tiling = { - # Enable tiling functionality - "padding" = 4; - }; - - # Enable krohnkite plugin automatically - kwinrc.Plugins = { - krohnkiteEnabled = true; - }; - - kwinrc.Effect-overview = { - # Configure overview effect for better tiling workflow - BorderActivate = 9; # Top-left corner activation - }; - - kcminputrc.Libinput = { - AccelerationProfile = "adaptive"; - PointerAcceleration = 0.5; - }; - - kcminputrc.Mouse = { - X11LibInputXAccelProfileFlat = false; - XLbInptAccelProfileFlat = false; - }; - - kdeglobals.KDE.LookAndFeelPackage = "org.kde.breezedark.desktop"; - - # Focus follows mouse configuration - kwinrc.Windows = { - FocusPolicy = "FocusFollowsMouse"; - AutoRaise = true; # Set to true if you want windows to auto-raise on focus - AutoRaiseInterval = 750; # Delay in ms before auto-raise (if enabled) - DelayFocusInterval = 0; # Delay in ms before focus follows mouse - }; - - # Desktop wallpaper configuration - plasma-localerc.Formats.LANG = "en_US.UTF-8"; - - # Set wallpaper for all desktops - plasmarc.Wallpapers.usersWallpapers = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}"; - }; - }; -} diff --git a/home/modules/tmux/default.nix b/home/modules/tmux/default.nix deleted file mode 100644 index 54552f9..0000000 --- a/home/modules/tmux/default.nix +++ /dev/null @@ -1,52 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - tokyo-night = pkgs.tmuxPlugins.mkTmuxPlugin { - pluginName = "tokyo-night"; - rtpFilePath = "tokyo-night.tmux"; - version = "1.6.1"; - src = pkgs.fetchFromGitHub { - owner = "janoamaral"; - repo = "tokyo-night-tmux"; - rev = "d610ced20d5f602a7995854931440e4a1e0ab780"; - sha256 = "sha256-17vEgkL7C51p/l5gpT9dkOy0bY9n8l0/LV51mR1k+V8="; - }; - }; -in -{ - programs.tmux.enable = true; - programs.tmux.terminal = "tmux-direct"; - programs.tmux.keyMode = "vi"; - programs.tmux.escapeTime = 0; - programs.tmux.mouse = true; - programs.tmux.newSession = true; - programs.tmux.historyLimit = 50000; - programs.tmux.clock24 = true; - programs.tmux.baseIndex = 1; - programs.tmux.prefix = "M-\\\\"; - - programs.tmux.plugins = with pkgs; [ - tmuxPlugins.cpu - tmuxPlugins.battery - tmuxPlugins.better-mouse-mode - tmuxPlugins.net-speed - tmuxPlugins.online-status - tmuxPlugins.pain-control - tmuxPlugins.tilish - tmuxPlugins.yank - - { - plugin = tmuxPlugins.resurrect; - extraConfig = "set -g @resurrect-strategy-nvim 'session'"; - } - { - plugin = tmuxPlugins.continuum; - extraConfig = '' - set -g @continuum-restore 'on' - set -g @continuum-save-interval '15' # minutes - ''; - } - - tokyo-night - ]; -} diff --git a/home/modules/aerospace/default.nix b/home/roles/aerospace/default.nix similarity index 97% rename from home/modules/aerospace/default.nix rename to home/roles/aerospace/default.nix index c621948..127f11d 100644 --- a/home/modules/aerospace/default.nix +++ b/home/roles/aerospace/default.nix @@ -3,10 +3,10 @@ with lib; let - cfg = config.programs.aerospace; + cfg = config.home.roles.aerospace; in { - options.programs.aerospace = { + options.home.roles.aerospace = { enable = mkEnableOption "AeroSpace tiling window manager for macOS"; leader = mkOption { @@ -68,7 +68,7 @@ in assertions = [ { assertion = pkgs.stdenv.isDarwin; - message = "Aerospace module is only supported on macOS (Darwin) systems"; + message = "Aerospace role is only supported on macOS (Darwin) systems"; } ]; diff --git a/home/roles/default.nix b/home/roles/default.nix index 06fe344..ef4c321 100644 --- a/home/roles/default.nix +++ b/home/roles/default.nix @@ -11,5 +11,10 @@ ./media ./office ./sync + ./tmux + ./plasma-manager + ./emacs + ./aerospace + ./i3+sway ]; } diff --git a/home/modules/emacs/default.nix b/home/roles/emacs/default.nix similarity index 83% rename from home/modules/emacs/default.nix rename to home/roles/emacs/default.nix index 4640b23..6c7fdee 100644 --- a/home/modules/emacs/default.nix +++ b/home/roles/emacs/default.nix @@ -3,6 +3,8 @@ with lib; let + cfg = config.home.roles.emacs; + doomEmacs = pkgs.fetchFromGitHub { owner = "doomemacs"; repo = "doomemacs"; @@ -17,20 +19,23 @@ let ]; # Default emacs configuration with vterm support - defaultEmacsPackage = - if pkgs.stdenv.isDarwin + defaultEmacsPackage = + if pkgs.stdenv.isDarwin then pkgs.emacs-macport.pkgs.withPackages emacsPackages else pkgs.emacs.pkgs.withPackages emacsPackages; in { - config = { + options.home.roles.emacs = { + enable = mkEnableOption "Doom Emacs with vterm and tree-sitter support"; + }; + + config = mkIf cfg.enable { home.packages = [ pkgs.emacs-all-the-icons-fonts pkgs.fira-code pkgs.fontconfig pkgs.graphviz pkgs.isort - #pkgs.libvterm # native vterm library pkgs.nerd-fonts.fira-code pkgs.nerd-fonts.droid-sans-mono pkgs.nil # nix lsp language server @@ -66,7 +71,7 @@ in home.activation.doomConfig = lib.hm.dag.entryAfter ["writeBoundary"] '' # Always remove and recreate the symlink to ensure it points to the source directory rm -rf "${config.xdg.configHome}/doom" - ln -sf "${config.home.homeDirectory}/nixos-configs/home/modules/emacs/doom" "${config.xdg.configHome}/doom" + ln -sf "${config.home.homeDirectory}/nixos-configs/home/roles/emacs/doom" "${config.xdg.configHome}/doom" ''; }; } diff --git a/home/modules/emacs/doom/config.el b/home/roles/emacs/doom/config.el similarity index 100% rename from home/modules/emacs/doom/config.el rename to home/roles/emacs/doom/config.el diff --git a/home/modules/emacs/doom/init.el b/home/roles/emacs/doom/init.el similarity index 100% rename from home/modules/emacs/doom/init.el rename to home/roles/emacs/doom/init.el diff --git a/home/modules/emacs/doom/packages.el b/home/roles/emacs/doom/packages.el similarity index 100% rename from home/modules/emacs/doom/packages.el rename to home/roles/emacs/doom/packages.el diff --git a/home/modules/i3+sway/default.nix b/home/roles/i3+sway/default.nix similarity index 96% rename from home/modules/i3+sway/default.nix rename to home/roles/i3+sway/default.nix index e0ab409..b36682e 100644 --- a/home/modules/i3+sway/default.nix +++ b/home/roles/i3+sway/default.nix @@ -3,7 +3,7 @@ with lib; let - cfg = config.home.i3_sway; + cfg = config.home.roles.i3_sway; shared_config = recursiveUpdate rec { modifier = "Mod4"; @@ -93,19 +93,29 @@ let }; } cfg.extraSharedConfig; in { - options.home.i3_sway = { + options.home.roles.i3_sway = { + enable = mkEnableOption "i3 and Sway tiling window managers with waybar and rofi"; + extraSharedConfig = mkOption { + type = types.attrs; default = {}; + description = "Extra configuration shared between i3 and sway"; }; + extraI3Config = mkOption { + type = types.attrs; default = {}; + description = "Extra i3-specific configuration"; }; + extraSwayConfig = mkOption { + type = types.attrs; default = {}; + description = "Extra sway-specific configuration"; }; }; - config = { + config = mkIf cfg.enable { # i3blocks configuration file home.file.".config/i3blocks/config".text = '' # i3blocks config - replicating waybar setup diff --git a/home/roles/kubectl/default.nix b/home/roles/kubectl/default.nix index dda679f..da56360 100644 --- a/home/roles/kubectl/default.nix +++ b/home/roles/kubectl/default.nix @@ -7,10 +7,237 @@ let in { options.home.roles.kubectl = { - enable = mkEnableOption "Enable management tools for the homelab k3s oglenet cluster"; + enable = mkEnableOption "management tools for the homelab k3s oglenet cluster with secure Bitwarden integration"; }; config = mkIf cfg.enable { - programs.kubectl-secure.enable = true; + home.packages = with pkgs; [ + kubectl + kubernetes-helm + ]; + + programs.k9s.enable = true; + + programs.bash.initExtra = mkAfter '' + # Kubectl secure session management + export KUBECTL_SESSION_DIR="/dev/shm/kubectl-$$" + + kube-select() { + if [[ $# -ne 1 ]]; then + echo "Usage: kube-select " + echo "Available contexts: $(kube-list)" + return 1 + fi + + local context="$1" + + # Clean up any existing session first + kube-clear 2>/dev/null + + # Create new session directory + mkdir -p "$KUBECTL_SESSION_DIR" + chmod 700 "$KUBECTL_SESSION_DIR" + + # Set cleanup trap for this shell session + trap "rm -rf '$KUBECTL_SESSION_DIR' 2>/dev/null" EXIT + + # Set KUBECONFIG for this session + export KUBECONFIG="$KUBECTL_SESSION_DIR/config" + + # Load config from Bitwarden secure notes + if ! rbw get "kubectl-$context" > "$KUBECONFIG" 2>/dev/null; then + echo "Error: Could not retrieve kubectl-$context from Bitwarden" + echo "Make sure the entry exists with name: kubectl-$context" + kube-clear + return 1 + fi + + # Verify the kubeconfig is valid + if ! kubectl config view >/dev/null 2>&1; then + echo "Error: Invalid kubeconfig retrieved from Bitwarden" + kube-clear + return 1 + fi + + echo "✓ Loaded kubectl context: $context (session: $$)" + echo " Config location: $KUBECONFIG" + } + + kube-list() { + echo "Available kubectl contexts in Bitwarden:" + rbw search kubectl- 2>/dev/null | grep "^kubectl-" | sed 's/^kubectl-/ - /' || echo " (none found or rbw not accessible)" + } + + kube-clear() { + if [[ -n "$KUBECTL_TIMEOUT_PID" ]]; then + kill "$KUBECTL_TIMEOUT_PID" 2>/dev/null + unset KUBECTL_TIMEOUT_PID + fi + + if [[ -d "$KUBECTL_SESSION_DIR" ]]; then + rm -rf "$KUBECTL_SESSION_DIR" + echo "Cleared kubectl session ($$)" + fi + + unset KUBECONFIG + } + + kube-status() { + if [[ -f "$KUBECONFIG" ]]; then + local current_context + current_context=$(kubectl config current-context 2>/dev/null) + if [[ -n "$current_context" ]]; then + echo "Active kubectl context: $current_context" + echo "Session: $$ | Config: $KUBECONFIG" + + # Show cluster info + local cluster_server + cluster_server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null) + if [[ -n "$cluster_server" ]]; then + echo "Cluster: $cluster_server" + fi + else + echo "No active context in current session" + fi + else + echo "No kubectl session active in this shell" + echo "Use 'kube-select ' to start a session" + fi + } + + # Helper function to show available commands + kube-help() { + echo "Secure kubectl session management commands:" + echo "" + echo "Session management:" + echo " kube-select - Load kubeconfig from Bitwarden" + echo " kube-status - Show current session status" + echo " kube-clear - Clear current session" + echo "" + echo "Configuration management:" + echo " kube-list - List available contexts in Bitwarden" + echo "" + echo "Help:" + echo " kube-help - Show this help" + echo "" + echo "Examples:" + echo " kube-select prod # Loads from secure note" + echo " kubectl get pods" + echo " kube-clear" + echo "" + echo "Note: Kubeconfigs are stored as secure notes in Bitwarden" + } + ''; + + programs.zsh.initExtra = mkAfter '' + # Kubectl secure session management (zsh) + export KUBECTL_SESSION_DIR="/dev/shm/kubectl-$$" + + kube-select() { + if [[ $# -ne 1 ]]; then + echo "Usage: kube-select " + echo "Available contexts: $(kube-list)" + return 1 + fi + + local context="$1" + + # Clean up any existing session first + kube-clear 2>/dev/null + + # Create new session directory + mkdir -p "$KUBECTL_SESSION_DIR" + chmod 700 "$KUBECTL_SESSION_DIR" + + # Set cleanup trap for this shell session + trap "rm -rf '$KUBECTL_SESSION_DIR' 2>/dev/null" EXIT + + # Set KUBECONFIG for this session + export KUBECONFIG="$KUBECTL_SESSION_DIR/config" + + # Load config from Bitwarden secure notes + if ! rbw get "kubectl-$context" > "$KUBECONFIG" 2>/dev/null; then + echo "Error: Could not retrieve kubectl-$context from Bitwarden" + echo "Make sure the entry exists with name: kubectl-$context" + kube-clear + return 1 + fi + + # Verify the kubeconfig is valid + if ! kubectl config view >/dev/null 2>&1; then + echo "Error: Invalid kubeconfig retrieved from Bitwarden" + kube-clear + return 1 + fi + + echo "✓ Loaded kubectl context: $context (session: $$)" + echo " Config location: $KUBECONFIG" + } + + kube-list() { + echo "Available kubectl contexts in Bitwarden:" + rbw search kubectl- 2>/dev/null | grep "^kubectl-" | sed 's/^kubectl-/ - /' || echo " (none found or rbw not accessible)" + } + + kube-clear() { + if [[ -n "$KUBECTL_TIMEOUT_PID" ]]; then + kill "$KUBECTL_TIMEOUT_PID" 2>/dev/null + unset KUBECTL_TIMEOUT_PID + fi + + if [[ -d "$KUBECTL_SESSION_DIR" ]]; then + rm -rf "$KUBECTL_SESSION_DIR" + echo "Cleared kubectl session ($$)" + fi + + unset KUBECONFIG + } + + kube-status() { + if [[ -f "$KUBECONFIG" ]]; then + local current_context + current_context=$(kubectl config current-context 2>/dev/null) + if [[ -n "$current_context" ]]; then + echo "Active kubectl context: $current_context" + echo "Session: $$ | Config: $KUBECONFIG" + + # Show cluster info + local cluster_server + cluster_server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null) + if [[ -n "$cluster_server" ]]; then + echo "Cluster: $cluster_server" + fi + else + echo "No active context in current session" + fi + else + echo "No kubectl session active in this shell" + echo "Use 'kube-select ' to start a session" + fi + } + + # Helper function to show available commands + kube-help() { + echo "Secure kubectl session management commands:" + echo "" + echo "Session management:" + echo " kube-select - Load kubeconfig from Bitwarden" + echo " kube-status - Show current session status" + echo " kube-clear - Clear current session" + echo "" + echo "Configuration management:" + echo " kube-list - List available contexts in Bitwarden" + echo "" + echo "Help:" + echo " kube-help - Show this help" + echo "" + echo "Examples:" + echo " kube-select prod # Loads from secure note" + echo " kubectl get pods" + echo " kube-clear" + echo "" + echo "Note: Kubeconfigs are stored as secure notes in Bitwarden" + } + ''; }; } diff --git a/home/roles/plasma-manager/default.nix b/home/roles/plasma-manager/default.nix new file mode 100644 index 0000000..3942040 --- /dev/null +++ b/home/roles/plasma-manager/default.nix @@ -0,0 +1,188 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.home.roles.plasma-manager; +in +{ + options.home.roles.plasma-manager = { + enable = mkEnableOption "KDE Plasma desktop environment configuration"; + }; + + config = mkIf cfg.enable { + # The current KDE config can be output with the command: + # nix run github:nix-community/plasma-manager + # + # Plasma-manager options documentation + # https://nix-community.github.io/plasma-manager/options.xhtml + # + # TODO: (ambitious) Add Kmail support to plasma-manager + programs.plasma = { + enable = true; + overrideConfig = true; + + hotkeys.commands."launch-ghostty" = { + name = "Launch Ghostty"; + key = "Meta+Return"; + command = "ghostty"; + }; + + shortcuts = { + kmix = { + "decrease_microphone_volume" = "Microphone Volume Down"; + "decrease_volume" = "Volume Down"; + "decrease_volume_small" = "Shift+Volume Down"; + "increase_microphone_volume" = "Microphone Volume Up"; + "increase_volume" = "Volume Up"; + "increase_volume_small" = "Shift+Volume Up"; + "mic_mute" = ["Microphone Mute" "Meta+Volume Mute,Microphone Mute" "Meta+Volume Mute,Mute Microphone"]; + "mute" = "Volume Mute"; + }; + + mediacontrol = { + "mediavolumedown" = "none,,Media volume down"; + "mediavolumeup" = "none,,Media volume up"; + "nextmedia" = "Media Next"; + "pausemedia" = "Media Pause"; + "playmedia" = "none,,Play media playback"; + "playpausemedia" = "Media Play"; + "previousmedia" = "Media Previous"; + "stopmedia" = "Media Stop"; + }; + + ksmserver = { + "Lock Session" = ["Meta+Ctrl+Q" "Screensaver" "Screensaver,Lock Session"]; + }; + + kwin = { + "Window Close" = "Meta+Shift+Q"; + "Kill Window" = "Meta+Ctrl+Esc"; + "Window Operations Menu" = "Alt+F3"; + "Window Resize" = "Meta+R,,Resize Window"; + + "Overview" = "Meta+Ctrl+W"; + "Grid View" = "Meta+G"; + "Edit Tiles" = "Meta+T"; + + "Activate Window Demanding Attention" = "Meta+Ctrl+A"; + + "Show Desktop" = "Meta+Ctrl+D"; + + "Walk Through Windows" = "Alt+Tab"; + "Walk Through Windows (Reverse)" = "Alt+Shift+Tab"; + "Walk Through Windows of Current Application" = "Alt+`"; + "Walk Through Windows of Current Application (Reverse)" = "Alt+~"; + + "Window Quick Tile Bottom" = "Meta+Down"; + "Window Quick Tile Left" = "Meta+Left"; + "Window Quick Tile Right" = "Meta+Right"; + "Window Quick Tile Top" = "Meta+Up"; + + "Switch to Desktop 1" = "Meta+1"; + "Switch to Desktop 2" = "Meta+2"; + "Switch to Desktop 3" = "Meta+3"; + "Switch to Desktop 4" = "Meta+4"; + "Switch to Desktop 5" = "Meta+5"; + "Switch to Desktop 6" = "Meta+6"; + "Switch to Desktop 7" = "Meta+7"; + "Switch to Desktop 8" = "Meta+8"; + "Switch to Desktop 9" = "Meta+9"; + "Switch to Desktop 10" = "Meta+0"; + + "Window to Desktop 1" = "Meta+!"; # Meta+Shift+1 + "Window to Desktop 2" = "Meta+@"; # Meta+Shift+2 + "Window to Desktop 3" = "Meta+#"; # Meta+Shift+3 + "Window to Desktop 4" = "Meta+$"; # Meta+Shift+4 + "Window to Desktop 5" = "Meta+%"; # Meta+Shift+5 + "Window to Desktop 6" = "Meta+^"; # Meta+Shift+6 + "Window to Desktop 7" = "Meta+&"; # Meta+Shift+7 + "Window to Desktop 8" = "Meta+*"; # Meta+Shift+8 + "Window to Desktop 9" = "Meta+("; # Meta+Shift+9 + "Window to Desktop 10" = "Meta+)"; # Meta+Shift+0 + + "view_actual_size" = "Meta+Ctrl+="; + "view_zoom_in" = ["Meta++" "Meta+=,Meta++" "Meta+=,Zoom In"]; + "view_zoom_out" = "Meta+-"; + }; + "org_kde_powerdevil"."Decrease Keyboard Brightness" = "Keyboard Brightness Down"; + "org_kde_powerdevil"."Decrease Screen Brightness" = "Monitor Brightness Down"; + "org_kde_powerdevil"."Decrease Screen Brightness Small" = "Shift+Monitor Brightness Down"; + "org_kde_powerdevil"."Hibernate" = "Hibernate"; + "org_kde_powerdevil"."Increase Keyboard Brightness" = "Keyboard Brightness Up"; + "org_kde_powerdevil"."Increase Screen Brightness" = "Monitor Brightness Up"; + "org_kde_powerdevil"."Increase Screen Brightness Small" = "Shift+Monitor Brightness Up"; + "org_kde_powerdevil"."PowerDown" = "Power Down"; + "org_kde_powerdevil"."PowerOff" = "Power Off"; + "org_kde_powerdevil"."Sleep" = "Sleep"; + "org_kde_powerdevil"."Toggle Keyboard Backlight" = "Keyboard Light On/Off"; + "org_kde_powerdevil"."Turn Off Screen" = [ ]; + "org_kde_powerdevil"."powerProfile" = ["Battery" "Meta+B,Battery" "Meta+B,Switch Power Profile"]; + + plasmashell = { + "activate application launcher" = ["Meta" "Alt+F1,Meta" "Alt+F1,Activate Application Launcher"]; + "activate task manager entry 1" = "none,,"; + "activate task manager entry 2" = "none,,"; + "activate task manager entry 3" = "none,,"; + "activate task manager entry 4" = "none,,"; + "activate task manager entry 5" = "none,,"; + "activate task manager entry 6" = "none,,"; + "activate task manager entry 7" = "none,,"; + "activate task manager entry 8" = "none,,"; + "activate task manager entry 9" = "none,,"; + "activate task manager entry 10" = "none,,"; + "show activity switcher" = "none,,"; + }; + }; + + configFile = { + kwinrc.Desktops.Number = { + value = 10; + immutable = true; + }; + + # Enable KWin tiling features + kwinrc.Tiling = { + # Enable tiling functionality + "padding" = 4; + }; + + # Enable krohnkite plugin automatically + kwinrc.Plugins = { + krohnkiteEnabled = true; + }; + + kwinrc.Effect-overview = { + # Configure overview effect for better tiling workflow + BorderActivate = 9; # Top-left corner activation + }; + + kcminputrc.Libinput = { + AccelerationProfile = "adaptive"; + PointerAcceleration = 0.5; + }; + + kcminputrc.Mouse = { + X11LibInputXAccelProfileFlat = false; + XLbInptAccelProfileFlat = false; + }; + + kdeglobals.KDE.LookAndFeelPackage = "org.kde.breezedark.desktop"; + + # Focus follows mouse configuration + kwinrc.Windows = { + FocusPolicy = "FocusFollowsMouse"; + AutoRaise = true; # Set to true if you want windows to auto-raise on focus + AutoRaiseInterval = 750; # Delay in ms before auto-raise (if enabled) + DelayFocusInterval = 0; # Delay in ms before focus follows mouse + }; + + # Desktop wallpaper configuration + plasma-localerc.Formats.LANG = "en_US.UTF-8"; + + # Set wallpaper for all desktops + plasmarc.Wallpapers.usersWallpapers = "${../../wallpapers/metroid-samus-returns-kz-3440x1440.jpg}"; + }; + }; + }; +} diff --git a/home/roles/tmux/default.nix b/home/roles/tmux/default.nix new file mode 100644 index 0000000..4da877b --- /dev/null +++ b/home/roles/tmux/default.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.home.roles.tmux; + + tokyo-night = pkgs.tmuxPlugins.mkTmuxPlugin { + pluginName = "tokyo-night"; + rtpFilePath = "tokyo-night.tmux"; + version = "1.6.1"; + src = pkgs.fetchFromGitHub { + owner = "janoamaral"; + repo = "tokyo-night-tmux"; + rev = "d610ced20d5f602a7995854931440e4a1e0ab780"; + sha256 = "sha256-17vEgkL7C51p/l5gpT9dkOy0bY9n8l0/LV51mR1k+V8="; + }; + }; +in +{ + options.home.roles.tmux = { + enable = mkEnableOption "tmux terminal multiplexer with Tokyo Night theme"; + }; + + config = mkIf cfg.enable { + programs.tmux.enable = true; + programs.tmux.terminal = "tmux-direct"; + programs.tmux.keyMode = "vi"; + programs.tmux.escapeTime = 0; + programs.tmux.mouse = true; + programs.tmux.newSession = true; + programs.tmux.historyLimit = 50000; + programs.tmux.clock24 = true; + programs.tmux.baseIndex = 1; + programs.tmux.prefix = "M-\\\\"; + + programs.tmux.plugins = with pkgs; [ + tmuxPlugins.cpu + tmuxPlugins.battery + tmuxPlugins.better-mouse-mode + tmuxPlugins.net-speed + tmuxPlugins.online-status + tmuxPlugins.pain-control + tmuxPlugins.tilish + tmuxPlugins.yank + + { + plugin = tmuxPlugins.resurrect; + extraConfig = "set -g @resurrect-strategy-nvim 'session'"; + } + { + plugin = tmuxPlugins.continuum; + extraConfig = '' + set -g @continuum-restore 'on' + set -g @continuum-save-interval '15' # minutes + ''; + } + + tokyo-night + ]; + }; +}