├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── files ├── avatar │ └── face └── screenshots │ ├── hyprland.png │ └── mac.png ├── flake.lock ├── flake.nix ├── home └── nabokikh │ ├── energy │ └── default.nix │ ├── nabokikh-mac │ └── default.nix │ └── nabokikh-z13 │ └── default.nix ├── hosts ├── energy │ ├── default.nix │ └── hardware-configuration.nix ├── nabokikh-mac │ └── default.nix └── nabokikh-z13 │ ├── default.nix │ └── hardware-configuration.nix ├── modules ├── home-manager │ ├── common │ │ └── default.nix │ ├── desktop │ │ └── hyprland │ │ │ ├── default.nix │ │ │ └── hyprland.conf │ ├── misc │ │ ├── gtk │ │ │ └── default.nix │ │ ├── qt │ │ │ └── default.nix │ │ ├── wallpaper │ │ │ ├── default.nix │ │ │ └── wallpaper.jpg │ │ └── xdg │ │ │ └── default.nix │ ├── programs │ │ ├── aerospace │ │ │ └── default.nix │ │ ├── alacritty │ │ │ └── default.nix │ │ ├── atuin │ │ │ └── default.nix │ │ ├── bat │ │ │ └── default.nix │ │ ├── bottom │ │ │ └── default.nix │ │ ├── brave │ │ │ └── default.nix │ │ ├── btop │ │ │ └── default.nix │ │ ├── fastfetch │ │ │ └── default.nix │ │ ├── fzf │ │ │ └── default.nix │ │ ├── git │ │ │ └── default.nix │ │ ├── go │ │ │ └── default.nix │ │ ├── gpg │ │ │ └── default.nix │ │ ├── k9s │ │ │ └── default.nix │ │ ├── krew │ │ │ └── default.nix │ │ ├── lazygit │ │ │ └── default.nix │ │ ├── neovim │ │ │ ├── default.nix │ │ │ └── lazyvim │ │ │ │ ├── .luarc.json │ │ │ │ ├── .neoconf.json │ │ │ │ ├── init.lua │ │ │ │ ├── lua │ │ │ │ ├── config │ │ │ │ │ ├── autocmds.lua │ │ │ │ │ ├── keymaps.lua │ │ │ │ │ ├── lazy.lua │ │ │ │ │ └── options.lua │ │ │ │ └── plugins │ │ │ │ │ ├── catppucin.lua │ │ │ │ │ ├── helm-ls.lua │ │ │ │ │ ├── lsp.lua │ │ │ │ │ ├── mason.lua │ │ │ │ │ ├── neo-tree.lua │ │ │ │ │ ├── none-ls.lua │ │ │ │ │ ├── tmux-navigator.lua │ │ │ │ │ └── treesitter.lua │ │ │ │ └── stylua.toml │ │ ├── obs-studio │ │ │ └── default.nix │ │ ├── saml2aws │ │ │ └── default.nix │ │ ├── starship │ │ │ └── default.nix │ │ ├── swappy │ │ │ └── default.nix │ │ ├── telegram │ │ │ └── default.nix │ │ ├── tmux │ │ │ └── default.nix │ │ ├── ulauncher │ │ │ ├── config │ │ │ │ ├── ext_preferences │ │ │ │ │ └── com.github.nortmas.chrome-bookmarks.db │ │ │ │ ├── extensions.json │ │ │ │ ├── icons │ │ │ │ │ ├── brave.png │ │ │ │ │ ├── icon.svg │ │ │ │ │ ├── quit.png │ │ │ │ │ └── tools.png │ │ │ │ ├── settings.json │ │ │ │ └── user-themes │ │ │ │ │ └── Catppuccin-Macchiato-Lavender │ │ │ │ │ ├── manifest.json │ │ │ │ │ ├── theme-gtk-3.20.css │ │ │ │ │ └── theme.css │ │ │ └── default.nix │ │ ├── wofi │ │ │ └── default.nix │ │ └── zsh │ │ │ └── default.nix │ ├── scripts │ │ ├── bin │ │ │ ├── asg-getter │ │ │ ├── asg-rotator │ │ │ ├── cd-to-project │ │ │ ├── fif │ │ │ ├── fkill │ │ │ ├── git-reset │ │ │ ├── hyprshot │ │ │ ├── konfig-updater │ │ │ ├── ks │ │ │ ├── ocr │ │ │ ├── pull-all │ │ │ ├── screen-recorder │ │ │ ├── terra-clean │ │ │ ├── traverser │ │ │ └── waybar-restart │ │ └── default.nix │ └── services │ │ ├── cliphist │ │ └── default.nix │ │ ├── easyeffects │ │ └── default.nix │ │ ├── flatpak │ │ └── default.nix │ │ ├── kanshi │ │ └── default.nix │ │ ├── swaync │ │ ├── default.nix │ │ └── style.css │ │ └── waybar │ │ └── default.nix └── nixos │ ├── common │ └── default.nix │ ├── desktop │ └── hyprland │ │ └── default.nix │ ├── programs │ └── steam │ │ └── default.nix │ └── services │ └── tlp │ └── default.nix └── overlays └── default.nix /.gitignore: -------------------------------------------------------------------------------- 1 | files/configs/nvim/lazy-lock.json 2 | files/configs/nvim/lazyvim.json 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Alexander Nabokikh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Variables (override these as needed) 2 | HOSTNAME ?= $(shell hostname) 3 | FLAKE ?= .#$(HOSTNAME) 4 | HOME_TARGET ?= $(FLAKE) 5 | EXPERIMENTAL ?= --extra-experimental-features "nix-command flakes" 6 | 7 | .PHONY: help install-nix install-nix-darwin darwin-rebuild nixos-rebuild \ 8 | home-manager-switch nix-gc flake-update flake-check bootstrap-mac 9 | 10 | help: 11 | @echo "Available targets:" 12 | @echo " install-nix - Install the Nix package manager" 13 | @echo " install-nix-darwin - Install nix-darwin using flake $(FLAKE)" 14 | @echo " darwin-rebuild - Rebuild the nix-darwin configuration" 15 | @echo " nixos-rebuild - Rebuild the NixOS configuration" 16 | @echo " home-manager-switch - Switch the Home Manager configuration using flake $(HOME_TARGET)" 17 | @echo " nix-gc - Run Nix garbage collection" 18 | @echo " flake-update - Update flake inputs" 19 | @echo " flake-check - Check the flake for issues" 20 | @echo " bootstrap-mac - Install Nix and nix-darwin sequentially" 21 | 22 | install-nix: 23 | @echo "Installing Nix..." 24 | @sudo curl -L https://nixos.org/nix/install | sh -s -- --daemon --yes 25 | @echo "Nix installation complete." 26 | 27 | install-nix-darwin: 28 | @echo "Installing nix-darwin..." 29 | @nix run nix-darwin $(EXPERIMENTAL) -- switch --flake $(FLAKE) 30 | @echo "nix-darwin installation complete." 31 | 32 | darwin-rebuild: 33 | @echo "Rebuilding darwin configuration..." 34 | @darwin-rebuild switch --flake $(FLAKE) 35 | @echo "Darwin rebuild complete." 36 | 37 | nixos-rebuild: 38 | @echo "Rebuilding NixOS configuration..." 39 | @sudo nixos-rebuild switch --flake $(FLAKE) 40 | @echo "NixOS rebuild complete." 41 | 42 | home-manager-switch: 43 | @echo "Switching Home Manager configuration..." 44 | @home-manager switch --flake $(HOME_TARGET) 45 | @echo "Home Manager switch complete." 46 | 47 | nix-gc: 48 | @echo "Collecting Nix garbage..." 49 | @nix-collect-garbage -d 50 | @echo "Garbage collection complete." 51 | 52 | flake-update: 53 | @echo "Updating flake inputs..." 54 | @nix flake update 55 | @echo "Flake update complete." 56 | 57 | flake-check: 58 | @echo "Checking flake..." 59 | @nix flake check 60 | @echo "Flake check complete." 61 | 62 | bootstrap-mac: install-nix install-nix-darwin 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NixOS and nix-darwin Configurations for My Machines 2 | 3 | This repository contains NixOS and nix-darwin configurations for my machines, managed through [Nix Flakes](https://nixos.wiki/wiki/Flakes). 4 | 5 | It is structured to easily accommodate multiple machines and user configurations, leveraging [nixpkgs](https://github.com/NixOS/nixpkgs), [home-manager](https://github.com/nix-community/home-manager), [nix-darwin](https://github.com/LnL7/nix-darwin), and various other community contributions for a seamless experience across NixOS and macOS. 6 | 7 | ## Showcase 8 | 9 | ### Hyprland 10 | 11 | ![hyprland](./files/screenshots/hyprland.png) 12 | 13 | ### macOS 14 | 15 | ![macos](./files/screenshots/mac.png) 16 | 17 | ## Structure 18 | 19 | - `flake.nix`: The flake itself, defining inputs and outputs for NixOS, nix-darwin, and Home Manager configurations. 20 | - `hosts/`: NixOS and nix-darwin configurations for each machine 21 | - `home/`: Home Manager configurations for each machine 22 | - `files/`: Miscellaneous configuration files and scripts used across various applications and services 23 | - `modules/`: Reusable platform-specific modules 24 | - `nixos/`: NixOS-specific modules 25 | - `darwin/`: macOS-specific modules 26 | - `home-manager/`: User-space configuration modules 27 | - `flake.lock`: Lock file ensuring reproducible builds by pinning input versions 28 | - `overlays/`: Custom Nix overlays for package modifications or additions 29 | 30 | ### Key Inputs 31 | 32 | - **nixpkgs**: Points to the `nixos-unstable` channel for access to the latest packages 33 | - **nixpkgs-stable**: Points to the `nixos-25.05` channel, providing stable NixOS packages 34 | - **home-manager**: Manages user-specific configurations, following the `nixpkgs` input (release-25.05) 35 | - **hardware**: Optimizes settings for different hardware configurations 36 | - **catppuccin**: Provides global Catppuccin theme integration 37 | - **nix-flatpak**: Provides declarative way to manage flatpaks 38 | - **darwin**: Enables nix-darwin for macOS system configuration 39 | 40 | ## Usage 41 | 42 | ### Adding a New Machine with a New User 43 | 44 | To add a new machine with a new user to your NixOS or nix-darwin configuration, follow these steps: 45 | 46 | 1. **Update `flake.nix`**: 47 | 48 | a. Add the new user to the `users` attribute set: 49 | 50 | ```nix 51 | users = { 52 | # Existing users... 53 | newuser = { 54 | avatar = ./files/avatar/face; 55 | email = "newuser@example.com"; 56 | fullName = "New User"; 57 | gitKey = "YOUR_GIT_KEY"; 58 | name = "newuser"; 59 | }; 60 | }; 61 | ``` 62 | 63 | b. Add the new machine to the appropriate configuration set: 64 | 65 | For NixOS: 66 | 67 | ```nix 68 | nixosConfigurations = { 69 | # Existing configurations... 70 | newmachine = mkNixosConfiguration "newmachine" "newuser"; 71 | }; 72 | ``` 73 | 74 | For nix-darwin: 75 | 76 | ```nix 77 | darwinConfigurations = { 78 | # Existing configurations... 79 | newmachine = mkDarwinConfiguration "newmachine" "newuser"; 80 | }; 81 | ``` 82 | 83 | c. Add the new home configuration: 84 | 85 | ```nix 86 | homeConfigurations = { 87 | # Existing configurations... 88 | "newuser@newmachine" = mkHomeConfiguration "x86_64-linux" "newuser" "newmachine"; 89 | }; 90 | ``` 91 | 92 | 2. **Create System Configuration**: 93 | 94 | a. Create a new directory under `hosts/` for your machine: 95 | 96 | ```sh 97 | mkdir -p hosts/newmachine 98 | ``` 99 | 100 | b. Create `default.nix` in this directory: 101 | 102 | ```sh 103 | touch hosts/newmachine/default.nix 104 | ``` 105 | 106 | c. Add the basic configuration to `default.nix`: 107 | 108 | For NixOS: 109 | 110 | ```nix 111 | { inputs, hostname, nixosModules, ... }: 112 | { 113 | imports = [ 114 | inputs.hardware.nixosModules.common-cpu-amd 115 | ./hardware-configuration.nix 116 | "${nixosModules}/common" 117 | "${nixosModules}/programs/hyprland" 118 | ]; 119 | 120 | networking.hostName = hostname; 121 | } 122 | ``` 123 | 124 | For nix-darwin: 125 | 126 | ```nix 127 | { config, pkgs, ... }: 128 | { 129 | # Add machine-specific configurations here 130 | } 131 | ``` 132 | 133 | d. For NixOS, generate `hardware-configuration.nix`: 134 | 135 | ```sh 136 | sudo nixos-generate-config --show-hardware-config > hosts/newmachine/hardware-configuration.nix 137 | ``` 138 | 139 | 3. **Create Home Manager Configuration**: 140 | 141 | a. Create a new directory for the user's host-specific configuration: 142 | 143 | ```sh 144 | mkdir -p home/newuser/newmachine 145 | touch home/newuser/newmachine/default.nix 146 | ``` 147 | 148 | b. Add basic home configuration: 149 | 150 | ```nix 151 | { nhModules, ... }: 152 | { 153 | imports = [ 154 | "${nhModules}/common" 155 | "${nhModules}/programs/neovim" 156 | "${nhModules}/services/waybar" 157 | ]; 158 | } 159 | ``` 160 | 161 | 4. **Building and Applying Configurations**: 162 | 163 | a. Commit new files to git: 164 | 165 | ```sh 166 | git add . 167 | ``` 168 | 169 | b. Build and switch to the new system configuration: 170 | 171 | For NixOS: 172 | 173 | ```sh 174 | sudo nixos-rebuild switch --flake .#newmachine 175 | ``` 176 | 177 | For nix-darwin (requires Nix and nix-darwin installation first): 178 | 179 | ```sh 180 | darwin-rebuild switch --flake .#newmachine 181 | ``` 182 | 183 | c. Build and switch to the new Home Manager configuration: 184 | 185 | > [!IMPORTANT] 186 | > On fresh systems, bootstrap Home Manager first: 187 | 188 | ```sh 189 | nix-shell -p home-manager 190 | home-manager switch --flake .#newuser@newmachine 191 | ``` 192 | 193 | After this initial setup, you can rebuild configurations separately and home-manager will be available without additional steps 194 | 195 | ## Updating Flakes 196 | 197 | To update all flake inputs to their latest versions: 198 | 199 | ```sh 200 | nix flake update 201 | ``` 202 | 203 | ## Modules and Configurations 204 | 205 | ### System Modules (in `modules/nixos/`) 206 | 207 | - **`common/`**: Common system space configurations 208 | - **`hyprland.nix`**: Hyprland window manager 209 | - **`steam.nix`**: Steam gaming platform 210 | - **`tlp.nix`**: Laptop power management 211 | 212 | ### Home Manager Modules (in `modules/home-manager/`) 213 | 214 | - **`common/`**: Common user space configurations 215 | - **`aerospace` (Darwin):** Tiling window manager for macOS with custom keybindings and workspace rules. 216 | - **`alacritty`:** GPU-accelerated terminal emulator, configured for tmux integration and platform-specific font sizes/decorations. 217 | - **`atuin`:** Enhanced shell history with cloud sync capabilities. 218 | - **`bat`:** Cat clone with syntax highlighting and Git integration. 219 | - **`brave`:** Web browser with XDG MIME type associations (Linux). 220 | - **`btop`:** Resource monitor with Vim keys. 221 | - **`cliphist` (Linux/Hyprland):** Clipboard manager. 222 | - **`easyeffects` (Linux):** Audio effects processor with a custom "mic" preset for input. 223 | - **`fastfetch`:** Customized system information tool. 224 | - **`fzf`:** Command-line fuzzy finder. **Note:** The `ctrl-y` clipboard binding needs to be conditional (`pbcopy` for macOS, `wl-copy` for Wayland/Linux) for cross-platform compatibility. 225 | - **`git`:** Version control system, configured with user details, GPG signing, and `delta` for diffs. 226 | - **`go`:** Golang development environment setup. 227 | - **`gpg`:** GnuPG settings and GPG agent configuration (with `pinentry-gnome3` on Linux). 228 | - **`gtk`:** GTK3/4 theming (Tela-circle icons, Yaru cursor, Roboto font) and Catppuccin theme. 229 | - **`hyprland`**: Hyprland window manager setup 230 | - **`k9s`:** Kubernetes CLI To Manage Your Clusters In Style, with custom hotkeys. 231 | - **`kanshi` (Linux/Hyprland):** Dynamic display output configuration based on connected monitors. 232 | - **`krew`:** Kubectl plugin manager with a predefined list of plugins. 233 | - **`lazygit`:** Terminal UI for Git. 234 | - **`neovim`:** Highly customized Neovim setup based on LazyVim, with numerous LSP and development tool integrations. 235 | - **`obs-studio` (Linux):** Streaming and screen recording software. 236 | - **`qt` (Linux):** Qt theming using Kvantum and Catppuccin. 237 | - **`saml2aws`:** For AWS authentication via SAML. 238 | - **`scripts/`**: Collection of development utilities 239 | - **`starship`:** Cross-shell prompt with custom configuration. 240 | - **`swaync` (Linux/Hyprland):** Notification daemon. 241 | - **`telegram`:** Desktop client for Telegram. 242 | - **`tmux`:** Terminal multiplexer with custom keybindings and Catppuccin theme. 243 | - **`ulauncher` (Linux):** Application launcher with custom shortcuts for Brave search, system actions (lock, suspend, shutdown, reboot), and launching work applications. 244 | - **`wallpaper`:** Defines the default wallpaper path. 245 | - **`waybar` (Linux/Hyprland):** Highly customized Wayland status bar with modules for workspaces, system stats, clock, tray, etc. 246 | - **`xdg`:** Manages XDG user directories and default MIME type associations for applications like Totem, Loupe, and TextEditor. 247 | - **`zsh`:** Zsh shell with extensive aliases (git, kubectl), completions, and custom keybindings. 248 | 249 | ## Contributing 250 | 251 | Contributions are welcome! If you have improvements or suggestions, please open an issue or submit a pull request. 252 | 253 | ## License 254 | 255 | This repository is licensed under MIT License. Feel free to use, modify, and distribute according to the license terms. 256 | -------------------------------------------------------------------------------- /files/avatar/face: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/files/avatar/face -------------------------------------------------------------------------------- /files/screenshots/hyprland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/files/screenshots/hyprland.png -------------------------------------------------------------------------------- /files/screenshots/mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/files/screenshots/mac.png -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "catppuccin": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs" 6 | }, 7 | "locked": { 8 | "lastModified": 1748080874, 9 | "narHash": "sha256-sUebEzAkrY8Aq5G0GHFyRddmRNGP/a2iTtV7ISNvi/c=", 10 | "owner": "catppuccin", 11 | "repo": "nix", 12 | "rev": "0ba11b12be81f0849a89ed17ab635164ea8f0112", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "catppuccin", 17 | "repo": "nix", 18 | "type": "github" 19 | } 20 | }, 21 | "darwin": { 22 | "inputs": { 23 | "nixpkgs": [ 24 | "nixpkgs" 25 | ] 26 | }, 27 | "locked": { 28 | "lastModified": 1748352827, 29 | "narHash": "sha256-sNUUP6qxGkK9hXgJ+p362dtWLgnIWwOCmiq72LAWtYo=", 30 | "owner": "LnL7", 31 | "repo": "nix-darwin", 32 | "rev": "44a7d0e687a87b73facfe94fba78d323a6686a90", 33 | "type": "github" 34 | }, 35 | "original": { 36 | "owner": "LnL7", 37 | "repo": "nix-darwin", 38 | "type": "github" 39 | } 40 | }, 41 | "hardware": { 42 | "locked": { 43 | "lastModified": 1747900541, 44 | "narHash": "sha256-dn64Pg9xLETjblwZs9Euu/SsjW80pd6lr5qSiyLY1pg=", 45 | "owner": "nixos", 46 | "repo": "nixos-hardware", 47 | "rev": "11f2d9ea49c3e964315215d6baa73a8d42672f06", 48 | "type": "github" 49 | }, 50 | "original": { 51 | "owner": "nixos", 52 | "repo": "nixos-hardware", 53 | "type": "github" 54 | } 55 | }, 56 | "home-manager": { 57 | "inputs": { 58 | "nixpkgs": [ 59 | "nixpkgs" 60 | ] 61 | }, 62 | "locked": { 63 | "lastModified": 1748570847, 64 | "narHash": "sha256-XU1a6wFctd+s3ZvBIFB6s4GhPJ+Oc6pkeOrEsbA2fMo=", 65 | "owner": "nix-community", 66 | "repo": "home-manager", 67 | "rev": "4e9efaa68b0be7e19127dad4f0506a9b89e28ef4", 68 | "type": "github" 69 | }, 70 | "original": { 71 | "owner": "nix-community", 72 | "repo": "home-manager", 73 | "type": "github" 74 | } 75 | }, 76 | "nix-flatpak": { 77 | "locked": { 78 | "lastModified": 1739444422, 79 | "narHash": "sha256-iAVVHi7X3kWORftY+LVbRiStRnQEob2TULWyjMS6dWg=", 80 | "owner": "gmodena", 81 | "repo": "nix-flatpak", 82 | "rev": "5e54c3ca05a7c7d968ae1ddeabe01d2a9bc1e177", 83 | "type": "github" 84 | }, 85 | "original": { 86 | "owner": "gmodena", 87 | "ref": "v0.6.0", 88 | "repo": "nix-flatpak", 89 | "type": "github" 90 | } 91 | }, 92 | "nixpkgs": { 93 | "locked": { 94 | "lastModified": 1744463964, 95 | "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", 96 | "owner": "NixOS", 97 | "repo": "nixpkgs", 98 | "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", 99 | "type": "github" 100 | }, 101 | "original": { 102 | "owner": "NixOS", 103 | "ref": "nixos-unstable", 104 | "repo": "nixpkgs", 105 | "type": "github" 106 | } 107 | }, 108 | "nixpkgs-stable": { 109 | "locked": { 110 | "lastModified": 1748302896, 111 | "narHash": "sha256-ixMT0a8mM091vSswlTORZj93WQAJsRNmEvqLL+qwTFM=", 112 | "owner": "nixos", 113 | "repo": "nixpkgs", 114 | "rev": "7848cd8c982f7740edf76ddb3b43d234cb80fc4d", 115 | "type": "github" 116 | }, 117 | "original": { 118 | "owner": "nixos", 119 | "ref": "nixos-25.05", 120 | "repo": "nixpkgs", 121 | "type": "github" 122 | } 123 | }, 124 | "nixpkgs_2": { 125 | "locked": { 126 | "lastModified": 1748370509, 127 | "narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=", 128 | "owner": "nixos", 129 | "repo": "nixpkgs", 130 | "rev": "4faa5f5321320e49a78ae7848582f684d64783e9", 131 | "type": "github" 132 | }, 133 | "original": { 134 | "owner": "nixos", 135 | "ref": "nixos-unstable", 136 | "repo": "nixpkgs", 137 | "type": "github" 138 | } 139 | }, 140 | "root": { 141 | "inputs": { 142 | "catppuccin": "catppuccin", 143 | "darwin": "darwin", 144 | "hardware": "hardware", 145 | "home-manager": "home-manager", 146 | "nix-flatpak": "nix-flatpak", 147 | "nixpkgs": "nixpkgs_2", 148 | "nixpkgs-stable": "nixpkgs-stable" 149 | } 150 | } 151 | }, 152 | "root": "root", 153 | "version": 7 154 | } 155 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "NixOS and nix-darwin configs for my machines"; 3 | inputs = { 4 | # Nixpkgs 5 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 6 | nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05"; 7 | 8 | # Home manager 9 | home-manager = { 10 | url = "github:nix-community/home-manager"; 11 | inputs.nixpkgs.follows = "nixpkgs"; 12 | }; 13 | 14 | # NixOS profiles to optimize settings for different hardware 15 | hardware.url = "github:nixos/nixos-hardware"; 16 | 17 | # Global catppuccin theme 18 | catppuccin.url = "github:catppuccin/nix"; 19 | 20 | # Declarative flatpak manager 21 | nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=v0.6.0"; 22 | 23 | # Nix Darwin (for MacOS machines) 24 | darwin = { 25 | url = "github:LnL7/nix-darwin"; 26 | inputs.nixpkgs.follows = "nixpkgs"; 27 | }; 28 | }; 29 | 30 | outputs = { 31 | self, 32 | catppuccin, 33 | darwin, 34 | home-manager, 35 | nixpkgs, 36 | ... 37 | } @ inputs: let 38 | inherit (self) outputs; 39 | 40 | # Define user configurations 41 | users = { 42 | nabokikh = { 43 | avatar = ./files/avatar/face; 44 | email = "alexander.nabokikh@olx.pl"; 45 | fullName = "Alexander Nabokikh"; 46 | gitKey = "C5810093"; 47 | name = "nabokikh"; 48 | }; 49 | }; 50 | 51 | # Function for NixOS system configuration 52 | mkNixosConfiguration = hostname: username: 53 | nixpkgs.lib.nixosSystem { 54 | specialArgs = { 55 | inherit inputs outputs hostname; 56 | userConfig = users.${username}; 57 | nixosModules = "${self}/modules/nixos"; 58 | }; 59 | modules = [./hosts/${hostname}]; 60 | }; 61 | 62 | # Function for nix-darwin system configuration 63 | mkDarwinConfiguration = hostname: username: 64 | darwin.lib.darwinSystem { 65 | system = "aarch64-darwin"; 66 | specialArgs = { 67 | inherit inputs outputs hostname; 68 | userConfig = users.${username}; 69 | }; 70 | modules = [ 71 | ./hosts/${hostname} 72 | home-manager.darwinModules.home-manager 73 | ]; 74 | }; 75 | 76 | # Function for Home Manager configuration 77 | mkHomeConfiguration = system: username: hostname: 78 | home-manager.lib.homeManagerConfiguration { 79 | pkgs = import nixpkgs {inherit system;}; 80 | extraSpecialArgs = { 81 | inherit inputs outputs; 82 | userConfig = users.${username}; 83 | nhModules = "${self}/modules/home-manager"; 84 | }; 85 | modules = [ 86 | ./home/${username}/${hostname} 87 | catppuccin.homeModules.catppuccin 88 | ]; 89 | }; 90 | in { 91 | nixosConfigurations = { 92 | energy = mkNixosConfiguration "energy" "nabokikh"; 93 | nabokikh-z13 = mkNixosConfiguration "nabokikh-z13" "nabokikh"; 94 | }; 95 | 96 | darwinConfigurations = { 97 | "nabokikh-mac" = mkDarwinConfiguration "nabokikh-mac" "nabokikh"; 98 | }; 99 | 100 | homeConfigurations = { 101 | "nabokikh@energy" = mkHomeConfiguration "x86_64-linux" "nabokikh" "energy"; 102 | "nabokikh@nabokikh-mac" = mkHomeConfiguration "aarch64-darwin" "nabokikh" "nabokikh-mac"; 103 | "nabokikh@nabokikh-z13" = mkHomeConfiguration "x86_64-linux" "nabokikh" "nabokikh-z13"; 104 | }; 105 | 106 | overlays = import ./overlays {inherit inputs;}; 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /home/nabokikh/energy/default.nix: -------------------------------------------------------------------------------- 1 | {nhModules, ...}: { 2 | imports = [ 3 | "${nhModules}/common" 4 | "${nhModules}/desktop/hyprland" 5 | ]; 6 | 7 | # Enable home-manager 8 | programs.home-manager.enable = true; 9 | 10 | # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion 11 | home.stateVersion = "25.05"; 12 | } 13 | -------------------------------------------------------------------------------- /home/nabokikh/nabokikh-mac/default.nix: -------------------------------------------------------------------------------- 1 | {nhModules, ...}: { 2 | imports = [ 3 | "${nhModules}/common" 4 | ]; 5 | 6 | # Enable home-manager 7 | programs.home-manager.enable = true; 8 | 9 | # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion 10 | home.stateVersion = "25.05"; 11 | } 12 | -------------------------------------------------------------------------------- /home/nabokikh/nabokikh-z13/default.nix: -------------------------------------------------------------------------------- 1 | {nhModules, ...}: { 2 | imports = [ 3 | "${nhModules}/common" 4 | "${nhModules}/desktop/hyprland" 5 | ]; 6 | 7 | # Enable home-manager 8 | programs.home-manager.enable = true; 9 | 10 | # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion 11 | home.stateVersion = "25.05"; 12 | } 13 | -------------------------------------------------------------------------------- /hosts/energy/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | hostname, 4 | nixosModules, 5 | ... 6 | }: { 7 | imports = [ 8 | inputs.hardware.nixosModules.common-cpu-amd 9 | inputs.hardware.nixosModules.common-gpu-amd 10 | inputs.hardware.nixosModules.common-pc-ssd 11 | 12 | ./hardware-configuration.nix 13 | "${nixosModules}/common" 14 | "${nixosModules}/desktop/hyprland" 15 | "${nixosModules}/programs/steam" 16 | ]; 17 | 18 | # Set hostname 19 | networking.hostName = hostname; 20 | 21 | # This value determines the NixOS release from which the default 22 | # settings for stateful data, like file locations and database versions 23 | # on your system were taken. It‘s perfectly fine and recommended to leave 24 | # this value at the release version of the first install of this system. 25 | system.stateVersion = "25.05"; 26 | } 27 | -------------------------------------------------------------------------------- /hosts/energy/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { 5 | config, 6 | lib, 7 | modulesPath, 8 | ... 9 | }: { 10 | imports = [ 11 | (modulesPath + "/installer/scan/not-detected.nix") 12 | ]; 13 | 14 | boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod"]; 15 | boot.initrd.kernelModules = []; 16 | 17 | fileSystems."/" = { 18 | device = "/dev/disk/by-label/NIXROOT"; 19 | fsType = "ext4"; 20 | }; 21 | 22 | fileSystems."/boot" = { 23 | device = "/dev/disk/by-label/NIXBOOT"; 24 | fsType = "vfat"; 25 | }; 26 | 27 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 28 | # (the default) this is the recommended approach. When using systemd-networkd it's 29 | # still possible to use this option, but it's recommended to use it in conjunction 30 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 31 | networking.useDHCP = lib.mkDefault true; 32 | # networking.interfaces.enp6s0.useDHCP = lib.mkDefault true; 33 | # networking.interfaces.enp7s0.useDHCP = lib.mkDefault true; 34 | # networking.interfaces.wlp5s0.useDHCP = lib.mkDefault true; 35 | 36 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 37 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 38 | } 39 | -------------------------------------------------------------------------------- /hosts/nabokikh-mac/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | outputs, 4 | userConfig, 5 | ... 6 | }: { 7 | # Nixpkgs configuration 8 | nixpkgs = { 9 | overlays = [ 10 | outputs.overlays.stable-packages 11 | ]; 12 | 13 | config = { 14 | allowUnfree = true; 15 | }; 16 | }; 17 | 18 | # Nix settings 19 | nix = { 20 | settings = { 21 | experimental-features = "nix-command flakes"; 22 | }; 23 | optimise.automatic = true; 24 | package = pkgs.nix; 25 | }; 26 | 27 | # User configuration 28 | users.users.${userConfig.name} = { 29 | name = "${userConfig.name}"; 30 | home = "/Users/${userConfig.name}"; 31 | }; 32 | 33 | # Add ability to use TouchID for sudo 34 | security.pam.services.sudo_local.touchIdAuth = true; 35 | 36 | # System settings 37 | system = { 38 | defaults = { 39 | CustomUserPreferences = { 40 | NSGlobalDomain."com.apple.mouse.linear" = true; 41 | }; 42 | NSGlobalDomain = { 43 | AppleInterfaceStyle = "Dark"; 44 | ApplePressAndHoldEnabled = false; 45 | AppleShowAllExtensions = true; 46 | KeyRepeat = 2; 47 | NSAutomaticCapitalizationEnabled = false; 48 | NSAutomaticDashSubstitutionEnabled = false; 49 | NSAutomaticQuoteSubstitutionEnabled = false; 50 | NSAutomaticSpellingCorrectionEnabled = false; 51 | NSAutomaticWindowAnimationsEnabled = false; 52 | NSDocumentSaveNewDocumentsToCloud = false; 53 | NSNavPanelExpandedStateForSaveMode = true; 54 | PMPrintingExpandedStateForPrint = true; 55 | }; 56 | LaunchServices = { 57 | LSQuarantine = false; 58 | }; 59 | trackpad = { 60 | TrackpadRightClick = true; 61 | TrackpadThreeFingerDrag = true; 62 | Clicking = true; 63 | }; 64 | finder = { 65 | AppleShowAllFiles = true; 66 | CreateDesktop = false; 67 | FXDefaultSearchScope = "SCcf"; 68 | FXEnableExtensionChangeWarning = false; 69 | FXPreferredViewStyle = "Nlsv"; 70 | QuitMenuItem = true; 71 | ShowPathbar = true; 72 | ShowStatusBar = true; 73 | _FXShowPosixPathInTitle = true; 74 | _FXSortFoldersFirst = true; 75 | }; 76 | dock = { 77 | autohide = true; 78 | expose-animation-duration = 0.15; 79 | show-recents = false; 80 | showhidden = true; 81 | persistent-apps = []; 82 | tilesize = 30; 83 | wvous-bl-corner = 1; 84 | wvous-br-corner = 1; 85 | wvous-tl-corner = 1; 86 | wvous-tr-corner = 1; 87 | }; 88 | screencapture = { 89 | location = "/Users/${userConfig.name}/Downloads/temp"; 90 | type = "png"; 91 | disable-shadow = true; 92 | }; 93 | }; 94 | keyboard = { 95 | enableKeyMapping = true; 96 | # Remap §± to ~ 97 | userKeyMapping = [ 98 | { 99 | HIDKeyboardModifierMappingDst = 30064771125; 100 | HIDKeyboardModifierMappingSrc = 30064771172; 101 | } 102 | ]; 103 | }; 104 | }; 105 | 106 | # Zsh configuration 107 | programs.zsh.enable = true; 108 | 109 | # Fonts configuration 110 | fonts.packages = with pkgs; [ 111 | nerd-fonts.meslo-lg 112 | ]; 113 | 114 | # Used for backwards compatibility, please read the changelog before changing. 115 | system.stateVersion = 6; 116 | } 117 | -------------------------------------------------------------------------------- /hosts/nabokikh-z13/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | hostname, 4 | nixosModules, 5 | ... 6 | }: { 7 | imports = [ 8 | inputs.hardware.nixosModules.lenovo-thinkpad-z13-gen1 9 | 10 | ./hardware-configuration.nix 11 | "${nixosModules}/common" 12 | "${nixosModules}/services/tlp" 13 | "${nixosModules}/desktop/hyprland" 14 | ]; 15 | 16 | # Set hostname 17 | networking.hostName = hostname; 18 | 19 | # This value determines the NixOS release from which the default 20 | # settings for stateful data, like file locations and database versions 21 | # on your system were taken. It‘s perfectly fine and recommended to leave 22 | # this value at the release version of the first install of this system. 23 | system.stateVersion = "25.05"; 24 | } 25 | -------------------------------------------------------------------------------- /hosts/nabokikh-z13/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { 5 | config, 6 | lib, 7 | modulesPath, 8 | ... 9 | }: { 10 | imports = [ 11 | (modulesPath + "/installer/scan/not-detected.nix") 12 | ]; 13 | 14 | boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod"]; 15 | boot.initrd.kernelModules = []; 16 | 17 | fileSystems."/" = { 18 | device = "/dev/disk/by-label/NIXROOT"; 19 | fsType = "ext4"; 20 | }; 21 | 22 | fileSystems."/boot" = { 23 | device = "/dev/disk/by-label/NIXBOOT"; 24 | fsType = "vfat"; 25 | }; 26 | 27 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 28 | # (the default) this is the recommended approach. When using systemd-networkd it's 29 | # still possible to use this option, but it's recommended to use it in conjunction 30 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 31 | networking.useDHCP = lib.mkDefault true; 32 | # networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true; 33 | 34 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 35 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 36 | } 37 | -------------------------------------------------------------------------------- /modules/home-manager/common/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | outputs, 3 | userConfig, 4 | pkgs, 5 | ... 6 | }: { 7 | imports = [ 8 | ../misc/qt 9 | ../programs/aerospace 10 | ../programs/alacritty 11 | ../programs/atuin 12 | ../programs/bat 13 | ../programs/brave 14 | ../programs/btop 15 | ../programs/fastfetch 16 | ../programs/fzf 17 | ../programs/git 18 | ../programs/go 19 | ../programs/gpg 20 | ../programs/k9s 21 | ../programs/krew 22 | ../programs/lazygit 23 | ../programs/neovim 24 | ../programs/obs-studio 25 | ../programs/saml2aws 26 | ../programs/starship 27 | ../programs/telegram 28 | ../programs/tmux 29 | ../programs/ulauncher 30 | ../programs/zsh 31 | ../scripts 32 | ../services/easyeffects 33 | ../services/flatpak 34 | ]; 35 | 36 | # Nixpkgs configuration 37 | nixpkgs = { 38 | overlays = [ 39 | outputs.overlays.stable-packages 40 | ]; 41 | 42 | config = { 43 | allowUnfree = true; 44 | }; 45 | }; 46 | 47 | # Nicely reload system units when changing configs 48 | systemd.user.startServices = "sd-switch"; 49 | 50 | # Home-Manager configuration for the user's home environment 51 | home = { 52 | username = "${userConfig.name}"; 53 | homeDirectory = 54 | if pkgs.stdenv.isDarwin 55 | then "/Users/${userConfig.name}" 56 | else "/home/${userConfig.name}"; 57 | }; 58 | 59 | # Ensure common packages are installed 60 | home.packages = with pkgs; 61 | [ 62 | anki-bin 63 | awscli2 64 | dig 65 | du-dust 66 | eza 67 | fd 68 | jq 69 | kubectl 70 | lazydocker 71 | nh 72 | openconnect 73 | pipenv 74 | python3 75 | ripgrep 76 | terraform 77 | ] 78 | ++ lib.optionals stdenv.isDarwin [ 79 | colima 80 | docker 81 | hidden-bar 82 | raycast 83 | ] 84 | ++ lib.optionals (!stdenv.isDarwin) [ 85 | pavucontrol 86 | tesseract 87 | unzip 88 | wl-clipboard 89 | ]; 90 | 91 | # Catpuccin flavor and accent 92 | catppuccin = { 93 | flavor = "macchiato"; 94 | accent = "lavender"; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /modules/home-manager/desktop/hyprland/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | nhModules, 5 | pkgs, 6 | ... 7 | }: { 8 | imports = [ 9 | "${nhModules}/misc/gtk" 10 | "${nhModules}/misc/wallpaper" 11 | "${nhModules}/misc/xdg" 12 | "${nhModules}/programs/swappy" 13 | "${nhModules}/programs/wofi" 14 | "${nhModules}/services/cliphist" 15 | "${nhModules}/services/kanshi" 16 | "${nhModules}/services/swaync" 17 | "${nhModules}/services/waybar" 18 | ]; 19 | 20 | # Consistent cursor theme across all applications. 21 | home.pointerCursor = { 22 | gtk.enable = true; 23 | x11.enable = true; 24 | package = pkgs.yaru-theme; 25 | name = "Yaru"; 26 | size = 24; 27 | }; 28 | 29 | # Source hyprland config from the home-manager store 30 | xdg.configFile = { 31 | "hypr/hyprland.conf" = { 32 | source = ./hyprland.conf; 33 | }; 34 | 35 | "hypr/hyprpaper.conf".text = '' 36 | splash = false 37 | preload = ${config.wallpaper} 38 | wallpaper = DP-1, ${config.wallpaper} 39 | wallpaper = eDP-1, ${config.wallpaper} 40 | ''; 41 | 42 | "hypr/hypridle.conf".text = '' 43 | general { 44 | lock_cmd = pidof hyprlock || hyprlock 45 | before_sleep_cmd = loginctl lock-session 46 | after_sleep_cmd = hyprctl dispatch dpms on 47 | } 48 | ''; 49 | 50 | "hypr/hyprlock.conf".text = '' 51 | background { 52 | monitor = 53 | path = ${config.wallpaper} 54 | blur_passes = 3 55 | contrast = 0.8916 56 | brightness = 0.8172 57 | vibrancy = 0.1696 58 | vibrancy_darkness = 0.0 59 | } 60 | 61 | general { 62 | grace = 0 63 | fail_timeout = 1000 64 | } 65 | 66 | # DP-1 Conifg 67 | input-field { 68 | monitor = DP-1 69 | size = 250, 60 70 | outline_thickness = 2 71 | dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8 72 | dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0 73 | dots_center = true 74 | outer_color = rgba(0, 0, 0, 0) 75 | inner_color = rgba(0, 0, 0, 0.5) 76 | font_color = rgb(200, 200, 200) 77 | fade_on_empty = false 78 | capslock_color = -1 79 | placeholder_text = Password 80 | fail_text = $FAIL ($ATTEMPTS) 81 | hide_input = false 82 | position = 0, -120 83 | halign = center 84 | valign = center 85 | } 86 | 87 | # Date 88 | label { 89 | monitor = DP-1 90 | text = cmd[update:1000] echo "$(date '+%A, %d %B')" 91 | color = rgba(255, 255, 255, 0.8) 92 | font_size = 15 93 | font_family = JetBrains Mono Nerd Font Mono ExtraBold 94 | position = 0, -400 95 | halign = center 96 | valign = top 97 | } 98 | 99 | # Time 100 | label { 101 | monitor = DP-1 102 | text = cmd[update:1000] echo "$(date '+%H:%M')" 103 | color = rgba(255, 255, 255, 0.8) 104 | font_size = 120 105 | font_family = JetBrains Mono Nerd Font Mono ExtraBold 106 | position = 0, -400 107 | halign = center 108 | valign = top 109 | } 110 | 111 | # Keyboard layout 112 | label { 113 | monitor = DP-1 114 | text = $LAYOUT 115 | color = rgba(255, 255, 255, 0.9) 116 | font_size = 10 117 | font_family = JetBrains Mono Nerd Font Mono 118 | position = 0, -175 119 | halign = center 120 | valign = center 121 | } 122 | 123 | # eDP-1 Conifg 124 | input-field { 125 | monitor = eDP-1 126 | size = 500, 120 127 | outline_thickness = 2 128 | dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8 129 | dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0 130 | dots_center = true 131 | outer_color = rgba(0, 0, 0, 0) 132 | inner_color = rgba(0, 0, 0, 0.5) 133 | font_color = rgb(200, 200, 200) 134 | fade_on_empty = false 135 | capslock_color = -1 136 | placeholder_text = Password 137 | fail_text = $FAIL ($ATTEMPTS) 138 | hide_input = false 139 | position = 0, -120 140 | halign = center 141 | valign = center 142 | } 143 | 144 | # Date 145 | label { 146 | monitor = eDP-1 147 | text = cmd[update:1000] echo "$(date '+%A, %d %B')" 148 | color = rgba(255, 255, 255, 0.8) 149 | font_size = 30 150 | font_family = JetBrains Mono Nerd Font Mono ExtraBold 151 | position = 0, -400 152 | halign = center 153 | valign = top 154 | } 155 | 156 | # Time 157 | label { 158 | monitor = eDP-1 159 | text = cmd[update:1000] echo "$(date '+%H:%M')" 160 | color = rgba(255, 255, 255, 0.8) 161 | font_size = 240 162 | font_family = JetBrains Mono Nerd Font Mono ExtraBold 163 | position = 0, -400 164 | halign = center 165 | valign = top 166 | } 167 | 168 | # Keyboard layout 169 | label { 170 | monitor = eDP-1 171 | text = $LAYOUT 172 | color = rgba(255, 255, 255, 0.9) 173 | font_size = 20 174 | font_family = JetBrains Mono Nerd Font Mono 175 | position = 0, -230 176 | halign = center 177 | valign = center 178 | } 179 | ''; 180 | }; 181 | 182 | dconf.settings = { 183 | "org/blueman/general" = { 184 | "plugin-list" = lib.mkForce ["!StatusNotifierItem"]; 185 | }; 186 | 187 | "org/blueman/plugins/powermanager" = { 188 | "auto-power-on" = true; 189 | }; 190 | 191 | "org/gnome/calculator" = { 192 | "accuracy" = 9; 193 | "angle-units" = "degrees"; 194 | "base" = 10; 195 | "button-mode" = "basic"; 196 | "number-format" = "automatic"; 197 | "show-thousands" = false; 198 | "show-zeroes" = false; 199 | "source-currency" = ""; 200 | "source-units" = "degree"; 201 | "target-currency" = ""; 202 | "target-units" = "radian"; 203 | "window-maximized" = false; 204 | }; 205 | 206 | "org/gnome/desktop/interface" = { 207 | "color-scheme" = "prefer-dark"; 208 | "cursor-theme" = "Yaru"; 209 | "font-name" = "Roboto 11"; 210 | "icon-theme" = "Tela-circle-dark"; 211 | }; 212 | 213 | "org/gnome/desktop/wm/preferences" = { 214 | "button-layout" = lib.mkForce ""; 215 | }; 216 | 217 | "org/gnome/nautilus/preferences" = { 218 | "default-folder-viewer" = "list-view"; 219 | "migrated-gtk-settings" = true; 220 | "search-filter-time-type" = "last_modified"; 221 | "search-view" = "list-view"; 222 | }; 223 | 224 | "org/gnome/nm-applet" = { 225 | "disable-connected-notifications" = true; 226 | "disable-vpn-notifications" = true; 227 | }; 228 | 229 | "org/gtk/gtk4/settings/file-chooser" = { 230 | "show-hidden" = true; 231 | }; 232 | 233 | "org/gtk/settings/file-chooser" = { 234 | "date-format" = "regular"; 235 | "location-mode" = "path-bar"; 236 | "show-hidden" = true; 237 | "show-size-column" = true; 238 | "show-type-column" = true; 239 | "sort-column" = "name"; 240 | "sort-directories-first" = false; 241 | "sort-order" = "ascending"; 242 | "type-format" = "category"; 243 | "view-type" = "list"; 244 | }; 245 | }; 246 | } 247 | -------------------------------------------------------------------------------- /modules/home-manager/desktop/hyprland/hyprland.conf: -------------------------------------------------------------------------------- 1 | # Load wallpapers 2 | exec-once = hyprpaper 3 | 4 | # Monitor settings 5 | monitor = DP-1, preferred, auto, 1 6 | monitor = eDP-1, preferred, auto, 2 7 | monitor = desc:Dell Inc. DELL U2724DE, highrr, auto, 1 8 | 9 | # Execute your favorite apps at launch 10 | exec-once = hypridle 11 | exec-once = gnome-keyring-daemon --start --components=secrets 12 | exec-once = kanshi 13 | exec-once = nm-applet --indicator 14 | exec-once = swaync 15 | exec-once = ulauncher --hide-window 16 | exec-once = waybar 17 | exec-once = wl-paste --watch cliphist store 18 | exec-once = wlsunset -l 52.23 -L 21.01 19 | 20 | # Input device setting 21 | input { 22 | kb_layout = pl,ru 23 | kb_options = grp:win_space_toggle 24 | repeat_delay = 250 25 | repeat_rate = 40 26 | 27 | follow_mouse = 1 28 | mouse_refocus = false 29 | 30 | touchpad { 31 | natural_scroll = true 32 | } 33 | 34 | sensitivity = 0 # -1.0 - 1.0, 0 means no modification. 35 | accel_profile = flat 36 | } 37 | 38 | # General settings 39 | general { 40 | allow_tearing = false 41 | border_size = 1 42 | col.active_border = rgb(b7bdf8) 43 | gaps_in = 3 44 | gaps_out = 3 45 | layout = master 46 | } 47 | 48 | # Window decorations settings 49 | decoration { 50 | rounding = 8 51 | blur { 52 | enabled = false 53 | size = 3 54 | passes = 1 55 | } 56 | shadow { 57 | enabled = false 58 | range = 4 59 | render_power = 3 60 | color = rgba(1a1a1aee) 61 | } 62 | } 63 | 64 | # Animations settings 65 | animations { 66 | enabled = false 67 | bezier = myBezier, 0.05, 0.9, 0.1, 1.05 68 | animation = windows, 1, 7, myBezier 69 | animation = windowsOut, 1, 7, default, popin 80% 70 | animation = border, 1, 10, default 71 | animation = borderangle, 1, 8, default 72 | animation = fade, 1, 7, default 73 | animation = workspaces, 1, 6, default 74 | } 75 | 76 | # Layouts settings 77 | dwindle { 78 | pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below 79 | preserve_split = true # you probably want this 80 | } 81 | 82 | master { 83 | orientation = left 84 | mfact = 0.50 85 | } 86 | 87 | # Mouse gestures settings 88 | gestures { 89 | workspace_swipe = on 90 | } 91 | 92 | # Misc settings 93 | misc { 94 | force_default_wallpaper = 0 # Set to 0 to disable the anime mascot wallpapers 95 | disable_hyprland_logo = true 96 | disable_splash_rendering = true 97 | vrr = 2 98 | } 99 | 100 | device { 101 | name = epic-mouse-v1 102 | sensitivity = -0.5 103 | } 104 | 105 | # Window rules 106 | # Center specific windows 107 | windowrule = center 1, class:^(.blueman-manager-wrapped)$ 108 | windowrule = center 1, class:^(gnome-calculator|org\.gnome\.Calculator)$ 109 | windowrule = center 1, class:^(nm-connection-editor)$ 110 | windowrule = center 1, class:^(org.pulseaudio.pavucontrol)$ 111 | windowrule = center 1, initialTitle:^(_crx_.*)$ # Centered Bitwarden extension 112 | 113 | # Float specific windows 114 | windowrule = float, class:^(.blueman-manager-wrapped)$ 115 | windowrule = float, class:^(gnome-calculator|org\.gnome\.Calculator)$ 116 | windowrule = float, class:^(nm-connection-editor)$ 117 | windowrule = float, class:^(org.pulseaudio.pavucontrol)$ 118 | windowrule = float, class:^(ulauncher)$ 119 | windowrule = float, title:^(MainPicker)$ 120 | windowrule = float, initialTitle:^(_crx_.*)$ # Float Bitwarden extension on Brave 121 | 122 | # Remove border for specific applications 123 | windowrule = noborder, class:^(ulauncher)$ 124 | windowrule = noborder, title:^(.*is sharing (your screen|a window)\.)$ # Screen share indicators 125 | 126 | # Set size for specific windows 127 | windowrule = size 50%, class:^(.blueman-manager-wrapped)$ 128 | windowrule = size 50%, class:^(nm-connection-editor)$ 129 | windowrule = size 50%, class:^(org.pulseaudio.pavucontrol)$ 130 | 131 | # Keep focus on specific windows when they open 132 | windowrule = stayfocused, class:^(.blueman-manager-wrapped)$ 133 | windowrule = stayfocused, class:^(gnome-calculator|org\.gnome\.Calculator)$ 134 | windowrule = stayfocused, class:^(org.pulseaudio.pavucontrol)$ 135 | windowrule = stayfocused, class:^(swappy)$ # Assuming class is 'swappy' 136 | windowrule = stayfocused, class:^(ulauncher)$ 137 | 138 | # Assign applications to specific workspaces 139 | windowrule = workspace 1, class:^(brave-browser)$ 140 | windowrule = workspace 2, class:^(Alacritty)$ 141 | windowrule = workspace 3, class:^(org\.telegram\.desktop)$ 142 | windowrule = workspace 4, class:^(com\.obsproject\.Studio)$ 143 | windowrule = workspace 4, class:^(steam)$ 144 | windowrule = workspace 5 silent, class:^(zoom)$ 145 | windowrule = workspace 6, class:^(steam_app_\d+)$ # Matches Steam game classes 146 | windowrule = workspace special, class:^(gnome-pomodoro)$ 147 | windowrule = workspace special silent, title:^(.*is sharing (your screen|a window)\.)$ # Screen share indicators to special workspace 148 | 149 | # Show applications on all workspaces (pin) 150 | windowrule = pin, title:^(as_toolbar)$ 151 | 152 | # Bindings 153 | $mainMod = SUPER 154 | 155 | bind = $mainMod SHIFT, Return, exec, alacritty 156 | bind = $mainMod SHIFT, B, exec, brave 157 | bind = $mainMod SHIFT, F, exec, nautilus 158 | bind = $mainMod SHIFT, T, exec, telegram-desktop 159 | bind = CTRL ALT, P, exec, gnome-pomodoro --start-stop 160 | bind = $mainMod, Return, layoutmsg, swapwithmaster 161 | bind = $mainMod, O, layoutmsg, orientationcycle 162 | bind = $mainMod, Q, killactive, 163 | bind = CTRL ALT, Q, exit 164 | bind = $mainMod, F, togglefloating 165 | bind = $mainMod, M, fullscreen 166 | bind = $mainMod SHIFT, M, movetoworkspacesilent, special 167 | bind = $mainMod SHIFT, P, togglespecialworkspace 168 | bind = $mainMod SHIFT, C, exec, hyprpicker -a 169 | 170 | # Move focus with mainMod + arrow keys 171 | bind = $mainMod, l, movefocus, l 172 | bind = $mainMod, h, movefocus, r 173 | bind = $mainMod, k, movefocus, u 174 | bind = $mainMod, j, movefocus, d 175 | 176 | # Resize windows 177 | bind = $mainMod SHIFT, left, resizeactive, -50 0 178 | bind = $mainMod SHIFT, right, resizeactive, 50 0 179 | bind = $mainMod SHIFT, up, resizeactive, 0 -50 180 | bind = $mainMod SHIFT, down, resizeactive, 0 50 181 | 182 | # Switch workspaces with mainMod + [0-9] 183 | bind = $mainMod, 1, workspace, 1 184 | bind = $mainMod, 2, workspace, 2 185 | bind = $mainMod, 3, workspace, 3 186 | bind = $mainMod, 4, workspace, 4 187 | bind = $mainMod, 5, workspace, 5 188 | bind = $mainMod, 6, workspace, 6 189 | bind = $mainMod, 7, workspace, 7 190 | bind = $mainMod, 8, workspace, 8 191 | bind = $mainMod, 9, workspace, 9 192 | bind = $mainMod, 0, workspace, 10 193 | 194 | # Move active window to a workspace with mainMod + SHIFT + [0-9] 195 | bind = $mainMod SHIFT, 1, movetoworkspace, 1 196 | bind = $mainMod SHIFT, 2, movetoworkspace, 2 197 | bind = $mainMod SHIFT, 3, movetoworkspace, 3 198 | bind = $mainMod SHIFT, 4, movetoworkspace, 4 199 | bind = $mainMod SHIFT, 5, movetoworkspace, 5 200 | bind = $mainMod SHIFT, 6, movetoworkspace, 6 201 | bind = $mainMod SHIFT, 7, movetoworkspace, 7 202 | bind = $mainMod SHIFT, 8, movetoworkspace, 8 203 | bind = $mainMod SHIFT, 9, movetoworkspace, 9 204 | bind = $mainMod SHIFT, 0, movetoworkspace, 10 205 | 206 | # Scroll through existing workspaces with mainMod + scroll 207 | bind = $mainMod, mouse_down, workspace, e+1 208 | bind = $mainMod, mouse_up, workspace, e-1 209 | 210 | # Move/resize windows with mainMod + LMB/RMB and dragging 211 | bindm = $mainMod, mouse:272, movewindow 212 | bindm = $mainMod, mouse:273, resizewindow 213 | 214 | # Application menu 215 | bind = $mainMod, A, exec, wofi --show drun --allow-images 216 | 217 | # Center focused window 218 | bind = CTRL ALT, C, centerwindow 219 | 220 | # Clipboard 221 | bind = ALT SHIFT, V, exec, cliphist list | wofi --show dmenu | cliphist decode | wl-copy 222 | 223 | # Ulauncher 224 | bind = CTRL, Space, exec, ulauncher-toggle 225 | 226 | # Screenshot area 227 | bind = $mainMod SHIFT, S, exec, $HOME/.local/bin/hyprshot --freeze --silent --raw --mode region | swappy -f - 228 | 229 | # Screenshot entire screen 230 | bind = $mainMod CTRL, S, exec, $HOME/.local/bin/hyprshot --freeze --silent --raw --mode output | swappy -f - 231 | 232 | # Screen recording 233 | bind = $mainMod SHIFT, R, exec, $HOME/.local/bin/screen-recorder 234 | 235 | # OCR 236 | bind = ALT SHIFT, 2, exec, $HOME/.local/bin/ocr 237 | 238 | # Lock screen 239 | bind = CTRL ALT, L, exec, hyprlock 240 | 241 | # Adjust brightness 242 | bind = , XF86MonBrightnessUp, exec, brightnessctl set +10% 243 | bind = , XF86MonBrightnessDown, exec, brightnessctl set 10%- 244 | 245 | # Open notifications 246 | bind = $mainMod, V, exec, swaync-client -t -sw 247 | 248 | # Adjust volume 249 | bind = , XF86AudioRaiseVolume, exec, pamixer --increase 10 250 | bind = , XF86AudioLowerVolume, exec, pamixer --decrease 10 251 | bind = , XF86AudioMute, exec, pamixer --toggle-mute 252 | bind = , XF86AudioMicMute, exec, pamixer --default-source --toggle-mute 253 | 254 | # Adjust mic sensitivity 255 | bind = SHIFT, XF86AudioRaiseVolume, exec, pamixer --increase 10 --default-source 256 | bind = SHIFT, XF86AudioLowerVolume, exec, pamixer --decrease 10 --default-source 257 | 258 | # Adjust keyboard backlight 259 | bind = SHIFT, XF86MonBrightnessUp, exec, brightnessctl -d tpacpi::kbd_backlight set +33% 260 | bind = SHIFT, XF86MonBrightnessDown, exec, brightnessctl -d tpacpi::kbd_backlight set 33%- 261 | -------------------------------------------------------------------------------- /modules/home-manager/misc/gtk/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | userConfig, 3 | pkgs, 4 | ... 5 | }: { 6 | # GTK theme configuration 7 | gtk = { 8 | enable = true; 9 | iconTheme = { 10 | name = "Tela-circle-dark"; 11 | package = pkgs.tela-circle-icon-theme; 12 | }; 13 | cursorTheme = { 14 | name = "Yaru"; 15 | package = pkgs.yaru-theme; 16 | size = 24; 17 | }; 18 | font = { 19 | name = "Roboto"; 20 | size = 11; 21 | }; 22 | gtk3 = { 23 | bookmarks = [ 24 | "file:///home/${userConfig.name}/Documents" 25 | "file:///home/${userConfig.name}/Downloads" 26 | "file:///home/${userConfig.name}/Pictures" 27 | "file:///home/${userConfig.name}/Videos" 28 | "file:///home/${userConfig.name}/Downloads/temp" 29 | "file:///home/${userConfig.name}/Documents/repositories" 30 | ]; 31 | }; 32 | }; 33 | 34 | # Enable catppuccin theming for GTK apps. 35 | catppuccin.gtk.enable = true; 36 | } 37 | -------------------------------------------------------------------------------- /modules/home-manager/misc/qt/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: { 6 | config = lib.mkIf (!pkgs.stdenv.isDarwin) { 7 | qt = { 8 | enable = true; 9 | platformTheme.name = "kvantum"; 10 | style.name = "kvantum"; 11 | }; 12 | 13 | catppuccin.kvantum.enable = true; 14 | catppuccin.kvantum.apply = true; 15 | 16 | home.sessionVariables = { 17 | # use wayland as the default backend, fallback to xcb if wayland is not available 18 | QT_QPA_PLATFORM = "wayland;xcb"; 19 | 20 | # remain backwards compatible with qt5 21 | DISABLE_QT5_COMPAT = "0"; 22 | 23 | # tell calibre to use the dark theme 24 | CALIBRE_USE_DARK_PALETTE = "1"; 25 | }; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /modules/home-manager/misc/wallpaper/default.nix: -------------------------------------------------------------------------------- 1 | {lib, ...}: { 2 | options.wallpaper = lib.mkOption { 3 | type = lib.types.path; 4 | default = ./wallpaper.jpg; 5 | readOnly = true; 6 | description = "Path to default wallpaper"; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /modules/home-manager/misc/wallpaper/wallpaper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/modules/home-manager/misc/wallpaper/wallpaper.jpg -------------------------------------------------------------------------------- /modules/home-manager/misc/xdg/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | xdg = { 3 | enable = true; 4 | mimeApps = { 5 | enable = true; 6 | associations.added = { 7 | "audio/mpeg" = ["org.gnome.Totem.desktop"]; 8 | "image/jpeg" = ["org.gnome.Loupe.desktop"]; 9 | "image/jpg" = ["org.gnome.Loupe.desktop"]; 10 | "image/png" = ["org.gnome.Loupe.desktop"]; 11 | "video/mp3" = ["org.gnome.Totem.desktop"]; 12 | "video/mp4" = ["org.gnome.Totem.desktop"]; 13 | "video/quicktime" = ["org.gnome.Totem.desktop"]; 14 | "video/webm" = ["org.gnome.Totem.desktop"]; 15 | }; 16 | defaultApplications = { 17 | "application/json" = ["gnome-text-editor.desktop"]; 18 | "application/toml" = "org.gnome.TextEditor.desktop"; 19 | "application/x-gnome-saved-search" = ["org.gnome.Nautilus.desktop"]; 20 | "audio/*" = ["org.gnome.Totem.desktop"]; 21 | "audio/mp3" = ["org.gnome.Totem.desktop"]; 22 | "image/*" = ["org.gnome.Loupe.desktop"]; 23 | "image/jpg" = ["org.gnome.Loupe.desktop"]; 24 | "image/png" = ["org.gnome.Loupe.desktop"]; 25 | "text/plain" = "org.gnome.TextEditor.desktop"; 26 | "video/*" = ["org.gnome.Totem.desktop"]; 27 | "video/mp4" = ["org.gnome.Totem.desktop"]; 28 | }; 29 | }; 30 | userDirs = { 31 | enable = true; 32 | createDirectories = true; 33 | }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/home-manager/programs/aerospace/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: { 6 | config = lib.mkIf (pkgs.stdenv.isDarwin) { 7 | # Ensure aerospace package installed 8 | home.packages = with pkgs; [ 9 | aerospace 10 | ]; 11 | 12 | # Source aerospace config from the home-manager store 13 | home.file.".aerospace.toml".text = '' 14 | # Start AeroSpace at login 15 | start-at-login = true 16 | 17 | # Normalization settings 18 | enable-normalization-flatten-containers = true 19 | enable-normalization-opposite-orientation-for-nested-containers = true 20 | 21 | # Accordion layout settings 22 | accordion-padding = 30 23 | 24 | # Default root container settings 25 | default-root-container-layout = 'tiles' 26 | default-root-container-orientation = 'auto' 27 | 28 | # Mouse follows focus settings 29 | on-focused-monitor-changed = ['move-mouse monitor-lazy-center'] 30 | on-focus-changed = ['move-mouse window-lazy-center'] 31 | 32 | # Automatically unhide macOS hidden apps 33 | automatically-unhide-macos-hidden-apps = true 34 | 35 | # Key mapping preset 36 | [key-mapping] 37 | preset = 'qwerty' 38 | 39 | # Gaps settings 40 | [gaps] 41 | inner.horizontal = 6 42 | inner.vertical = 6 43 | outer.left = 6 44 | outer.bottom = 6 45 | outer.top = 6 46 | outer.right = 6 47 | 48 | # Main mode bindings 49 | [mode.main.binding] 50 | # Launch applications 51 | alt-shift-enter = 'exec-and-forget open -na alacritty' 52 | alt-shift-b = 'exec-and-forget open -a "Brave Browser"' 53 | alt-shift-t = 'exec-and-forget open -a "Telegram"' 54 | alt-shift-f = 'exec-and-forget open -a Finder' 55 | 56 | # Window management 57 | alt-q = "close" 58 | alt-slash = 'layout tiles horizontal vertical' 59 | alt-comma = 'layout accordion horizontal vertical' 60 | alt-m = 'fullscreen' 61 | 62 | # Focus movement 63 | alt-h = 'focus left' 64 | alt-j = 'focus down' 65 | alt-k = 'focus up' 66 | alt-l = 'focus right' 67 | 68 | # Window movement 69 | alt-shift-h = 'move left' 70 | alt-shift-j = 'move down' 71 | alt-shift-k = 'move up' 72 | alt-shift-l = 'move right' 73 | 74 | # Resize windows 75 | alt-shift-minus = 'resize smart -50' 76 | alt-shift-equal = 'resize smart +50' 77 | 78 | # Workspace management 79 | alt-1 = 'workspace 1' 80 | alt-2 = 'workspace 2' 81 | alt-3 = 'workspace 3' 82 | alt-4 = 'workspace 4' 83 | alt-5 = 'workspace 5' 84 | alt-6 = 'workspace 6' 85 | alt-7 = 'workspace 7' 86 | alt-8 = 'workspace 8' 87 | alt-9 = 'workspace 9' 88 | 89 | # Move windows to workspaces 90 | alt-shift-1 = 'move-node-to-workspace 1' 91 | alt-shift-2 = 'move-node-to-workspace 2' 92 | alt-shift-3 = 'move-node-to-workspace 3' 93 | alt-shift-4 = 'move-node-to-workspace 4' 94 | alt-shift-5 = 'move-node-to-workspace 5' 95 | alt-shift-6 = 'move-node-to-workspace 6' 96 | alt-shift-7 = 'move-node-to-workspace 7' 97 | alt-shift-8 = 'move-node-to-workspace 8' 98 | alt-shift-9 = 'move-node-to-workspace 9' 99 | 100 | # Workspace navigation 101 | alt-tab = 'workspace-back-and-forth' 102 | alt-shift-tab = 'move-workspace-to-monitor --wrap-around next' 103 | 104 | # Enter service mode 105 | alt-shift-semicolon = 'mode service' 106 | 107 | # Service mode bindings 108 | [mode.service.binding] 109 | # Reload config and exit service mode 110 | esc = ['reload-config', 'mode main'] 111 | 112 | # Reset layout 113 | r = ['flatten-workspace-tree', 'mode main'] 114 | 115 | # Toggle floating/tiling layout 116 | f = ['layout floating tiling', 'mode main'] 117 | 118 | # Close all windows but current 119 | backspace = ['close-all-windows-but-current', 'mode main'] 120 | 121 | # Join with adjacent windows 122 | alt-shift-h = ['join-with left', 'mode main'] 123 | alt-shift-j = ['join-with down', 'mode main'] 124 | alt-shift-k = ['join-with up', 'mode main'] 125 | alt-shift-l = ['join-with right', 'mode main'] 126 | 127 | # Window detection rules 128 | [[on-window-detected]] 129 | if.app-id = 'com.brave.Browser' 130 | run = 'move-node-to-workspace 1' 131 | 132 | [[on-window-detected]] 133 | if.app-id = 'org.alacritty' 134 | run = 'move-node-to-workspace 2' 135 | 136 | [[on-window-detected]] 137 | if.app-id = 'com.tdesktop.Telegram' 138 | run = 'move-node-to-workspace 3' 139 | 140 | [[on-window-detected]] 141 | if.app-id = 'com.obsproject.obs-studio' 142 | run = 'move-node-to-workspace 4' 143 | 144 | [[on-window-detected]] 145 | if.app-id = 'us.zoom.xos' 146 | run = 'move-node-to-workspace 5' 147 | ''; 148 | }; 149 | } 150 | -------------------------------------------------------------------------------- /modules/home-manager/programs/alacritty/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | # Install alacritty via home-manager module 3 | programs.alacritty = { 4 | enable = true; 5 | settings = { 6 | general = { 7 | live_config_reload = true; 8 | }; 9 | 10 | terminal = { 11 | shell.program = "zsh"; 12 | shell.args = [ 13 | "-l" 14 | "-c" 15 | "tmux attach || tmux " 16 | ]; 17 | }; 18 | 19 | env = { 20 | TERM = "xterm-256color"; 21 | }; 22 | 23 | window = { 24 | decorations = 25 | if pkgs.stdenv.isDarwin 26 | then "buttonless" 27 | else "none"; 28 | dynamic_title = false; 29 | dynamic_padding = true; 30 | dimensions = { 31 | columns = 170; 32 | lines = 45; 33 | }; 34 | padding = { 35 | x = 5; 36 | y = 1; 37 | }; 38 | }; 39 | 40 | scrolling = { 41 | history = 10000; 42 | multiplier = 3; 43 | }; 44 | 45 | font = { 46 | size = 47 | if pkgs.stdenv.isDarwin 48 | then 15 49 | else 12; 50 | normal = { 51 | family = "MesloLGS Nerd Font"; 52 | style = "Regular"; 53 | }; 54 | bold = { 55 | family = "MesloLGS Nerd Font"; 56 | style = "Bold"; 57 | }; 58 | italic = { 59 | family = "MesloLGS Nerd Font"; 60 | style = "Italic"; 61 | }; 62 | bold_italic = { 63 | family = "MesloLGS Nerd Font"; 64 | style = "Italic"; 65 | }; 66 | }; 67 | 68 | selection = { 69 | semantic_escape_chars = '',│`|:"' ()[]{}<>''; 70 | save_to_clipboard = true; 71 | }; 72 | }; 73 | }; 74 | 75 | # Enable catppuccin theming for alacritty. 76 | catppuccin.alacritty.enable = true; 77 | } 78 | -------------------------------------------------------------------------------- /modules/home-manager/programs/atuin/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install atuin via home-manager module 3 | programs.atuin = { 4 | enable = true; 5 | settings = { 6 | inline_height = 25; 7 | invert = true; 8 | records = true; 9 | search_mode = "skim"; 10 | secrets_filter = true; 11 | style = "compact"; 12 | }; 13 | flags = ["--disable-up-arrow"]; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /modules/home-manager/programs/bat/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install bat via home-manager module 3 | programs.bat = { 4 | enable = true; 5 | }; 6 | 7 | # Enable catppuccin theming for bat. 8 | catppuccin.bat.enable = true; 9 | } 10 | -------------------------------------------------------------------------------- /modules/home-manager/programs/bottom/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install bottom via home-manager module 3 | programs.bottom = { 4 | enable = true; 5 | settings = { 6 | flags = { 7 | avg_cpu = true; 8 | temperature_type = "c"; 9 | }; 10 | 11 | colors = { 12 | low_battery_color = "red"; 13 | }; 14 | }; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /modules/home-manager/programs/brave/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: { 6 | # Ensure Brave browser package installed 7 | home.packages = with pkgs; [ 8 | brave 9 | ]; 10 | 11 | # Apply XDG configuration only on non-Darwin platforms 12 | xdg = lib.mkIf (!pkgs.stdenv.isDarwin) { 13 | mimeApps = { 14 | defaultApplications = { 15 | "application/x-extension-htm" = "brave-browser.desktop"; 16 | "application/x-extension-html" = "brave-browser.desktop"; 17 | "application/x-extension-shtml" = "brave-browser.desktop"; 18 | "application/x-extension-xht" = "brave-browser.desktop"; 19 | "application/x-extension-xhtml" = "brave-browser.desktop"; 20 | "application/xhtml+xml" = "brave-browser.desktop"; 21 | "text/html" = "brave-browser.desktop"; 22 | "x-scheme-handler/about" = "brave-browser.desktop"; 23 | "x-scheme-handler/chrome" = ["chromium-browser.desktop"]; 24 | "x-scheme-handler/ftp" = "brave-browser.desktop"; 25 | "x-scheme-handler/http" = "brave-browser.desktop"; 26 | "x-scheme-handler/https" = "brave-browser.desktop"; 27 | "x-scheme-handler/unknown" = "brave-browser.desktop"; 28 | "application/pdf" = "brave-browser.desktop"; 29 | }; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/home-manager/programs/btop/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install btop via home-manager module 3 | programs.btop = { 4 | enable = true; 5 | settings = { 6 | vim_keys = true; 7 | }; 8 | }; 9 | 10 | # Enable catppuccin theming for btop. 11 | catppuccin.btop.enable = true; 12 | } 13 | -------------------------------------------------------------------------------- /modules/home-manager/programs/fastfetch/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install and configure fastfetch via home-manager module 3 | programs.fastfetch = { 4 | enable = true; 5 | settings = { 6 | logo = { 7 | type = "none"; 8 | }; 9 | display = { 10 | separator = "-> "; 11 | }; 12 | modules = [ 13 | { 14 | type = "title"; 15 | format = "{6}{7}{8}"; 16 | } 17 | "break" 18 | { 19 | type = "custom"; 20 | format = "┌───────────────────────────── System Information ─────────────────────────────┐"; 21 | } 22 | "break" 23 | { 24 | key = "  OS "; 25 | keyColor = "red"; 26 | type = "os"; 27 | } 28 | { 29 | key = " 󰌢 Machine "; 30 | keyColor = "green"; 31 | type = "host"; 32 | } 33 | { 34 | key = "  Kernel "; 35 | keyColor = "magenta"; 36 | type = "kernel"; 37 | } 38 | { 39 | key = " 󰏖 Packages "; 40 | type = "packages"; 41 | } 42 | { 43 | key = " 󰅐 Uptime "; 44 | keyColor = "red"; 45 | type = "uptime"; 46 | } 47 | { 48 | key = " 󰍹 Resolution "; 49 | keyColor = "yellow"; 50 | type = "display"; 51 | compactType = "original-with-refresh-rate"; 52 | } 53 | { 54 | key = "  WM "; 55 | keyColor = "blue"; 56 | type = "wm"; 57 | } 58 | { 59 | key = "  DE "; 60 | keyColor = "green"; 61 | type = "de"; 62 | } 63 | { 64 | key = "  Shell "; 65 | keyColor = "cyan"; 66 | type = "shell"; 67 | } 68 | { 69 | key = "  Terminal "; 70 | keyColor = "red"; 71 | type = "terminal"; 72 | } 73 | { 74 | key = " 󰻠 CPU "; 75 | keyColor = "yellow"; 76 | type = "cpu"; 77 | } 78 | { 79 | key = " 󰍛 GPU "; 80 | keyColor = "blue"; 81 | type = "gpu"; 82 | } 83 | { 84 | key = " 󰑭 Memory "; 85 | keyColor = "magenta"; 86 | type = "memory"; 87 | } 88 | { 89 | key = " 󰩟 Local IP "; 90 | keyColor = "red"; 91 | type = "localip"; 92 | } 93 | { 94 | key = " 󰩠 Public IP "; 95 | keyColor = "cyan"; 96 | type = "publicip"; 97 | } 98 | "break" 99 | { 100 | type = "custom"; 101 | format = "└──────────────────────────────────────────────────────────────────────────────┘"; 102 | } 103 | "break" 104 | { 105 | paddingLeft = 34; 106 | symbol = "circle"; 107 | type = "colors"; 108 | } 109 | ]; 110 | }; 111 | }; 112 | } 113 | -------------------------------------------------------------------------------- /modules/home-manager/programs/fzf/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: let 2 | copyCmd = 3 | if pkgs.stdenv.isDarwin 4 | then "pbcopy" 5 | else "wl-copy"; 6 | in { 7 | # Install fzf via home-manager module 8 | programs.fzf = { 9 | enable = true; 10 | 11 | defaultCommand = "find ."; 12 | defaultOptions = [ 13 | "--bind '?:toggle-preview'" 14 | "--bind 'ctrl-a:select-all'" 15 | "--bind 'ctrl-e:execute(echo {+} | xargs -o nvim)'" 16 | "--bind 'ctrl-y:execute-silent(echo {+} | ${copyCmd})'" 17 | "--color='hl:148,hl+:154,pointer:032,marker:010,bg+:237,gutter:008'" 18 | "--height=40%" 19 | "--info=inline" 20 | "--layout=reverse" 21 | "--multi" 22 | "--preview '([[ -f {} ]] && (bat --color=always --style=numbers,changes {} || cat {})) || ([[ -d {} ]] && (tree -C {} | less)) || echo {} 2> /dev/null | head -200'" 23 | "--preview-window=:hidden" 24 | "--prompt='~ ' --pointer='▶' --marker='✓'" 25 | ]; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /modules/home-manager/programs/git/default.nix: -------------------------------------------------------------------------------- 1 | {userConfig, ...}: { 2 | # Install git via home-manager module 3 | programs.git = { 4 | enable = true; 5 | userName = userConfig.fullName; 6 | userEmail = userConfig.email; 7 | signing = { 8 | key = userConfig.gitKey; 9 | signByDefault = true; 10 | }; 11 | delta = { 12 | enable = true; 13 | options = { 14 | keep-plus-minus-markers = true; 15 | light = false; 16 | line-numbers = true; 17 | navigate = true; 18 | width = 280; 19 | }; 20 | }; 21 | extraConfig = { 22 | pull.rebase = "true"; 23 | }; 24 | }; 25 | 26 | # Enable catppuccin theming for git delta 27 | catppuccin.delta.enable = true; 28 | } 29 | -------------------------------------------------------------------------------- /modules/home-manager/programs/go/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install and configure Golang via home-manager module 3 | programs.go = { 4 | enable = true; 5 | goBin = "go/bin"; 6 | goPath = "go"; 7 | }; 8 | 9 | # Ensure Go bin in the PATH 10 | home.sessionPath = [ 11 | "$HOME/go/bin" 12 | ]; 13 | } 14 | -------------------------------------------------------------------------------- /modules/home-manager/programs/gpg/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: { 6 | # Install gpg via home-manager module 7 | programs.gpg = { 8 | enable = true; 9 | settings = { 10 | personal-cipher-preferences = "AES256"; 11 | personal-digest-preferences = "SHA512"; 12 | personal-compress-preferences = "ZLIB BZIP2 ZIP Uncompressed"; 13 | default-preference-list = "SHA512 AES256 ZLIB BZIP2 ZIP Uncompressed"; 14 | cert-digest-algo = "SHA512"; 15 | s2k-digest-algo = "SHA512"; 16 | s2k-cipher-algo = "AES256"; 17 | charset = "utf-8"; 18 | fixed-list-mode = true; 19 | no-comments = true; 20 | no-emit-version = true; 21 | no-greeting = true; 22 | keyid-format = "0xlong"; 23 | list-options = "show-uid-validity"; 24 | verify-options = "show-uid-validity"; 25 | with-key-origin = true; 26 | require-cross-certification = true; 27 | no-symkey-cache = true; 28 | use-agent = true; 29 | throw-keyids = true; 30 | }; 31 | }; 32 | 33 | services.gpg-agent = lib.mkIf (!pkgs.stdenv.isDarwin) { 34 | enable = true; 35 | defaultCacheTtl = 86400; 36 | enableSshSupport = true; 37 | pinentry.package = pkgs.pinentry-gnome3; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /modules/home-manager/programs/k9s/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install k9s via home-manager module 3 | programs.k9s = { 4 | enable = true; 5 | settings.k9s = { 6 | ui = { 7 | headless = true; 8 | logoless = true; 9 | }; 10 | }; 11 | hotkey.hotKeys = { 12 | shift-1 = { 13 | shortCut = "Shift-1"; 14 | description = "Show pods"; 15 | command = "pods"; 16 | }; 17 | shift-2 = { 18 | shortCut = "Shift-2"; 19 | description = "Show deployments"; 20 | command = "dp"; 21 | }; 22 | shift-3 = { 23 | shortCut = "Shift-3"; 24 | description = "Show nodes"; 25 | command = "nodes"; 26 | }; 27 | shift-4 = { 28 | shortCut = "Shift-4"; 29 | description = "Show services"; 30 | command = "services"; 31 | }; 32 | shift-5 = { 33 | shortCut = "Shift-5"; 34 | description = "Show Ingress"; 35 | command = "ingress"; 36 | }; 37 | shift-6 = { 38 | shortCut = "Shift-6"; 39 | description = "Show Pulses"; 40 | command = "pulses"; 41 | }; 42 | shift-7 = { 43 | shortCut = "Shift-7"; 44 | description = "Show Events"; 45 | command = "events"; 46 | }; 47 | }; 48 | }; 49 | 50 | # Enable catppuccin theming for k9s 51 | catppuccin.k9s.enable = true; 52 | } 53 | -------------------------------------------------------------------------------- /modules/home-manager/programs/krew/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: let 6 | krewPkgs = [ 7 | "ctx" 8 | "ns" 9 | ]; 10 | 11 | # Convert the list of plugins into a space-separated string 12 | krewPkgStr = lib.concatStringsSep " " krewPkgs; 13 | in { 14 | # Ensure krew package installed 15 | home.packages = with pkgs; [ 16 | krew 17 | ]; 18 | 19 | # Ensure krew is in the PATH 20 | home.sessionPath = [ 21 | "$HOME/.krew/bin" 22 | ]; 23 | 24 | # Install krew plugins 25 | home.activation.krew = lib.hm.dag.entryAfter ["writeBoundary"] '' 26 | export PATH="$HOME/.krew/bin:${pkgs.git}/bin:/usr/bin:$PATH"; 27 | 28 | if [ -z "$(${pkgs.krew}/bin/krew list)" ]; then 29 | ${pkgs.krew}/bin/krew install ${krewPkgStr} 30 | else 31 | ${pkgs.krew}/bin/krew upgrade 32 | fi 33 | ''; 34 | } 35 | -------------------------------------------------------------------------------- /modules/home-manager/programs/lazygit/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install lazygit via home-manager module 3 | programs.lazygit = { 4 | enable = true; 5 | 6 | settings = { 7 | git = { 8 | paging = { 9 | colorArg = "always"; 10 | pager = "delta --color-only --dark --paging=never"; 11 | }; 12 | }; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | # Neovim text editor configuration 3 | programs.neovim = { 4 | enable = true; 5 | package = pkgs.neovim-unwrapped; 6 | defaultEditor = true; 7 | withNodeJs = true; 8 | withPython3 = true; 9 | withRuby = true; 10 | 11 | extraPackages = with pkgs; [ 12 | alejandra 13 | black 14 | golangci-lint 15 | gopls 16 | gotools 17 | hadolint 18 | isort 19 | lua-language-server 20 | markdownlint-cli 21 | nixd 22 | nodePackages.bash-language-server 23 | nodePackages.prettier 24 | pyright 25 | ruff 26 | shellcheck 27 | shfmt 28 | stylua 29 | terraform-ls 30 | tflint 31 | vscode-langservers-extracted 32 | yaml-language-server 33 | ]; 34 | }; 35 | 36 | # source lua config from this repo 37 | xdg.configFile = { 38 | "nvim" = { 39 | source = ./lazyvim; 40 | recursive = true; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/.luarc.json: -------------------------------------------------------------------------------- 1 | { 2 | "diagnostics.globals": [ 3 | "yaml_language_server", 4 | "tflint", 5 | "terraform_ls", 6 | "stylua", 7 | "shfmt", 8 | "pyright", 9 | "prittier", 10 | "markdownlint", 11 | "lua_language_server", 12 | "json_lsp", 13 | "isort", 14 | "hadolint", 15 | "golangci_lint", 16 | "goimports", 17 | "black", 18 | "bash_language_server", 19 | "on_attach" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/.neoconf.json: -------------------------------------------------------------------------------- 1 | { 2 | "neodev": { 3 | "library": { 4 | "enabled": true, 5 | "plugins": true 6 | } 7 | }, 8 | "neoconf": { 9 | "plugins": { 10 | "lua_ls": { 11 | "enabled": true 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/init.lua: -------------------------------------------------------------------------------- 1 | -- bootstrap lazy.nvim, LazyVim and your plugins 2 | require("config.lazy") 3 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/config/autocmds.lua: -------------------------------------------------------------------------------- 1 | -- Autocmds are automatically loaded on the VeryLazy event 2 | -- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua 3 | -- Add any additional autocmds here 4 | vim.filetype.add({ 5 | pattern = { 6 | [".*/chart/*/templates/.{yaml,tpl}"] = "helm", 7 | }, 8 | }) 9 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/config/keymaps.lua: -------------------------------------------------------------------------------- 1 | -- Keymaps are automatically loaded on the VeryLazy event 2 | -- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua 3 | -- Add any additional keymaps here 4 | 5 | vim.keymap.set("v", "p", '"_dP', { desc = "Paste without overwriting the default register" }) 6 | vim.keymap.set("n", "dt", "diffthis", { desc = "Diff This" }) 7 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/config/lazy.lua: -------------------------------------------------------------------------------- 1 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 2 | if not (vim.uv or vim.loop).fs_stat(lazypath) then 3 | local lazyrepo = "https://github.com/folke/lazy.nvim.git" 4 | local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) 5 | if vim.v.shell_error ~= 0 then 6 | vim.api.nvim_echo({ 7 | { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, 8 | { out, "WarningMsg" }, 9 | { "\nPress any key to exit..." }, 10 | }, true, {}) 11 | vim.fn.getchar() 12 | os.exit(1) 13 | end 14 | end 15 | vim.opt.rtp:prepend(lazypath) 16 | 17 | require("lazy").setup({ 18 | spec = { 19 | { "LazyVim/LazyVim", import = "lazyvim.plugins" }, 20 | { import = "lazyvim.plugins.extras.lsp.none-ls" }, 21 | { import = "plugins" }, 22 | }, 23 | defaults = { 24 | lazy = false, 25 | version = false, -- always use the latest git commit 26 | }, 27 | install = { colorscheme = { "tokyonight", "habamax" } }, 28 | checker = { 29 | enabled = false, 30 | notify = false, 31 | }, 32 | performance = { 33 | rtp = { 34 | disabled_plugins = { 35 | "gzip", 36 | "tarPlugin", 37 | "tohtml", 38 | "tutor", 39 | "zipPlugin", 40 | }, 41 | }, 42 | }, 43 | }) 44 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/config/options.lua: -------------------------------------------------------------------------------- 1 | -- Options are automatically loaded before lazy.nvim startup 2 | -- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua 3 | -- Add any additional options here 4 | vim.opt.winbar = "%=%m %f" 5 | vim.g.lazygit_config = false 6 | vim.g.snacks_animate = false 7 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/catppucin.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "LazyVim/LazyVim", 4 | opts = { 5 | colorscheme = "catppuccin-macchiato", 6 | }, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/helm-ls.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { "towolf/vim-helm", ft = "helm" }, 3 | } 4 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/lsp.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "neovim/nvim-lspconfig", 4 | opts = { 5 | servers = { 6 | bashls = {}, 7 | gopls = { 8 | settings = { 9 | gopls = { 10 | semanticTokens = true, 11 | analyses = { 12 | unusedparams = true, 13 | }, 14 | staticcheck = true, 15 | hints = { 16 | assignVariableTypes = false, 17 | compositeLiteralFields = false, 18 | compositeLiteralTypes = false, 19 | constantValues = false, 20 | functionTypeParameters = false, 21 | parameterNames = false, 22 | rangeVariableTypes = false, 23 | }, 24 | }, 25 | }, 26 | }, 27 | jsonls = {}, 28 | lua_ls = { 29 | settings = { 30 | Lua = { 31 | workspace = { 32 | checkThirdParty = false, 33 | }, 34 | completion = { 35 | callSnippet = "Replace", 36 | }, 37 | }, 38 | }, 39 | }, 40 | nixd = {}, 41 | pyright = { 42 | settings = { 43 | python = { 44 | analysis = { 45 | autoSearchPaths = true, 46 | useLibraryCodeForTypes = true, 47 | typeCheckingMode = "basic", 48 | diagnosticMode = "openFilesOnly", 49 | }, 50 | }, 51 | }, 52 | }, 53 | ruff = {}, 54 | terraformls = {}, 55 | tflint = {}, 56 | yamlls = { 57 | settings = { 58 | yaml = { 59 | keyOrdering = false, 60 | }, 61 | }, 62 | }, 63 | }, 64 | }, 65 | }, 66 | } 67 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/mason.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "williamboman/mason.nvim", 4 | -- Disable Mason in favor of Nix packages 5 | enabled = false, 6 | opts = function(_, opts) 7 | vim.list_extend(opts.ensure_installed, { 8 | "bash-language-server", 9 | "black", 10 | "goimports", 11 | "golangci-lint", 12 | "hadolint", 13 | "isort", 14 | "json-lsp", 15 | "lua-language-server", 16 | "markdownlint", 17 | "prettier", 18 | "pyright", 19 | "shfmt", 20 | "stylua", 21 | "terraform-ls", 22 | "tflint", 23 | "yaml-language-server", 24 | }) 25 | end, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/neo-tree.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-neo-tree/neo-tree.nvim", 3 | opts = { 4 | filesystem = { 5 | filtered_items = { 6 | visible = true, 7 | hide_dotfiles = false, 8 | hide_gitignored = false, 9 | }, 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/none-ls.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvimtools/none-ls.nvim", 3 | opts = function() 4 | local nls = require("null-ls") 5 | return { 6 | root_dir = require("null-ls.utils").root_pattern(".null-ls-root", ".neoconf.json", "Makefile", ".git"), 7 | sources = { 8 | -- code actions 9 | -- formatters 10 | nls.builtins.formatting.alejandra, 11 | nls.builtins.formatting.black.with({ 12 | extra_args = { "--line-length", "120" }, 13 | }), 14 | nls.builtins.formatting.prettier.with({ 15 | filetypes = { 16 | "css", 17 | "markdown", 18 | "yaml.docker-compose", 19 | "yaml.kubernetes", 20 | "yaml", 21 | }, 22 | }), 23 | nls.builtins.formatting.goimports, 24 | nls.builtins.formatting.isort, 25 | nls.builtins.formatting.markdownlint, 26 | nls.builtins.formatting.shfmt, 27 | nls.builtins.formatting.stylua, 28 | nls.builtins.formatting.terraform_fmt, 29 | -- linters 30 | nls.builtins.diagnostics.golangci_lint, 31 | nls.builtins.diagnostics.hadolint, 32 | nls.builtins.diagnostics.markdownlint.with({ extra_args = { "--disable", "MD013" } }), 33 | }, 34 | on_attach = function(client, bufnr) 35 | -- Disable diagnostics for non-file buffers (like terminals) 36 | if vim.bo[bufnr].buftype ~= "" then 37 | vim.diagnostic.enable(false, bufnr) 38 | end 39 | end, 40 | } 41 | end, 42 | } 43 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/tmux-navigator.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "christoomey/vim-tmux-navigator", 4 | cmd = { 5 | "TmuxNavigateLeft", 6 | "TmuxNavigateDown", 7 | "TmuxNavigateUp", 8 | "TmuxNavigateRight", 9 | "TmuxNavigatePrevious", 10 | }, 11 | keys = { 12 | { "", "TmuxNavigateLeft" }, 13 | { "", "TmuxNavigateDown" }, 14 | { "", "TmuxNavigateUp" }, 15 | { "", "TmuxNavigateRight" }, 16 | { "", "TmuxNavigatePrevious" }, 17 | }, 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/lua/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-treesitter/nvim-treesitter", 3 | opts = { 4 | highlight = { 5 | enable = true, 6 | }, 7 | rainbow = { 8 | enable = true, 9 | extended_mode = true, 10 | max_file_lines = 1000, 11 | }, 12 | indent = { 13 | enable = true, 14 | }, 15 | ensure_installed = { 16 | "bash", 17 | "c", 18 | "dockerfile", 19 | "go", 20 | "hcl", 21 | "helm", 22 | "json", 23 | "jsonc", 24 | "lua", 25 | "luadoc", 26 | "luap", 27 | "make", 28 | "markdown", 29 | "markdown_inline", 30 | "nix", 31 | "python", 32 | "regex", 33 | "terraform", 34 | "vim", 35 | "vimdoc", 36 | "yaml", 37 | }, 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /modules/home-manager/programs/neovim/lazyvim/stylua.toml: -------------------------------------------------------------------------------- 1 | indent_type = "Spaces" 2 | indent_width = 2 3 | column_width = 120 -------------------------------------------------------------------------------- /modules/home-manager/programs/obs-studio/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: { 6 | config = lib.mkIf (!pkgs.stdenv.isDarwin) { 7 | # Install OBS Studio via home-manager module 8 | programs.obs-studio.enable = true; 9 | 10 | # Enable catppuccin theming for OBS. 11 | catppuccin.obs.enable = true; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /modules/home-manager/programs/saml2aws/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | # Ensure saml2aws package installed 3 | home.packages = with pkgs; [ 4 | saml2aws 5 | ]; 6 | 7 | # Set session duration via env vars 8 | home.sessionVariables = { 9 | AWS_REGION = "eu-west-1"; 10 | SAML2AWS_SESSION_DURATION = "3600"; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /modules/home-manager/programs/starship/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Starship configuration 3 | programs.starship = { 4 | enable = true; 5 | enableZshIntegration = true; 6 | settings = { 7 | add_newline = false; 8 | directory = { 9 | style = "bold lavender"; 10 | }; 11 | aws = { 12 | disabled = true; 13 | }; 14 | docker_context = { 15 | symbol = " "; 16 | }; 17 | golang = { 18 | symbol = " "; 19 | }; 20 | kubernetes = { 21 | disabled = false; 22 | style = "bold pink"; 23 | symbol = "󱃾 "; 24 | format = "[$symbol$context( \($namespace\))]($style)"; 25 | contexts = [ 26 | { 27 | context_pattern = "arn:aws:eks:(?P.*):(?P[0-9]{12}):cluster/(?P.*)"; 28 | context_alias = "$var_cluster"; 29 | } 30 | ]; 31 | }; 32 | helm = { 33 | symbol = " "; 34 | }; 35 | gradle = { 36 | symbol = " "; 37 | }; 38 | java = { 39 | symbol = " "; 40 | }; 41 | kotlin = { 42 | symbol = " "; 43 | }; 44 | lua = { 45 | symbol = " "; 46 | }; 47 | package = { 48 | symbol = " "; 49 | }; 50 | php = { 51 | symbol = " "; 52 | }; 53 | python = { 54 | symbol = " "; 55 | }; 56 | rust = { 57 | symbol = " "; 58 | }; 59 | terraform = { 60 | symbol = " "; 61 | }; 62 | right_format = "$kubernetes"; 63 | }; 64 | }; 65 | 66 | # Enable catppuccin theming for starship. 67 | catppuccin.starship.enable = true; 68 | } 69 | -------------------------------------------------------------------------------- /modules/home-manager/programs/swappy/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | # Ensure swappy package installed 3 | home.packages = with pkgs; [ 4 | swappy 5 | ]; 6 | 7 | # Source swappy config from the home-manager store 8 | xdg.configFile = { 9 | "swappy/config".text = '' 10 | [Default] 11 | save_dir=$HOME/Pictures 12 | save_filename_format=screenshot-%Y%m%d-%H%M%S.png 13 | ''; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /modules/home-manager/programs/telegram/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: { 6 | # Ensure Telegram desktop package installed 7 | home.packages = with pkgs; [ 8 | telegram-desktop 9 | ]; 10 | 11 | # XDG configuration (only on non-Darwin platforms) 12 | xdg = lib.mkIf (!pkgs.stdenv.isDarwin) { 13 | mimeApps = { 14 | associations.added = { 15 | "x-scheme-handler/tg" = ["org.telegram.desktop.desktop"]; 16 | "x-scheme-handler/tonsite" = ["org.telegram.desktop.desktop"]; 17 | }; 18 | defaultApplications = { 19 | "x-scheme-handler/tg" = ["org.telegram.desktop.desktop"]; 20 | "x-scheme-handler/tonsite" = ["org.telegram.desktop.desktop"]; 21 | }; 22 | }; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /modules/home-manager/programs/tmux/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Tmux terminal multiplexer configuration 3 | programs.tmux = { 4 | enable = true; 5 | baseIndex = 1; 6 | escapeTime = 10; 7 | historyLimit = 10000; 8 | keyMode = "vi"; 9 | mouse = true; 10 | sensibleOnTop = false; 11 | terminal = "screen-256color"; 12 | 13 | extraConfig = '' 14 | # Set the prefix to `ctrl + q` instead of `ctrl + b` 15 | set -g prefix C-q 16 | unbind C-b 17 | 18 | # Use | and - to split a window vertically and horizontally instead of " and % respoectively 19 | unbind '"' 20 | unbind % 21 | bind v split-window -h -c "#{pane_current_path}" 22 | bind s split-window -v -c "#{pane_current_path}" 23 | 24 | # Bind Arrow keys to resize the window 25 | bind -n S-Down resize-pane -D 8 26 | bind -n S-Up resize-pane -U 8 27 | bind -n S-Left resize-pane -L 8 28 | bind -n S-Right resize-pane -R 8 29 | 30 | # Rename window with prefix + r 31 | bind r command-prompt -I "#W" "rename-window '%%'" 32 | 33 | # Reload tmux config by pressing prefix + R 34 | bind R source-file ~/.config/tmux/tmux.conf \; display "TMUX Conf Reloaded" 35 | 36 | # Clear screen with prefix + l 37 | bind C-l send-keys 'C-l' 38 | 39 | # Open a project in a separate window 40 | bind-key -n C-f run-shell "tmux new-window -t 10 -n project-selector cd-to-project" 41 | 42 | # Apply Tc 43 | set -ga terminal-overrides ",xterm-256color:RGB:smcup@:rmcup@" 44 | 45 | # Enable focus-events 46 | set -g focus-events on 47 | 48 | # Set default escape-time 49 | set-option -sg escape-time 10 50 | 51 | # Smart pane switching with awareness of Vim splits 52 | is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?|fzf|atuin)(diff)?$'" 53 | bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' 54 | bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' 55 | bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' 56 | bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' 57 | 58 | bind-key -T copy-mode-vi 'C-h' select-pane -L 59 | bind-key -T copy-mode-vi 'C-j' select-pane -D 60 | bind-key -T copy-mode-vi 'C-k' select-pane -U 61 | bind-key -T copy-mode-vi 'C-l' select-pane -R 62 | ''; 63 | }; 64 | 65 | # Enable catppuccin theming for tmux. 66 | catppuccin = { 67 | tmux = { 68 | enable = true; 69 | extraConfig = '' 70 | set -g @catppuccin_flavor "macchiato" 71 | set -g @catppuccin_status_background "none" 72 | 73 | set -g @catppuccin_window_current_number_color "#{@thm_peach}" 74 | set -g @catppuccin_window_current_text " #W" 75 | set -g @catppuccin_window_current_text_color "#{@thm_bg}" 76 | set -g @catppuccin_window_number_color "#{@thm_blue}" 77 | set -g @catppuccin_window_text " #W" 78 | set -g @catppuccin_window_text_color "#{@thm_surface_0}" 79 | set -g @catppuccin_status_left_separator "█" 80 | 81 | set -g status-right "#{E:@catppuccin_status_host}#{E:@catppuccin_status_date_time}" 82 | set -g status-left "" 83 | ''; 84 | }; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/ext_preferences/com.github.nortmas.chrome-bookmarks.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/modules/home-manager/programs/ulauncher/config/ext_preferences/com.github.nortmas.chrome-bookmarks.db -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "com.github.nortmas.chrome-bookmarks": { 3 | "id": "com.github.nortmas.chrome-bookmarks", 4 | "url": "https://github.com/nortmas/chrome-bookmarks", 5 | "updated_at": "2025-05-22T09:13:39.079659", 6 | "last_commit": "b4598ea1e208cd6feb49574e998721dcc771157f", 7 | "last_commit_time": "2021-01-09T15:04:28" 8 | } 9 | } -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/icons/brave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/modules/home-manager/programs/ulauncher/config/icons/brave.png -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/icons/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/icons/quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/modules/home-manager/programs/ulauncher/config/icons/quit.png -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/icons/tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexNabokikh/nix-config/b021df3e13a57f2f8e435bd2ac5c15ed6be30a0b/modules/home-manager/programs/ulauncher/config/icons/tools.png -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "blacklisted-desktop-dirs": "/usr/share/locale:/usr/share/app-install:/usr/share/kservices5:/usr/share/fk5:/usr/share/kservicetypes5:/usr/share/applications/screensavers:/usr/share/kde4:/usr/share/mimelnk", 3 | "clear-previous-query": true, 4 | "disable-desktop-filters": true, 5 | "grab-mouse-pointer": true, 6 | "hotkey-show-app": "space", 7 | "render-on-screen": "mouse-pointer-monitor", 8 | "show-indicator-icon": false, 9 | "show-recent-apps": "0", 10 | "terminal-command": "", 11 | "theme-name": "Catppuccin-Macchiato-Lavender" 12 | } -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/user-themes/Catppuccin-Macchiato-Lavender/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": "1", 3 | "name": "Catppuccin-Macchiato-Lavender", 4 | "display_name": "Catppuccin Macchiato Lavender", 5 | "extend_theme": "light", 6 | "css_file": "theme.css", 7 | "css_file_gtk_3.20+": "theme-gtk-3.20.css", 8 | "matched_text_hl_colors": { 9 | "when_selected": "#b7bdf8", 10 | "when_not_selected": "#b7bdf8" 11 | } 12 | } -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/user-themes/Catppuccin-Macchiato-Lavender/theme-gtk-3.20.css: -------------------------------------------------------------------------------- 1 | @import url("theme.css"); 2 | .input { 3 | caret-color: #b7bdf8; 4 | } 5 | /* workaround for a bug in GTK+ < 3.20 */ 6 | .selected.item-box { 7 | border: none; 8 | } -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/config/user-themes/Catppuccin-Macchiato-Lavender/theme.css: -------------------------------------------------------------------------------- 1 | /*Catpuccin colors*/ 2 | @define-color backgroundColor #24273a; 3 | @define-color accentColor #b7bdf8; 4 | @define-color textColor #cad3f5; 5 | @define-color subTextColor #b8c0e0; 6 | .app { 7 | background-color: @backgroundColor; 8 | border-color: @accentColor; 9 | border-radius: 8px; 10 | } 11 | .input { 12 | color: @accentColor; 13 | } 14 | .input *:selected, 15 | .input *:focus, 16 | *:selected:focus { 17 | background-color: alpha (@accentColor, 0.4); 18 | color: @textColor; 19 | } 20 | .item-text { 21 | color: @textColor; 22 | } 23 | .item-name { 24 | color: @textColor; 25 | font-size: 1.2rem; 26 | } 27 | .selected.item-box { 28 | background-color: alpha (@accentColor, 0.3); 29 | border-radius: 8px; 30 | } 31 | .selected.item-box .item-text { 32 | color: @textColor; 33 | } 34 | .selected.item-box .item-name { 35 | color: @textColor; 36 | font-size: 1.2rem; 37 | } 38 | .item-shortcut { 39 | color: @accentColor; 40 | } 41 | .selected.item-box .item-shortcut { 42 | color: @accentColor; 43 | font-size: 1.1rem; 44 | } 45 | .selected.item-box{ 46 | color: @accentColor; 47 | } 48 | .prefs-btn { 49 | opacity: 1; 50 | } 51 | .prefs-btn:hover { 52 | background-color: alpha (@accentColor, 1.0); 53 | } -------------------------------------------------------------------------------- /modules/home-manager/programs/ulauncher/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: let 6 | manageShortcutsScript = pkgs.writeScriptBin "manage-ulauncher-shortcuts" '' 7 | #!/usr/bin/env bash 8 | set -euo pipefail 9 | 10 | configDir="$HOME/.config/ulauncher" 11 | shortcutsFile="$configDir/shortcuts.json" 12 | 13 | # Ensure the configuration directory exists 14 | mkdir -p "$configDir" 15 | 16 | # JSON content to ensure is in `shortcuts.json` 17 | cat >"$shortcutsFile" <<'EOF' 18 | { 19 | "0155d149-516b-4f38-bdab-f51d245818e3": { 20 | "id": "0155d149-516b-4f38-bdab-f51d245818e3", 21 | "name": "Search", 22 | "keyword": "br", 23 | "cmd": "https://search.brave.com/search?q=%s", 24 | "icon": "~/.config/ulauncher/icons/brave.png", 25 | "is_default_search": true, 26 | "run_without_argument": false, 27 | "added": 1747897791.8054328 28 | }, 29 | "11e80e5b-3841-403c-ae08-64e53372e7df": { 30 | "id": "11e80e5b-3841-403c-ae08-64e53372e7df", 31 | "name": "Quit All Applications", 32 | "keyword": "quit", 33 | "cmd": "#!/usr/bin/env bash\n\n[ \"$DESKTOP_SESSION\" = \"hyprland\" ] || exit 0\n\nhyprctl -j clients 2>/dev/null | jq -j '.[] | \"dispatch closewindow address:\\(.address); \"' |\n\txargs -r hyprctl --batch 2>/dev/null", 34 | "icon": "~/.config/ulauncher/icons/quit.png", 35 | "is_default_search": false, 36 | "run_without_argument": true, 37 | "added": 1747897834.2170281 38 | }, 39 | "b72345b1-312c-4a39-89fc-0265437c2ccf": { 40 | "id": "b72345b1-312c-4a39-89fc-0265437c2ccf", 41 | "name": "Work Tools", 42 | "keyword": "work", 43 | "cmd": "#!/usr/bin/env bash\n\n# Check if Brave is already running\nif ! pgrep \"brave\" >/dev/null; then\n\techo \"Launching Brave...\"\n\tbrave &\nelse\n\techo \"Brave is already running.\"\nfi\n\n# Check if Alacritty is already running\nif ! pgrep -x \"alacritty\" >/dev/null; then\n\techo \"Launching Alacritty...\"\n\talacritty &\nelse\n\techo \"Alacritty is already running.\"\nfi\n\n# Check if Telegram is already running\nif ! pgrep -x \"telegram-desktop\" >/dev/null; then\n\techo \"Launching Telegram...\"\n\ttelegram-desktop\nelse\n\techo \"Telegram is already running.\"\nfi", 44 | "icon": "~/.config/ulauncher/icons/tools.png", 45 | "is_default_search": false, 46 | "run_without_argument": true, 47 | "added": 1747897863.1040845 48 | }, 49 | "56b485f3-9561-49af-9fe4-b4144efa9fb2": { 50 | "id": "56b485f3-9561-49af-9fe4-b4144efa9fb2", 51 | "name": "Lock\u2005Screen", 52 | "keyword": "lock", 53 | "cmd": "#!/usr/bin/env bash\n\nloginctl lock-session", 54 | "icon": "~/.config/ulauncher/icons/icon.svg", 55 | "is_default_search": false, 56 | "run_without_argument": true, 57 | "added": 1747898201.1167789 58 | }, 59 | "8407589e-0e44-41cf-8a86-32d9cc3b45d5": { 60 | "id": "8407589e-0e44-41cf-8a86-32d9cc3b45d5", 61 | "name": "Suspend / Sleep", 62 | "keyword": "suspend", 63 | "cmd": "#!/usr/bin/env bash\n\nsystemctl suspend -i", 64 | "icon": "~/.config/ulauncher/icons/icon.svg", 65 | "is_default_search": false, 66 | "run_without_argument": true, 67 | "added": 1747898274.058171 68 | }, 69 | "eda21a94-aa60-4db8-98cc-ff37687af457": { 70 | "id": "eda21a94-aa60-4db8-98cc-ff37687af457", 71 | "name": "Shut\u2005Down\u2005/\u2005Power\u2005Off", 72 | "keyword": "shutdown", 73 | "cmd": "#!/usr/bin/env bash\n\nsystemctl poweroff -i", 74 | "icon": "~/.config/ulauncher/icons/icon.svg", 75 | "is_default_search": false, 76 | "run_without_argument": true, 77 | "added": 1747898438.8860931 78 | }, 79 | "dac53ff3-db88-451b-89b1-89e81cfdd165": { 80 | "id": "dac53ff3-db88-451b-89b1-89e81cfdd165", 81 | "name": "Reboot\u2005/\u2005Restart", 82 | "keyword": "reboot", 83 | "cmd": "#!/usr/bin/env bash\n\nsystemctl reboot -i", 84 | "icon": "~/.config/ulauncher/icons/icon.svg", 85 | "is_default_search": false, 86 | "run_without_argument": true, 87 | "added": 1747898972.3437614 88 | } 89 | } 90 | EOF 91 | ''; 92 | in { 93 | config = lib.mkIf (!pkgs.stdenv.isDarwin) { 94 | # Ulauncher package 95 | home.packages = with pkgs; [ 96 | ulauncher 97 | ]; 98 | 99 | # Source ulauncher configuration from this repository 100 | xdg.configFile = { 101 | "ulauncher" = { 102 | recursive = true; 103 | source = ./config; 104 | }; 105 | }; 106 | 107 | # A bit nasty, but shortcuts file has to be writeble by the ulauncher 108 | home.activation.manageShortcuts = lib.hm.dag.entryAfter ["writeBoundary"] '' 109 | ${manageShortcutsScript}/bin/manage-ulauncher-shortcuts 110 | ''; 111 | }; 112 | } 113 | -------------------------------------------------------------------------------- /modules/home-manager/programs/wofi/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install wofi via home-manager module 3 | programs.wofi = { 4 | enable = true; 5 | settings = { 6 | insensitive = true; 7 | normal_window = true; 8 | prompt = "Search..."; 9 | width = "50%"; 10 | height = "40%"; 11 | key_up = "Ctrl-k"; 12 | key_down = "Ctrl-j"; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /modules/home-manager/programs/zsh/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: { 6 | # Zsh shell configuration 7 | programs.zsh = { 8 | enable = true; 9 | enableCompletion = true; 10 | shellAliases = { 11 | ff = "fastfetch"; 12 | 13 | # git 14 | gaa = "git add --all"; 15 | gcam = "git commit --all --message"; 16 | gcl = "git clone"; 17 | gco = "git checkout"; 18 | ggl = "git pull"; 19 | ggp = "git push"; 20 | 21 | # kubectl 22 | k = "kubectl"; 23 | kgno = "kubectl get node"; 24 | kdno = "kubectl describe node"; 25 | kgp = "kubectl get pods"; 26 | kep = "kubectl edit pods"; 27 | kdp = "kubectl describe pods"; 28 | kdelp = "kubectl delete pods"; 29 | kgs = "kubectl get svc"; 30 | kes = "kubectl edit svc"; 31 | kds = "kubectl describe svc"; 32 | kdels = "kubectl delete svc"; 33 | kgi = "kubectl get ingress"; 34 | kei = "kubectl edit ingress"; 35 | kdi = "kubectl describe ingress"; 36 | kdeli = "kubectl delete ingress"; 37 | kgns = "kubectl get namespaces"; 38 | kens = "kubectl edit namespace"; 39 | kdns = "kubectl describe namespace"; 40 | kdelns = "kubectl delete namespace"; 41 | kgd = "kubectl get deployment"; 42 | ked = "kubectl edit deployment"; 43 | kdd = "kubectl describe deployment"; 44 | kdeld = "kubectl delete deployment"; 45 | kgsec = "kubectl get secret"; 46 | kdsec = "kubectl describe secret"; 47 | kdelsec = "kubectl delete secret"; 48 | 49 | ld = "lazydocker"; 50 | lg = "lazygit"; 51 | 52 | repo = "cd $HOME/Documents/repositories"; 53 | temp = "cd $HOME/Downloads/temp"; 54 | 55 | v = "nvim"; 56 | vi = "nvim"; 57 | vim = "nvim"; 58 | 59 | ls = "eza --icons always"; # default view 60 | ll = "eza -bhl --icons --group-directories-first"; # long list 61 | la = "eza -abhl --icons --group-directories-first"; # all list 62 | lt = "eza --tree --level=2 --icons"; # tree 63 | }; 64 | initContent = '' 65 | # kubectl auto-complete 66 | source <(kubectl completion zsh) 67 | 68 | # bindings 69 | bindkey -e 70 | bindkey '^H' backward-delete-word 71 | bindkey '^[[1;5C' forward-word 72 | bindkey '^[[1;5D' backward-word 73 | 74 | # open commands in $EDITOR with C-e 75 | autoload -z edit-command-line 76 | zle -N edit-command-line 77 | bindkey "^v" edit-command-line 78 | 79 | ${lib.optionalString pkgs.stdenv.hostPlatform.isDarwin '' 80 | # Enable ALT-C fzf keybinding on Mac 81 | bindkey 'ć' fzf-cd-widget 82 | ''} 83 | ''; 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/asg-getter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script is designed to assist in managing AWS Kubernetes clusters, it provides functionality 4 | for querying information about ASGs, and their respective instances using AWS CLI and kubectl. 5 | 6 | Features: 7 | - Cluster Information Retrieval: Fetches the current AWS Kubernetes cluster's name and default region. 8 | - Auto Scaling Group Interaction: Lists ASGs associated with the Kubernetes cluster and allows the user 9 | to select an ASG to query further. 10 | - Instance Information: For a selected ASG, lists all EC2 instances and retrieves their corresponding 11 | Kubernetes node names. 12 | 13 | Dependencies: 14 | - AWS CLI: For interacting with AWS services. 15 | - kubectl: For Kubernetes cluster management. 16 | - Python 3 and standard libraries: re, subprocess, sys. 17 | 18 | Usage: 19 | The script is executed as a standalone Python script. It guides the user through a series of prompts to select 20 | the desired ASG and view details about its instances. 21 | """ 22 | 23 | __author__ = "Alexander Nabokikh" 24 | __license__ = "GPL-2.0 license" 25 | 26 | 27 | import re 28 | import subprocess 29 | import sys 30 | 31 | 32 | def check_dependency(command): 33 | """ 34 | Check if a command-line dependency exists. 35 | 36 | Args: 37 | command (str): The name of the command to check. 38 | 39 | Raises: 40 | SystemExit: If the command is not found. 41 | """ 42 | try: 43 | subprocess.run([command, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 44 | except FileNotFoundError: 45 | print(f"Error: The command '{command}' is not found. Please install it before proceeding.") 46 | sys.exit(1) 47 | 48 | 49 | def fetch_cluster_info(): 50 | """ 51 | Fetches AWS cluster name and default region from `kubectl config current-context`. 52 | 53 | Returns: 54 | tuple: AWS_DEFAULT_REGION and CLUSTER_NAME or None if an error occurs. 55 | """ 56 | command = ["kubectl", "config", "current-context"] 57 | cluster_info = run_command(command) 58 | if not cluster_info: 59 | print("Failed to fetch cluster information.") 60 | return None, None 61 | 62 | match = re.search(r"arn:aws:eks:(.+?):\d+:cluster/(.+)$", cluster_info) 63 | if match: 64 | region, cluster_name = match.groups() 65 | return region, cluster_name 66 | 67 | return None, None 68 | 69 | 70 | def prompt(message): 71 | """ 72 | Prompt the user for a 'y' or 'n' response. 73 | 74 | Args: 75 | message (str): The message to display to the user. 76 | 77 | Returns: 78 | bool: True if 'y', False if 'n'. 79 | 80 | Raises: 81 | SystemExit: If the operation is cancelled by the user. 82 | """ 83 | while True: 84 | try: 85 | ans = input(message) 86 | if ans.lower() == "y": 87 | return True 88 | elif ans.lower() == "n": 89 | return False 90 | else: 91 | print("Invalid input. Please enter 'y' or 'n'.") 92 | except KeyboardInterrupt: 93 | print("\nOperation cancelled by the user.") 94 | sys.exit(0) 95 | 96 | 97 | def get_input(label): 98 | """ 99 | Get input from the user. 100 | 101 | Args: 102 | label (str): Label for the input field. 103 | 104 | Returns: 105 | str: User input. 106 | 107 | Raises: 108 | SystemExit: If the operation is cancelled by the user. 109 | """ 110 | try: 111 | return input(f"Please enter the {label}: ") 112 | except KeyboardInterrupt: 113 | print("\nOperation cancelled by the user.") 114 | sys.exit(0) 115 | 116 | 117 | def run_command(command): 118 | """ 119 | Run a shell command. 120 | 121 | Args: 122 | command (list): The command to run. 123 | 124 | Returns: 125 | str or None: The stdout as a string or None if an error occurs. 126 | 127 | Raises: 128 | SystemExit: If the operation is cancelled by the user. 129 | """ 130 | try: 131 | process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 132 | stdout, stderr = process.communicate() 133 | if process.returncode != 0: 134 | print(f"Command failed with error: {stderr}") 135 | return None 136 | return stdout.strip() 137 | except KeyboardInterrupt: 138 | print("\nOperation cancelled by the user.") 139 | sys.exit(0) 140 | 141 | 142 | def get_asgs(region, cluster_name): 143 | """ 144 | Get the Auto Scaling Groups for a given cluster in a region. 145 | 146 | Args: 147 | region (str): AWS region. 148 | cluster_name (str): Name of the cluster. 149 | 150 | Returns: 151 | list: List of Auto Scaling Groups or empty list if none found. 152 | """ 153 | command = [ 154 | "aws", 155 | "autoscaling", 156 | "describe-auto-scaling-groups", 157 | "--query", 158 | f"AutoScalingGroups[? Tags[? (Key=='kubernetes.io/cluster/{cluster_name}') && Value=='owned']].AutoScalingGroupName", 159 | "--output", 160 | "text", 161 | "--region", 162 | region, 163 | ] 164 | asgs_str = run_command(command) 165 | return asgs_str.split("\t") if asgs_str else [] 166 | 167 | 168 | def get_instances_in_asg(region, asg): 169 | """ 170 | Get the EC2 instances in a given Auto Scaling Group in a region. 171 | 172 | Args: 173 | region (str): AWS region. 174 | asg (str): Name of the Auto Scaling Group. 175 | 176 | Returns: 177 | list: List of instance IDs or empty list if none found. 178 | """ 179 | command = [ 180 | "aws", 181 | "autoscaling", 182 | "describe-auto-scaling-groups", 183 | "--auto-scaling-group-name", 184 | asg, 185 | "--query", 186 | "AutoScalingGroups[].Instances[][InstanceId]", 187 | "--output", 188 | "text", 189 | "--region", 190 | region, 191 | ] 192 | ins_str = run_command(command) 193 | return ins_str.split() if ins_str else [] 194 | 195 | 196 | def get_node_by_instance(region, instance_id): 197 | """ 198 | Get the node name by instance ID. 199 | 200 | Args: 201 | region (str): AWS region. 202 | instance_id (str): EC2 instance ID. 203 | 204 | Returns: 205 | str or None: Node name as a string or None if an error occurs. 206 | """ 207 | command = [ 208 | "aws", 209 | "ec2", 210 | "describe-instances", 211 | "--instance-ids", 212 | instance_id, 213 | "--query", 214 | "Reservations[].Instances[].PrivateDnsName", 215 | "--output", 216 | "text", 217 | "--region", 218 | region, 219 | ] 220 | return run_command(command) 221 | 222 | 223 | def main(): 224 | """ 225 | Main function. 226 | """ 227 | for cmd in ["aws", "kubectl"]: 228 | check_dependency(cmd) 229 | 230 | AWS_DEFAULT_REGION, CLUSTER_NAME = fetch_cluster_info() 231 | 232 | asgs = get_asgs(AWS_DEFAULT_REGION, CLUSTER_NAME) 233 | if not asgs: 234 | print("No ASGs found.") 235 | exit(1) 236 | 237 | print("Found the following Auto Scaling Groups:") 238 | for idx, asg in enumerate(asgs): 239 | print(f"{idx + 1}. {asg}") 240 | 241 | while True: 242 | asg_number = int(get_input("Enter the number corresponding to the ASG you want to query")) 243 | if 1 <= asg_number <= len(asgs): 244 | selected_asg = asgs[asg_number - 1] 245 | else: 246 | print("Invalid ASG number.") 247 | sys.exit(1) 248 | 249 | print(f"Querying information for autoscaling-group: {selected_asg}") 250 | instances = get_instances_in_asg(AWS_DEFAULT_REGION, selected_asg) 251 | 252 | if not instances: 253 | print("No instances found in the selected ASG.") 254 | else: 255 | for instance in instances: 256 | node = get_node_by_instance(AWS_DEFAULT_REGION, instance) 257 | if node: 258 | subprocess.run(["kubectl", "get", "node", node, "--no-headers=true"]) 259 | 260 | if not prompt("Would you like to query another ASG? (y/n): "): 261 | break 262 | 263 | 264 | if __name__ == "__main__": 265 | main() 266 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/asg-rotator: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script automates the process of updating Kubernetes nodes in an AWS environment. It integrates 4 | AWS CLI and kubectl to rotate nodes within Auto Scaling Groups (ASGs). 5 | 6 | Features: 7 | - Cluster Information Retrieval: Fetches the name and default region of the current AWS Kubernetes cluster. 8 | - ASG and Instance Management: Lists ASGs associated with the cluster, allows the user to select an ASG, 9 | and fetches EC2 instance IDs within the selected ASG. 10 | - Node Management: For each EC2 instance, identifies the corresponding Kubernetes node, checks its 11 | Kubernetes version, and performs updates if necessary. 12 | - Draining and Deleting Nodes: Drains Kubernetes nodes that don't match the specified version and 13 | then deletes them after a specified wait time. 14 | - User Interaction: Prompts the user for inputs and confirmation, handles keyboard interrupts and 15 | unexpected inputs. 16 | 17 | Dependencies: 18 | - AWS CLI: For interacting with AWS services. 19 | - kubectl: For Kubernetes cluster management. 20 | - Python 3 and standard libraries: json, re, subprocess, sys, time. 21 | 22 | Usage: 23 | The script is executed as a standalone Python script. It guides the user through selecting an ASG, 24 | specifying the target Kubernetes version, and then proceeds to update the nodes. 25 | """ 26 | 27 | __author__ = "Alexander Nabokikh" 28 | __license__ = "GPL-2.0 license" 29 | 30 | 31 | import json 32 | import re 33 | import subprocess 34 | import sys 35 | import time 36 | 37 | 38 | def check_dependency(command): 39 | """ 40 | Check if a given command-line tool is installed. 41 | 42 | Args: 43 | command (str): The command-line tool to check. 44 | 45 | Raises: 46 | SystemExit: If the command is not installed. 47 | """ 48 | try: 49 | subprocess.run([command, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 50 | except FileNotFoundError: 51 | print(f"Error: The command '{command}' is not found. Please install it before proceeding.") 52 | sys.exit(1) 53 | 54 | 55 | def fetch_cluster_info(): 56 | """ 57 | Fetches AWS cluster name and default region from `kubectl config current-context`. 58 | 59 | Returns: 60 | tuple: AWS_DEFAULT_REGION and CLUSTER_NAME or None if an error occurs. 61 | """ 62 | command = ["kubectl", "config", "current-context"] 63 | cluster_info = run_command(command) 64 | if not cluster_info: 65 | print("Failed to fetch cluster information.") 66 | return None, None 67 | 68 | match = re.search(r"arn:aws:eks:(.+?):\d+:cluster/(.+)$", cluster_info) 69 | if match: 70 | region, cluster_name = match.groups() 71 | return region, cluster_name 72 | 73 | return None, None 74 | 75 | 76 | def run_command(command_list, capture_output=True): 77 | """ 78 | Run a shell command and capture its output. 79 | 80 | Args: 81 | command_list (list): List of command and arguments. 82 | capture_output (bool, optional): Whether to capture output. Defaults to True. 83 | 84 | Returns: 85 | str: The standard output of the command. 86 | 87 | Raises: 88 | SystemExit: If the command fails to execute. 89 | """ 90 | try: 91 | result = subprocess.run(command_list, capture_output=capture_output, text=True, check=True) 92 | return result.stdout.strip() 93 | except subprocess.CalledProcessError as e: 94 | print(f"Command failed with error: {e}") 95 | sys.exit(1) 96 | 97 | 98 | def prompt(): 99 | """ 100 | Prompt the user to continue or not. 101 | 102 | Returns: 103 | bool: True if the user wants to continue, False otherwise. 104 | 105 | Raises: 106 | SystemExit: If the operation is cancelled by the user. 107 | """ 108 | while True: 109 | try: 110 | ans = input("Continue? (y/n): ") 111 | if ans.lower() == "y": 112 | return True 113 | elif ans.lower() == "n": 114 | return False 115 | else: 116 | print("Invalid input. Please enter 'y' or 'n'.") 117 | except KeyboardInterrupt: 118 | print("\nOperation cancelled by the user.") 119 | sys.exit(0) 120 | 121 | 122 | def get_input(label): 123 | """ 124 | Get input from the user. 125 | 126 | Args: 127 | label (str): Label for the input field. 128 | 129 | Returns: 130 | str: User input. 131 | 132 | Raises: 133 | SystemExit: If the operation is cancelled by the user. 134 | """ 135 | try: 136 | return input(f"Please enter the {label}: ") 137 | except KeyboardInterrupt: 138 | print("\nOperation cancelled by the user.") 139 | sys.exit(0) 140 | 141 | 142 | def get_asgs(region, cluster_name): 143 | """ 144 | Get the Auto Scaling Groups for a given cluster in a region. 145 | 146 | Args: 147 | region (str): AWS region. 148 | cluster_name (str): Name of the cluster. 149 | 150 | Returns: 151 | list: List of Auto Scaling Groups or empty list if none found. 152 | """ 153 | command = [ 154 | "aws", 155 | "autoscaling", 156 | "describe-auto-scaling-groups", 157 | "--query", 158 | f"AutoScalingGroups[? Tags[? (Key=='kubernetes.io/cluster/{cluster_name}') && Value=='owned']].AutoScalingGroupName", 159 | "--output", 160 | "text", 161 | "--region", 162 | region, 163 | ] 164 | asgs_str = run_command(command) 165 | return asgs_str.split("\t") if asgs_str else [] 166 | 167 | 168 | def get_instances(asg_name, region): 169 | """ 170 | Get a list of instance IDs for a given Auto Scaling Group (ASG). 171 | 172 | Args: 173 | ASG_NAME (str): The name of the ASG. 174 | 175 | Returns: 176 | list: List of instance IDs. 177 | """ 178 | return run_command( 179 | [ 180 | "aws", 181 | "autoscaling", 182 | "describe-auto-scaling-groups", 183 | "--auto-scaling-group-name", 184 | asg_name, 185 | "--region", 186 | region, 187 | "--query", 188 | "AutoScalingGroups[].Instances[][InstanceId]", 189 | "--output", 190 | "text", 191 | ] 192 | ).split() 193 | 194 | 195 | def get_node_name(instance_id, region): 196 | """ 197 | Get the node name corresponding to a given EC2 instance ID. 198 | 199 | Args: 200 | instance_id (str): EC2 instance ID. 201 | 202 | Returns: 203 | str: Node name. 204 | """ 205 | return run_command( 206 | [ 207 | "aws", 208 | "ec2", 209 | "describe-instances", 210 | "--instance-ids", 211 | instance_id, 212 | "--region", 213 | region, 214 | "--query", 215 | "Reservations[].Instances[].PrivateDnsName", 216 | "--output", 217 | "text", 218 | ] 219 | ) 220 | 221 | 222 | def get_node_version(node_name): 223 | """ 224 | Get the Kubernetes version for a given node. 225 | 226 | Args: 227 | node_name (str): The name of the Kubernetes node. 228 | 229 | Returns: 230 | str: The Kubernetes version of the node. 231 | """ 232 | try: 233 | result = subprocess.run( 234 | [ 235 | "kubectl", 236 | "get", 237 | "node", 238 | node_name, 239 | "-o", 240 | "custom-columns=VERSION:.status.nodeInfo.kubeletVersion", 241 | "--no-headers=true", 242 | ], 243 | check=True, 244 | text=True, 245 | stdout=subprocess.PIPE, 246 | stderr=subprocess.PIPE, 247 | ) 248 | return result.stdout.strip() 249 | except subprocess.CalledProcessError: 250 | return None 251 | 252 | 253 | def main(): 254 | """ 255 | The main function that orchestrates the entire process of updating Kubernetes nodes. 256 | """ 257 | for cmd in ["aws", "kubectl"]: 258 | check_dependency(cmd) 259 | 260 | AWS_DEFAULT_REGION, CLUSTER_NAME = fetch_cluster_info() 261 | 262 | WAIT = 15 263 | 264 | asgs = get_asgs(AWS_DEFAULT_REGION, CLUSTER_NAME) 265 | if not asgs: 266 | print("No ASGs found.") 267 | exit(1) 268 | 269 | print("Found the following Auto Scaling Groups:") 270 | for idx, asg in enumerate(asgs): 271 | print(f"{idx + 1}. {asg}") 272 | 273 | asg_number = int(get_input("Enter the number corresponding to the ASG")) 274 | if 1 <= asg_number <= len(asgs): 275 | selected_asg = asgs[asg_number - 1] 276 | else: 277 | print("Invalid ASG number.") 278 | sys.exit(1) 279 | 280 | K8S_VERSION = get_input("Enter the target Kubernetes version (e.g., 1.24)") 281 | if not K8S_VERSION: 282 | print("Error - Kubernetes version not provided.") 283 | sys.exit(1) 284 | 285 | instances = get_instances(selected_asg, AWS_DEFAULT_REGION) 286 | 287 | for instance in instances: 288 | node_name = get_node_name(instance, AWS_DEFAULT_REGION) 289 | print(f"Node name: {node_name}") 290 | 291 | node_version = get_node_version(node_name) 292 | 293 | if not node_version: 294 | print("Version is empty. Skipping...") 295 | continue 296 | 297 | if K8S_VERSION in node_version: 298 | print(f"Node {node_name} matches desired version {K8S_VERSION}. Skipping...") 299 | continue 300 | 301 | print(f"Do you want to proceed with draining the node {node_name}?") 302 | if not prompt(): 303 | print("Skipping this node.") 304 | continue 305 | 306 | subprocess.run( 307 | ["kubectl", "drain", "--ignore-daemonsets=true", "--delete-emptydir-data=true", "--force", node_name] 308 | ) 309 | 310 | print(f"Checking for pods on node {node_name} ...") 311 | 312 | pod_data = json.loads(run_command(["kubectl", "get", "po", "-A", "-o", "json"])) 313 | 314 | for item in pod_data["items"]: 315 | try: 316 | if item["spec"]["nodeName"] == node_name: 317 | print(item["metadata"]["name"]) 318 | except KeyError: 319 | print(f"KeyError: 'nodeName' not found in item: {item['metadata']['name']}") 320 | 321 | print(f"Deleting node in {WAIT} seconds... press Ctrl-C to abort") 322 | time.sleep(WAIT) 323 | run_command(["kubectl", "delete", "node", node_name]) 324 | 325 | print(f"Terminating EC2 instance {instance} ...") 326 | run_command(["aws", "ec2", "terminate-instances", "--instance-ids", instance, "--region", AWS_DEFAULT_REGION]) 327 | 328 | 329 | if __name__ == "__main__": 330 | try: 331 | main() 332 | except KeyboardInterrupt: 333 | print("\nOperation cancelled by the user. Exiting...") 334 | sys.exit(1) 335 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/cd-to-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | selected=$(find ~/Documents/repositories -mindepth 1 -maxdepth 2 -type d -not -iwholename '*.git*' | fzf) 4 | if [ -n "$selected" ]; then 5 | tmux new-window -c "$selected" -n "$(basename "$selected")" || exit 6 | fi 7 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/fif: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ ! "$#" -gt 0 ]; then 4 | echo "Need a string to search for!" 5 | return 1 6 | fi 7 | 8 | rg --hidden --glob '!.git' --files-with-matches --no-messages "$1" | fzf --preview "rg --ignore-case --pretty --context 10 '$1' {}" 9 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/fkill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pid=$(ps -ef | sed 1d | fzf | awk '{print $2}') 4 | 5 | if [ "x$pid" != "x" ]; then 6 | sudo kill -"${1:-9}" "$pid" 7 | fi 8 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/git-reset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script is designed to automate the process of resetting multiple Git repositories to their latest 4 | commit on the current branch. It is especially useful in environments where multiple repositories are 5 | managed simultaneously and require frequent synchronization. 6 | 7 | Features: 8 | - Git Repository Reset: Resets any identified Git repository to the latest commit on its current branch. 9 | - Directory Traversal: Scans a specified base directory (defaulting to the current directory) to find 10 | all directories containing a Git repository. 11 | - Terragrunt Cache Exclusion: Skips over directories named '.terragrunt-cache', which are typically 12 | used for caching in Terraform workflows. 13 | 14 | Dependencies: 15 | - Git: For managing and resetting the repositories. 16 | - Python 3 and standard libraries: os, subprocess. 17 | 18 | Usage: 19 | The script is executed as a standalone Python script. It requires no additional input from the user, 20 | automatically finding and resetting Git repositories in the current or specified directory. 21 | """ 22 | 23 | __author__ = "Alexander Nabokikh" 24 | __license__ = "GPL-2.0 license" 25 | 26 | 27 | import os 28 | import subprocess 29 | 30 | 31 | def reset_git_repo(path): 32 | """Reset a git repository to the latest commit on the current branch.""" 33 | old_cwd = os.getcwd() 34 | 35 | try: 36 | os.chdir(path) 37 | subprocess.run(["git", "reset", "--hard", "HEAD"]) 38 | finally: 39 | os.chdir(old_cwd) 40 | 41 | 42 | def find_git_dirs(base="."): 43 | """Find all directories containing a .git directory and excluding .terragrunt-cache.""" 44 | for root, dirs, _ in os.walk(base): 45 | if ".terragrunt-cache" in dirs: 46 | dirs.remove(".terragrunt-cache") 47 | 48 | if ".git" in dirs: 49 | yield root 50 | 51 | 52 | def main(): 53 | """Main function.""" 54 | try: 55 | for git_repo in find_git_dirs(): 56 | print(f"Resetting repository: {git_repo}") 57 | reset_git_repo(git_repo) 58 | except KeyboardInterrupt: 59 | print("\nScript interrupted by the user. Exiting.") 60 | 61 | 62 | if __name__ == "__main__": 63 | main() 64 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/hyprshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | function Help() { 6 | cat <&2 printf "$fmt" "$@" 52 | } 53 | 54 | function send_notification() { 55 | if [ $SILENT -eq 1 ]; then 56 | return 0 57 | fi 58 | 59 | local message 60 | if [ $CLIPBOARD -eq 1 ]; then 61 | message="Image copied to the clipboard" 62 | else 63 | message="Image saved in ${1} and copied to the clipboard." 64 | fi 65 | notify-send "Screenshot saved" \ 66 | "${message}" \ 67 | -t "$NOTIF_TIMEOUT" -i "${1}" -a Hyprshot 68 | } 69 | 70 | function trim() { 71 | Print "Geometry: %s\n" "${1}" 72 | local geometry="${1}" 73 | local xy_str wh_str x y width height 74 | local max_width max_height min_x min_y 75 | local cropped_x cropped_y cropped_width cropped_height 76 | local cropped 77 | 78 | xy_str=$(echo "${geometry}" | cut -d' ' -f1) 79 | wh_str=$(echo "${geometry}" | cut -d' ' -f2) 80 | x=$(echo "${xy_str}" | cut -d',' -f1) 81 | y=$(echo "${xy_str}" | cut -d',' -f2) 82 | width=$(echo "${wh_str}" | cut -dx -f1) 83 | height=$(echo "${wh_str}" | cut -dx -f2) 84 | 85 | max_width=$(hyprctl monitors -j | jq -r '[.[] | if (.transform % 2 == 0) then (.x + .width) else (.x + .height) end] | max') 86 | max_height=$(hyprctl monitors -j | jq -r '[.[] | if (.transform % 2 == 0) then (.y + .height) else (.y + .width) end] | max') 87 | 88 | min_x=$(hyprctl monitors -j | jq -r '[.[] | (.x)] | min') 89 | min_y=$(hyprctl monitors -j | jq -r '[.[] | (.y)] | min') 90 | 91 | cropped_x=$x 92 | cropped_y=$y 93 | cropped_width=$width 94 | cropped_height=$height 95 | 96 | if ((x + width > max_width)); then 97 | cropped_width=$((max_width - x)) 98 | fi 99 | if ((y + height > max_height)); then 100 | cropped_height=$((max_height - y)) 101 | fi 102 | 103 | if ((x < min_x)); then 104 | cropped_x="$min_x" 105 | cropped_width=$((cropped_width + x - min_x)) 106 | fi 107 | if ((y < min_y)); then 108 | cropped_y="$min_y" 109 | cropped_height=$((cropped_height + y - min_y)) 110 | fi 111 | 112 | cropped=$(printf "%s,%s %sx%s" \ 113 | "${cropped_x}" "${cropped_y}" \ 114 | "${cropped_width}" "${cropped_height}") 115 | Print "Crop: %s\n" "${cropped}" 116 | echo "${cropped}" 117 | } 118 | 119 | function save_geometry() { 120 | local geometry="${1}" 121 | local output="" 122 | 123 | if [ $RAW -eq 1 ]; then 124 | grim -g "${geometry}" - 125 | return 0 126 | fi 127 | 128 | if [ $CLIPBOARD -eq 0 ]; then 129 | mkdir -p "$SAVEDIR" 130 | grim -g "${geometry}" "$SAVE_FULLPATH" 131 | output="$SAVE_FULLPATH" 132 | wl-copy --type image/png <"$output" 133 | if [ ${#COMMAND_ARGS[@]} -gt 0 ]; then 134 | "${COMMAND_ARGS[@]}" "$output" 135 | fi 136 | else 137 | wl-copy --type image/png < <(grim -g "${geometry}" -) 138 | fi 139 | 140 | send_notification "$output" 141 | } 142 | 143 | function checkRunning() { 144 | sleep 1 145 | while true; do 146 | if [[ $(pgrep slurp | wc -m) == 0 ]]; then 147 | pkill hyprpicker 148 | exit 149 | fi 150 | sleep 0.1 151 | done 152 | } 153 | 154 | function begin_grab() { 155 | if [ $FREEZE -eq 1 ] && [ "$(command -v "hyprpicker")" ] >/dev/null 2>&1; then 156 | hyprpicker -r -z & 157 | sleep 0.2 158 | fi 159 | local option="$1" 160 | local geometry 161 | 162 | case "$option" in 163 | output) 164 | if [ $CURRENT -eq 1 ]; then 165 | geometry=$(grab_active_output) 166 | elif [ -z "$SELECTED_MONITOR" ]; then 167 | geometry=$(grab_output) 168 | else 169 | geometry=$(grab_selected_output "$SELECTED_MONITOR") 170 | fi 171 | ;; 172 | region) 173 | geometry=$(grab_region) 174 | ;; 175 | window) 176 | if [ $CURRENT -eq 1 ]; then 177 | geometry=$(grab_active_window) 178 | else 179 | geometry=$(grab_window) 180 | fi 181 | local trimmed_geometry 182 | trimmed_geometry=$(trim "${geometry}") 183 | geometry="$trimmed_geometry" 184 | ;; 185 | esac 186 | if [ "${DELAY:-0}" -gt 0 ]; then 187 | sleep "${DELAY}" 188 | fi 189 | save_geometry "${geometry}" 190 | } 191 | 192 | function grab_output() { 193 | slurp -or 194 | } 195 | 196 | function grab_active_output() { 197 | local active_workspace monitors current_monitor active_ws_id 198 | active_workspace=$(hyprctl -j activeworkspace) 199 | monitors=$(hyprctl -j monitors) 200 | Print "Monitors: %s\n" "$monitors" 201 | Print "Active workspace: %s\n" "$active_workspace" 202 | 203 | active_ws_id=$(echo "$active_workspace" | jq -r '.id') 204 | current_monitor=$(echo "$monitors" | jq -r --argjson id "$active_ws_id" 'first(.[] | select(.activeWorkspace.id == $id))') 205 | 206 | Print "Current output: %s\n" "$current_monitor" 207 | echo "$current_monitor" | jq -r '"\(.x),\(.y) \(.width/.scale|round)x\(.height/.scale|round)"' 208 | } 209 | 210 | function grab_selected_output() { 211 | local monitor_name="$1" 212 | local monitor 213 | Print "Capturing: %s\n" "${monitor_name}" 214 | monitor=$(hyprctl -j monitors | jq -r --arg name "$monitor_name" '.[] | select(.name == $name)') 215 | echo "$monitor" | jq -r '"\(.x),\(.y) \(.width/.scale|round)x\(.height/.scale|round)"' 216 | } 217 | 218 | function grab_region() { 219 | slurp -d 220 | } 221 | 222 | function grab_window() { 223 | local monitors clients boxes active_ws_ids_json 224 | monitors=$(hyprctl -j monitors) 225 | 226 | active_ws_ids_json=$(echo "$monitors" | jq -r 'map(.activeWorkspace.id)') 227 | clients=$(hyprctl -j clients | jq -r --argjson ids "$active_ws_ids_json" '[.[] | select(.workspace.id as $wsid | $ids | index($wsid))]') 228 | 229 | Print "Monitors: %s\n" "$monitors" 230 | Print "Clients: %s\n" "$clients" 231 | boxes="$(echo "$clients" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1]) \(.title)"' | cut -f1,2 -d' ')" 232 | Print "Boxes:\n%s\n" "$boxes" 233 | slurp -r <<<"$boxes" 234 | } 235 | 236 | function grab_active_window() { 237 | local active_window box 238 | active_window=$(hyprctl -j activewindow) 239 | box=$(echo "$active_window" | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | cut -f1,2 -d' ') 240 | Print "Box:\n%s\n" "$box" 241 | echo "$box" 242 | } 243 | 244 | function parse_mode() { 245 | local mode_arg="$1" 246 | 247 | case "$mode_arg" in 248 | window | region | output) 249 | OPTION="$mode_arg" 250 | ;; 251 | active) 252 | CURRENT=1 253 | ;; 254 | *) 255 | if hyprctl monitors -j | jq -re --arg name "$mode_arg" '.[] | select(.name == $name)' &>/dev/null; then 256 | SELECTED_MONITOR="$mode_arg" 257 | else 258 | Print "Error: Unknown mode or output name: %s\n" "$mode_arg" 259 | exit 3 260 | fi 261 | ;; 262 | esac 263 | } 264 | 265 | COMMAND_ARGS=() 266 | 267 | function args() { 268 | local options 269 | options=$(getopt -o hf:o:m:D:dszr:t: --long help,filename:,output-folder:,mode:,delay:,clipboard-only,debug,silent,freeze,raw,notif-timeout: -- "$@") 270 | eval set -- "$options" 271 | 272 | while true; do 273 | case "$1" in 274 | -h | --help) 275 | Help 276 | exit 277 | ;; 278 | -o | --output-folder) 279 | shift 280 | SAVEDIR="$1" 281 | ;; 282 | -f | --filename) 283 | shift 284 | FILENAME="$1" 285 | ;; 286 | -D | --delay) 287 | shift 288 | DELAY="$1" 289 | ;; 290 | -m | --mode) 291 | shift 292 | parse_mode "$1" 293 | ;; 294 | --clipboard-only) 295 | CLIPBOARD=1 296 | ;; 297 | -d | --debug) 298 | DEBUG=1 299 | ;; 300 | -z | --freeze) 301 | FREEZE=1 302 | ;; 303 | -s | --silent) 304 | SILENT=1 305 | ;; 306 | -r | --raw) 307 | RAW=1 308 | ;; 309 | -t | --notif-timeout) 310 | shift 311 | NOTIF_TIMEOUT="$1" 312 | ;; 313 | --) 314 | shift 315 | COMMAND_ARGS=("$@") 316 | break 317 | ;; 318 | esac 319 | shift 320 | done 321 | 322 | if [ -z "$OPTION" ]; then 323 | Print "A mode is required\n\nAvailable modes are:\n\toutput\n\tregion\n\twindow\n" 324 | exit 2 325 | fi 326 | } 327 | 328 | if [ -z "$1" ]; then 329 | Help 330 | exit 331 | fi 332 | 333 | CLIPBOARD=0 334 | DEBUG=0 335 | SILENT=0 336 | RAW=0 337 | NOTIF_TIMEOUT=5000 338 | CURRENT=0 339 | FREEZE=0 340 | if [ -z "$XDG_PICTURES_DIR" ] && type xdg-user-dir &>/dev/null; then 341 | XDG_PICTURES_DIR=$(xdg-user-dir PICTURES) 342 | fi 343 | FILENAME="$(date +'%Y-%m-%d-%H%M%S_hyprshot.png')" 344 | if [ -z "$HYPRSHOT_DIR" ]; then 345 | SAVEDIR="${XDG_PICTURES_DIR:-$HOME/Pictures}" 346 | else 347 | SAVEDIR="${HYPRSHOT_DIR}" 348 | fi 349 | 350 | args "$0" "$@" 351 | 352 | SAVE_FULLPATH="$SAVEDIR/$FILENAME" 353 | [ $CLIPBOARD -eq 0 ] && Print "Saving in: %s\n" "$SAVE_FULLPATH" 354 | begin_grab "$OPTION" & 355 | checkRunning 356 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/konfig-updater: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script is designed to lists AWS EKS clusters and updates the kubeconfig file for each found cluster. 4 | It is particularly useful for administrators who manage multiple AWS accounts with EKS clusters 5 | in different regions, allowing them to quickly switch contexts and manage these clusters. 6 | 7 | Features: 8 | - Account Retrieval: Parses the AWS configuration file to fetch a list of AWS profiles (accounts). 9 | - Cluster Listing: For each account and predefined region, lists all EKS clusters using the AWS CLI. 10 | - Kubeconfig Update: Updates the kubeconfig file for each discovered cluster, facilitating 11 | Kubernetes cluster management. 12 | - Region Support: Currently supports 'eu-west-1' and 'eu-central-1' regions. 13 | 14 | 15 | Dependencies: 16 | - AWS CLI: For interacting with AWS EKS and managing configurations. 17 | - jq: Command-line JSON processor used for parsing AWS CLI output. 18 | - Python 3 and standard libraries: configparser, os, shutil, subprocess. 19 | 20 | Usage: 21 | The script is executed as a standalone Python script. It automatically iterates over the predefined 22 | accounts and regions, performing actions without needing additional user input. 23 | """ 24 | 25 | __author__ = "Alexander Nabokikh" 26 | __license__ = "GPL-2.0 license" 27 | 28 | 29 | import configparser 30 | import os 31 | import shutil 32 | import subprocess 33 | 34 | regions = ["eu-west-1", "eu-central-1"] 35 | 36 | 37 | def check_dependencies(): 38 | """Check if required dependencies are available.""" 39 | 40 | if not shutil.which("aws"): 41 | print("Error: AWS provider not found") 42 | exit(-1) 43 | 44 | 45 | def get_accounts(): 46 | """Get the list of accounts by parsing the ~/.aws/config file.""" 47 | config_file_path = os.path.expanduser("~/.aws/config") 48 | 49 | if not os.path.exists(config_file_path): 50 | print("Error: AWS config file not found") 51 | exit(-1) 52 | 53 | config_parser = configparser.ConfigParser() 54 | 55 | config_parser.read(config_file_path) 56 | 57 | accounts = [] 58 | for section in config_parser.sections(): 59 | if section.startswith("profile "): 60 | profile_name = section.split(" ", 1)[1] 61 | accounts.append(profile_name) 62 | 63 | if not accounts: 64 | print("Error: No AWS profiles found") 65 | exit(-1) 66 | 67 | return accounts 68 | 69 | 70 | def list_clusters(account, region): 71 | """List clusters in the given account and region.""" 72 | clusters_process = subprocess.run( 73 | ["aws", "eks", "list-clusters", "--region", region, "--profile", account], capture_output=True, text=True 74 | ) 75 | if clusters_process.returncode != 0: 76 | print(f"Error: Failed to list clusters on {account} {region}") 77 | return [] 78 | return subprocess.run( 79 | ["jq", "-r", ".clusters | .[]"], input=clusters_process.stdout, capture_output=True, text=True 80 | ).stdout.splitlines() 81 | 82 | 83 | def main(): 84 | """Main function.""" 85 | try: 86 | check_dependencies() 87 | 88 | accounts = get_accounts() 89 | 90 | for account in accounts: 91 | for region in regions: 92 | print(f"Switching for {account} {region}") 93 | 94 | clusters = list_clusters(account, region) 95 | 96 | if not clusters: 97 | print(f"No clusters found on {account} {region}") 98 | continue 99 | 100 | print(f"Found Clusters on {account} {region}:") 101 | print("\n".join(clusters)) 102 | 103 | for cluster in clusters: 104 | subprocess.run( 105 | ["aws", "eks", "update-kubeconfig", "--name", cluster, "--region", region, "--profile", account] 106 | ) 107 | 108 | except KeyboardInterrupt: 109 | print("\nScript interrupted by the user. Exiting.") 110 | 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/ks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | The script is designed to run in environments where Kubernetes clusters are managed through AWS 4 | and access is controlled via SAML authentication. It automates the process of logging into the 5 | appropriate AWS account and setting up the shell environment for further interactions with AWS services. 6 | 7 | Key functionalities include: 8 | - Checking if 'saml2aws' and 'kubectl' are installed on the system. 9 | - Executes 'kubectl ctx' to switch to specific kubernets context. 10 | - Retrieving the current Kubernetes context and extracting the associated AWS account number. 11 | - Parsing the AWS configuration file to find the relevant profile. 12 | - Finding the correct profile name by matching the account number in the AWS configuration. 13 | - Executing the 'saml2aws' command with the identified profile to set up the shell environment. 14 | 15 | Dependencies: 16 | - saml2aws: A tool for logging into an AWS account. 17 | - kubectl: A command-line tool for interacting with Kubernetes clusters. 18 | - Python 3 and standard libraries: configparser, os, re, subprocess. 19 | 20 | Usage: 21 | The script is executed as a standalone Python script. It does not take any command-line arguments 22 | and relies on the correct configuration of the AWS and Kubernetes environments on the user's system. 23 | 24 | """ 25 | 26 | __author__ = "Alexander Nabokikh" 27 | __license__ = "GPL-2.0 license" 28 | 29 | 30 | import configparser 31 | import os 32 | import re 33 | import subprocess 34 | 35 | 36 | def check_dependencies(): 37 | """ 38 | Check if required command-line tools are installed. 39 | """ 40 | try: 41 | for command in ["saml2aws", "kubectl"]: 42 | subprocess.run([command, "help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 43 | except FileNotFoundError: 44 | print(f"Error: The command '{command}' is not found. Please install it before proceeding.") 45 | exit(1) 46 | 47 | 48 | def select_context(): 49 | """Run kubectl ctx to choose context""" 50 | try: 51 | subprocess.run(["kubectl", "ctx"]) 52 | 53 | except subprocess.CalledProcessError as e: 54 | print(f"Error: kubectl ctx failed with an erro: {e}") 55 | exit(-1) 56 | 57 | 58 | def get_kube_context(): 59 | """Get the current Kubernetes context and extract the account number.""" 60 | try: 61 | kube_context = subprocess.check_output(["kubectl", "config", "current-context"]).decode().strip() 62 | print(f"Current Kubernetes context: {kube_context}") 63 | 64 | match = re.search(r"arn:aws:eks:([\w-]+):(\d+):cluster/([\w-]+)", kube_context) 65 | if match: 66 | account_number = match.group(2) 67 | print(f"Account Number: {account_number}") 68 | return account_number 69 | else: 70 | raise ValueError("Invalid Kubernetes context ARN") 71 | except subprocess.CalledProcessError as e: 72 | print(f"Error in getting Kubernetes context: {e}") 73 | exit(-1) 74 | 75 | 76 | def parse_aws_config(): 77 | """Parse AWS config file.""" 78 | aws_config_path = os.path.expanduser("~/.aws/config") 79 | if not os.path.exists(aws_config_path): 80 | print("AWS config file not found") 81 | exit(-1) 82 | 83 | config = configparser.ConfigParser() 84 | config.read(aws_config_path) 85 | return config 86 | 87 | 88 | def find_profile_name(config, account_number): 89 | """Find the profile name by matching the account number.""" 90 | for section in config.sections(): 91 | if "role_arn" in config[section] and account_number in config[section]["role_arn"]: 92 | return section.replace("profile ", "") 93 | return None 94 | 95 | 96 | def execute_saml2aws_command(profile_name): 97 | """Execute the saml2aws command with the found values.""" 98 | shell = os.getenv("SHELL", "/bin/zsh") 99 | 100 | try: 101 | subprocess.run(["saml2aws", "exec", "--exec-profile", profile_name, shell], check=True) 102 | except subprocess.CalledProcessError: 103 | print("Existing credentials failed, attempting new login") 104 | subprocess.run(["saml2aws", "login", "--skip-prompt"], check=True) 105 | subprocess.run(["saml2aws", "exec", "--exec-profile", profile_name, shell], check=True) 106 | 107 | 108 | def main(): 109 | """Main function.""" 110 | check_dependencies() 111 | select_context() 112 | account_number = get_kube_context() 113 | aws_config = parse_aws_config() 114 | profile_name = find_profile_name(aws_config, account_number) 115 | 116 | if profile_name: 117 | print(f"Profile Name: {profile_name}") 118 | execute_saml2aws_command(profile_name) 119 | else: 120 | print("Profile not found for the account number") 121 | exit(-1) 122 | 123 | 124 | if __name__ == "__main__": 125 | try: 126 | main() 127 | except KeyboardInterrupt: 128 | print("\nOperation cancelled by the user. Exiting...") 129 | exit(1) 130 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/ocr: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | grim -t png -g "$(slurp)" - | 4 | tesseract stdin stdout -l "eng+rus+pol" | 5 | tr -d '\f' | wl-copy 6 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/pull-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script automates the process of updating Git repositories located in a specified directory. 4 | It walks through the directory structure, identifies Git repositories, determines their main branch, 5 | and performs a 'git pull' operation to update each repository. 6 | 7 | Features: 8 | - Git Repository Identification: Checks directories to determine if they are Git repositories. 9 | - Main Branch Detection: Dynamically identifies the main branch for each repository. 10 | - Automated Git Pull: Executes a 'git pull' command for the main branch of each repository. 11 | - Directory Exclusion: Excludes directories related to Terraform and Terragrunt to avoid unnecessary processing. 12 | 13 | Dependencies: 14 | - Git: For managing and updating the repositories. 15 | - Python 3 and standard libraries: os, subprocess. 16 | 17 | Usage: 18 | The script is executed as a standalone Python script. It automatically searches for Git repositories 19 | in a predefined directory (default is '~/Documents/repositories') and updates them. 20 | """ 21 | 22 | __author__ = "Alexander Nabokikh" 23 | __license__ = "GPL-2.0 license" 24 | 25 | 26 | import os 27 | import subprocess 28 | 29 | repo_directory = os.path.expanduser("~/Documents/repositories") 30 | 31 | 32 | def is_git_directory(directory): 33 | """ 34 | Checks if a directory is a Git repository by looking for a .git subdirectory. 35 | """ 36 | return os.path.isdir(os.path.join(directory, ".git")) 37 | 38 | 39 | def get_git_main_branch(directory): 40 | """ 41 | Determines the name of the main branch for the Git repository located at 'directory'. 42 | """ 43 | os.chdir(directory) 44 | try: 45 | result = subprocess.run( 46 | ["git", "rev-parse", "--abbrev-ref", "HEAD"], check=True, capture_output=True, text=True 47 | ) 48 | return result.stdout.strip() 49 | except subprocess.CalledProcessError as e: 50 | print(f"Failed to determine the main branch for {directory}. Error: {str(e)}") 51 | return None 52 | 53 | 54 | def git_pull(directory): 55 | """ 56 | Performs a Git pull operation in the specified directory. 57 | """ 58 | os.chdir(directory) # Navigate to directory 59 | main_branch = get_git_main_branch(directory) 60 | 61 | if main_branch is None: 62 | print(f"Skipping pull operation for {directory}.") 63 | return 64 | 65 | try: 66 | # Run git pull command for the detected main branch 67 | subprocess.run(["git", "pull", "origin", main_branch], check=True, capture_output=True, text=True) 68 | print(f"Successfully updated {directory} from '{main_branch}' branch.") 69 | except subprocess.CalledProcessError as e: 70 | print(f"Failed to update {directory} from '{main_branch}' branch. Error: {str(e)}") 71 | 72 | 73 | def main(): 74 | if os.path.exists(repo_directory): 75 | for root, dirs, _ in os.walk(repo_directory): 76 | for dir in dirs: 77 | full_dir_path = os.path.join(root, dir) 78 | 79 | # Skip if the directory is under a .terraform directory 80 | if ".terraform" in full_dir_path.split("/") or ".terragrunt-cache" in full_dir_path.split("/"): 81 | continue 82 | 83 | if is_git_directory(full_dir_path): 84 | git_pull(full_dir_path) 85 | else: 86 | print(f"The directory {repo_directory} does not exist.") 87 | 88 | 89 | if __name__ == "__main__": 90 | main() 91 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/screen-recorder: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VIDEODIR="$HOME/Videos" 4 | DATE_FORMAT="+%Y-%m-%d_%H-%M-%S" 5 | 6 | if ! pgrep "wf-recorder" >/dev/null; then 7 | if [ ! -d "$VIDEODIR" ]; then 8 | mkdir -p "$VIDEODIR" 9 | fi 10 | FILENAME="$VIDEODIR/$(date --utc "$DATE_FORMAT").mp4" 11 | wf-recorder -f "$FILENAME" -g "$(slurp -c "#FFFFFF")" &>/dev/null & 12 | else 13 | killall -s SIGINT wf-recorder 14 | fi 15 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/terra-clean: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | This script is designed to recursively search for and delete .terraform and .terragrunt-cache 4 | directories within a specified base directory (~/Documents/repositories/). 5 | 6 | Features: 7 | - Directory Traversal: Scans the ~/Documents/repositories/ directory to find all .terraform 8 | and .terragrunt-cache directories. 9 | - Directory Deletion: Removes identified .terraform and .terragrunt-cache directories. 10 | - Error Handling: Provides feedback on successful deletions and any errors encountered. 11 | 12 | Dependencies: 13 | - Python 3 and standard libraries: os, shutil. 14 | 15 | Usage: 16 | The script is executed as a standalone Python script. It requires no additional input from the user, 17 | automatically finding and deleting .terraform and .terragrunt-cache directories in the specified path. 18 | """ 19 | 20 | __author__ = "Assistant" 21 | __license__ = "GPL-2.0 license" 22 | 23 | import os 24 | import shutil 25 | 26 | 27 | def delete_directory(path): 28 | """Delete a directory and its contents.""" 29 | try: 30 | shutil.rmtree(path) 31 | print(f"Deleted: {path}") 32 | except Exception as e: 33 | print(f"Error deleting {path}: {e}") 34 | 35 | 36 | def find_and_delete_dirs(base): 37 | """Find and delete .terraform and .terragrunt-cache directories.""" 38 | for root, dirs, _ in os.walk(base, topdown=False): 39 | for dir_name in [".terraform", ".terragrunt-cache"]: 40 | if dir_name in dirs: 41 | path_to_delete = os.path.join(root, dir_name) 42 | delete_directory(path_to_delete) 43 | dirs.remove(dir_name) 44 | 45 | 46 | def main(): 47 | """Main function.""" 48 | base_directory = os.path.expanduser("~/Documents/repositories/") 49 | 50 | if not os.path.exists(base_directory): 51 | print(f"The specified directory does not exist: {base_directory}") 52 | return 53 | 54 | try: 55 | find_and_delete_dirs(base_directory) 56 | print("Finished searching and deleting .terraform and .terragrunt-cache directories.") 57 | except KeyboardInterrupt: 58 | print("\nScript interrupted by the user. Exiting.") 59 | 60 | 61 | if __name__ == "__main__": 62 | main() 63 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/traverser: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import configparser 4 | import os 5 | import re 6 | import subprocess 7 | import sys 8 | 9 | 10 | def get_all_kube_contexts(): 11 | """Get a list of all Kubernetes context names.""" 12 | try: 13 | result = subprocess.run( 14 | ["kubectl", "config", "get-contexts", "-o", "name"], 15 | capture_output=True, 16 | text=True, 17 | check=True, 18 | ) 19 | contexts = result.stdout.strip().split("\n") 20 | if not contexts or contexts == [""]: 21 | return [] 22 | return contexts 23 | except subprocess.CalledProcessError: 24 | return [] 25 | except FileNotFoundError: 26 | print("Error: 'kubectl' command not found.") 27 | sys.exit(1) 28 | 29 | 30 | def switch_kube_context(context_name): 31 | """Switch to the specified Kubernetes context.""" 32 | try: 33 | subprocess.run( 34 | ["kubectl", "config", "use-context", context_name], 35 | check=True, 36 | capture_output=True, 37 | text=True, 38 | ) 39 | return True 40 | except subprocess.CalledProcessError: 41 | return False 42 | 43 | 44 | def get_current_kube_context_info(): 45 | """Get the current Kubernetes context ARN and extract the account number.""" 46 | try: 47 | current_context_name = subprocess.check_output(["kubectl", "config", "current-context"]).decode().strip() 48 | 49 | match = re.search( 50 | r"arn:aws:eks:([\w-]+):(\d+):cluster/([\w-]+)", 51 | current_context_name, 52 | ) 53 | if match: 54 | return match.group(2) 55 | return None 56 | except subprocess.CalledProcessError: 57 | return None 58 | 59 | 60 | def parse_aws_config(): 61 | """Parse AWS config file.""" 62 | aws_config_path = os.path.expanduser("~/.aws/config") 63 | if not os.path.exists(aws_config_path): 64 | return None 65 | 66 | config = configparser.ConfigParser() 67 | config.read(aws_config_path) 68 | return config 69 | 70 | 71 | def find_profile_name(config, account_number): 72 | """Find the profile name by matching the account number.""" 73 | if not config or not account_number: 74 | return None 75 | for section in config.sections(): 76 | profile_section_match = re.match(r"profile\s+(.+)", section, re.IGNORECASE) 77 | if profile_section_match: 78 | profile_name_in_section = profile_section_match.group(1) 79 | if "role_arn" in config[section]: 80 | role_arn = config[section]["role_arn"] 81 | if f"::{account_number}:" in role_arn: 82 | return profile_name_in_section 83 | return None 84 | 85 | 86 | def execute_saml2aws_command(profile_name, command, max_attempts=2): 87 | """Execute the command with saml2aws credentials.""" 88 | attempt = 0 89 | 90 | while attempt < max_attempts: 91 | try: 92 | if attempt > 0: 93 | print(f"Attempting login (attempt {attempt}/{max_attempts})") 94 | subprocess.run( 95 | ["saml2aws", "login", "--profile", profile_name, "--skip-prompt"], check=True, timeout=30 96 | ) 97 | 98 | cmd_parts = command.split() 99 | process_env = dict(os.environ, AWS_PROFILE=profile_name) 100 | result = subprocess.run( 101 | cmd_parts, 102 | env=process_env, 103 | stdout=subprocess.PIPE, 104 | stderr=subprocess.STDOUT, 105 | text=True, 106 | check=False, 107 | ) 108 | 109 | return result.stdout.strip() if result.stdout else "" 110 | 111 | except subprocess.CalledProcessError as e: 112 | print(f"Command failed: {e}") 113 | except subprocess.TimeoutExpired: 114 | print("Login command timed out") 115 | except Exception as e: 116 | print(f"Error: {str(e)}") 117 | 118 | attempt += 1 119 | 120 | return "Failed to execute command after multiple attempts" 121 | 122 | 123 | def run_command_in_cluster(command): 124 | """Run the user-provided command in the current cluster.""" 125 | try: 126 | process = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 127 | stdout, stderr = process.communicate() 128 | 129 | if process.returncode != 0: 130 | return f"Command failed with exit code {process.returncode}:\n{stderr}" 131 | 132 | if stdout: 133 | return stdout 134 | elif stderr: 135 | return f"Command produced error: {stderr}" 136 | else: 137 | return "Command executed but produced no output." 138 | except Exception as e: 139 | return f"Error executing command: {str(e)}" 140 | 141 | 142 | def main(): 143 | if len(sys.argv) < 2: 144 | print("Usage: traverser 'command to execute'") 145 | exit(1) 146 | 147 | user_command = " ".join(sys.argv[1:]) 148 | print(f"Command to execute: {user_command}") 149 | 150 | aws_config = parse_aws_config() 151 | if aws_config is None: 152 | print("Could not parse AWS config. Exiting.") 153 | sys.exit(1) 154 | 155 | contexts = get_all_kube_contexts() 156 | if not contexts: 157 | print("No contexts found or error retrieving contexts. Exiting.") 158 | sys.exit(1) 159 | 160 | print(f"Found {len(contexts)} contexts") 161 | original_context = subprocess.check_output(["kubectl", "config", "current-context"]).decode().strip() 162 | 163 | for context_name in contexts: 164 | if not switch_kube_context(context_name): 165 | print(f"Failed to switch to context: {context_name}") 166 | continue 167 | 168 | print(f"[CONTEXT: {context_name}]") 169 | 170 | account_number = get_current_kube_context_info() 171 | if not account_number: 172 | print(f"Could not extract account number from context: {context_name}") 173 | continue 174 | 175 | profile_name = find_profile_name(aws_config, account_number) 176 | if not profile_name: 177 | print(f"No matching AWS profile found for account: {account_number}") 178 | continue 179 | 180 | output = execute_saml2aws_command(profile_name, user_command) 181 | print("COMMAND OUTPUT:") 182 | print(output) 183 | 184 | switch_kube_context(original_context) 185 | 186 | 187 | if __name__ == "__main__": 188 | try: 189 | main() 190 | except KeyboardInterrupt: 191 | print("\nOperation cancelled by the user. Exiting...") 192 | sys.exit(1) 193 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/bin/waybar-restart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Attempting to stop any running instance of waybar..." 4 | pkill waybar 5 | 6 | sleep 1 7 | 8 | if pgrep waybar >/dev/null 2>&1; then 9 | echo "Failed to stop waybar." >&2 10 | else 11 | echo "Waybar stopped successfully." 12 | echo "Starting waybar..." 13 | waybar &>/dev/null & 14 | disown 15 | echo "Waybar restarted successfully." 16 | fi 17 | -------------------------------------------------------------------------------- /modules/home-manager/scripts/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: { 6 | # Source scripts from the home-manager store 7 | home.file = { 8 | ".local/bin" = { 9 | recursive = true; 10 | source = ./bin; 11 | }; 12 | }; 13 | 14 | # Conditional configuration for Darwin systems 15 | home.sessionPath = lib.mkMerge [ 16 | (lib.mkIf pkgs.stdenv.isDarwin [ 17 | "$HOME/.local/bin" 18 | ]) 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /modules/home-manager/services/cliphist/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install cliphist via home-manager module 3 | services.cliphist = { 4 | enable = true; 5 | systemdTargets = "hyprland-session.target"; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /modules/home-manager/services/easyeffects/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | ... 5 | }: { 6 | config = lib.mkIf (!pkgs.stdenv.isDarwin) { 7 | # Install easyeffects via home-manager module 8 | services.easyeffects = { 9 | enable = true; 10 | preset = "mic"; 11 | }; 12 | 13 | # Source easyeffects preset from the home-manager store 14 | xdg.configFile = { 15 | "easyeffects/input/mic.json".text = '' 16 | { 17 | "input": { 18 | "blocklist": [], 19 | "compressor#0": { 20 | "attack": 2.0, 21 | "boost-amount": 6.0, 22 | "boost-threshold": -72.0, 23 | "bypass": false, 24 | "dry": -100.0, 25 | "hpf-frequency": 10.0, 26 | "hpf-mode": "off", 27 | "input-gain": 9.0, 28 | "knee": -6.0, 29 | "lpf-frequency": 20000.0, 30 | "lpf-mode": "off", 31 | "makeup": 0.0, 32 | "mode": "Downward", 33 | "output-gain": 0.0, 34 | "ratio": 4.0, 35 | "release": 200.0, 36 | "release-threshold": -40.0, 37 | "sidechain": { 38 | "lookahead": 0.0, 39 | "mode": "RMS", 40 | "preamp": 0.0, 41 | "reactivity": 10.0, 42 | "source": "Middle", 43 | "stereo-split-source": "Left/Right", 44 | "type": "Feed-forward" 45 | }, 46 | "stereo-split": false, 47 | "threshold": -16.0, 48 | "wet": 0.0 49 | }, 50 | "limiter#0": { 51 | "alr": false, 52 | "alr-attack": 5.0, 53 | "alr-knee": 0.0, 54 | "alr-release": 50.0, 55 | "attack": 1.0, 56 | "bypass": false, 57 | "dithering": "16bit", 58 | "external-sidechain": false, 59 | "gain-boost": false, 60 | "input-gain": 0.0, 61 | "lookahead": 5.0, 62 | "mode": "Herm Wide", 63 | "output-gain": 0.0, 64 | "oversampling": "Half x2(2L)", 65 | "release": 20.0, 66 | "sidechain-preamp": 0.0, 67 | "stereo-link": 100.0, 68 | "threshold": -3.0 69 | }, 70 | "plugins_order": [ 71 | "rnnoise#0", 72 | "compressor#0", 73 | "limiter#0" 74 | ], 75 | "rnnoise#0": { 76 | "bypass": false, 77 | "enable-vad": true, 78 | "input-gain": 0.0, 79 | "model-path": "", 80 | "output-gain": 0.0, 81 | "release": 20.0, 82 | "vad-thres": 50.0, 83 | "wet": 0.0 84 | } 85 | } 86 | } 87 | ''; 88 | }; 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /modules/home-manager/services/flatpak/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | pkgs, 4 | config, 5 | ... 6 | }: { 7 | imports = [inputs.nix-flatpak.homeManagerModules.nix-flatpak]; 8 | 9 | services.flatpak = { 10 | enable = true; 11 | packages = ["us.zoom.Zoom"]; 12 | uninstallUnmanaged = true; 13 | update.auto.enable = false; 14 | }; 15 | 16 | home.packages = [pkgs.flatpak]; 17 | 18 | xdg.systemDirs.data = [ 19 | "/var/lib/flatpak/exports/share" 20 | "${config.home.homeDirectory}/.local/share/flatpak/exports/share" 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /modules/home-manager/services/kanshi/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Manage kanshi services via Home-manager 3 | services.kanshi = { 4 | enable = true; 5 | systemdTarget = "graphical-session.target"; 6 | settings = [ 7 | { 8 | profile.name = "docked"; 9 | profile.outputs = [ 10 | { 11 | criteria = "DP-1"; 12 | status = "enable"; 13 | position = "0,0"; 14 | } 15 | { 16 | criteria = "eDP-1"; 17 | status = "disable"; 18 | } 19 | ]; 20 | } 21 | { 22 | profile.name = "undocked"; 23 | profile.outputs = [ 24 | { 25 | criteria = "eDP-1"; 26 | status = "enable"; 27 | position = "0,0"; 28 | } 29 | ]; 30 | } 31 | ]; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /modules/home-manager/services/swaync/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install swaync via home-manager module 3 | services.swaync = { 4 | enable = true; 5 | }; 6 | 7 | # Source swaync config from the home-manager store 8 | xdg.configFile = { 9 | "swaync/style.css" = { 10 | source = ./style.css; 11 | }; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /modules/home-manager/services/swaync/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | all: unset; 3 | font-size: 14px; 4 | font-family: "Roboto Nerd Font"; 5 | transition: 200ms; 6 | } 7 | 8 | trough highlight { 9 | background: #cad3f5; 10 | } 11 | 12 | scale trough { 13 | margin: 0rem 1rem; 14 | background-color: #363a4f; 15 | min-height: 8px; 16 | min-width: 70px; 17 | } 18 | 19 | slider { 20 | background-color: #8aadf4; 21 | } 22 | 23 | .floating-notifications.background .notification-row .notification-background { 24 | box-shadow: 25 | 0 0 8px 0 rgba(0, 0, 0, 0.8), 26 | inset 0 0 0 1px #363a4f; 27 | border-radius: 8px; 28 | margin: 18px; 29 | background-color: #24273a; 30 | color: #cad3f5; 31 | padding: 0; 32 | } 33 | 34 | .floating-notifications.background 35 | .notification-row 36 | .notification-background 37 | .notification { 38 | padding: 7px; 39 | border-radius: 8px; 40 | } 41 | 42 | .floating-notifications.background 43 | .notification-row 44 | .notification-background 45 | .notification.critical { 46 | box-shadow: inset 0 0 7px 0 #ed8796; 47 | } 48 | 49 | .floating-notifications.background 50 | .notification-row 51 | .notification-background 52 | .notification 53 | .notification-content { 54 | margin: 7px; 55 | } 56 | 57 | .floating-notifications.background 58 | .notification-row 59 | .notification-background 60 | .notification 61 | .notification-content 62 | .summary { 63 | color: #cad3f5; 64 | } 65 | 66 | .floating-notifications.background 67 | .notification-row 68 | .notification-background 69 | .notification 70 | .notification-content 71 | .time { 72 | color: #a5adcb; 73 | } 74 | 75 | .floating-notifications.background 76 | .notification-row 77 | .notification-background 78 | .notification 79 | .notification-content 80 | .body { 81 | color: #cad3f5; 82 | } 83 | 84 | .floating-notifications.background 85 | .notification-row 86 | .notification-background 87 | .notification 88 | > *:last-child 89 | > * { 90 | min-height: 3.4em; 91 | } 92 | 93 | .floating-notifications.background 94 | .notification-row 95 | .notification-background 96 | .notification 97 | > *:last-child 98 | > * 99 | .notification-action { 100 | border-radius: 8px; 101 | color: #cad3f5; 102 | background-color: #363a4f; 103 | box-shadow: inset 0 0 0 1px #494d64; 104 | margin: 7px; 105 | } 106 | 107 | .floating-notifications.background 108 | .notification-row 109 | .notification-background 110 | .notification 111 | > *:last-child 112 | > * 113 | .notification-action:hover { 114 | box-shadow: inset 0 0 0 1px #494d64; 115 | background-color: #363a4f; 116 | color: #cad3f5; 117 | } 118 | 119 | .floating-notifications.background 120 | .notification-row 121 | .notification-background 122 | .notification 123 | > *:last-child 124 | > * 125 | .notification-action:active { 126 | box-shadow: inset 0 0 0 1px #494d64; 127 | background-color: #7dc4e4; 128 | color: #cad3f5; 129 | } 130 | 131 | .floating-notifications.background 132 | .notification-row 133 | .notification-background 134 | .close-button { 135 | margin: 7px; 136 | padding: 2px; 137 | border-radius: 8px; 138 | color: #24273a; 139 | background-color: #ed8796; 140 | } 141 | 142 | .floating-notifications.background 143 | .notification-row 144 | .notification-background 145 | .close-button:hover { 146 | background-color: #ee99a0; 147 | color: #24273a; 148 | } 149 | 150 | .floating-notifications.background 151 | .notification-row 152 | .notification-background 153 | .close-button:active { 154 | background-color: #ed8796; 155 | color: #24273a; 156 | } 157 | 158 | .control-center { 159 | box-shadow: 160 | 0 0 8px 0 rgba(0, 0, 0, 0.8), 161 | inset 0 0 0 1px #363a4f; 162 | border-radius: 8px; 163 | margin: 18px; 164 | background-color: #24273a; 165 | color: #cad3f5; 166 | padding: 14px; 167 | } 168 | 169 | .control-center .widget-title > label { 170 | color: #cad3f5; 171 | font-size: 1.3em; 172 | } 173 | 174 | .control-center .widget-title button { 175 | border-radius: 8px; 176 | color: #cad3f5; 177 | background-color: #363a4f; 178 | box-shadow: inset 0 0 0 1px #494d64; 179 | padding: 8px; 180 | } 181 | 182 | .control-center .widget-title button:hover { 183 | box-shadow: inset 0 0 0 1px #494d64; 184 | background-color: #5b6078; 185 | color: #cad3f5; 186 | } 187 | 188 | .control-center .widget-title button:active { 189 | box-shadow: inset 0 0 0 1px #494d64; 190 | background-color: #7dc4e4; 191 | color: #24273a; 192 | } 193 | 194 | .control-center .notification-row .notification-background { 195 | border-radius: 8px; 196 | color: #cad3f5; 197 | background-color: #363a4f; 198 | box-shadow: inset 0 0 0 1px #494d64; 199 | margin-top: 14px; 200 | } 201 | 202 | .control-center .notification-row .notification-background .notification { 203 | padding: 7px; 204 | border-radius: 8px; 205 | } 206 | 207 | .control-center 208 | .notification-row 209 | .notification-background 210 | .notification.critical { 211 | box-shadow: inset 0 0 7px 0 #ed8796; 212 | } 213 | 214 | .control-center 215 | .notification-row 216 | .notification-background 217 | .notification 218 | .notification-content { 219 | margin: 7px; 220 | } 221 | 222 | .control-center 223 | .notification-row 224 | .notification-background 225 | .notification 226 | .notification-content 227 | .summary { 228 | color: #cad3f5; 229 | } 230 | 231 | .control-center 232 | .notification-row 233 | .notification-background 234 | .notification 235 | .notification-content 236 | .time { 237 | color: #a5adcb; 238 | } 239 | 240 | .control-center 241 | .notification-row 242 | .notification-background 243 | .notification 244 | .notification-content 245 | .body { 246 | color: #cad3f5; 247 | } 248 | 249 | .control-center 250 | .notification-row 251 | .notification-background 252 | .notification 253 | > *:last-child 254 | > * { 255 | min-height: 3.4em; 256 | } 257 | 258 | .control-center 259 | .notification-row 260 | .notification-background 261 | .notification 262 | > *:last-child 263 | > * 264 | .notification-action { 265 | border-radius: 8px; 266 | color: #cad3f5; 267 | background-color: #181926; 268 | box-shadow: inset 0 0 0 1px #494d64; 269 | margin: 7px; 270 | } 271 | 272 | .control-center 273 | .notification-row 274 | .notification-background 275 | .notification 276 | > *:last-child 277 | > * 278 | .notification-action:hover { 279 | box-shadow: inset 0 0 0 1px #494d64; 280 | background-color: #363a4f; 281 | color: #cad3f5; 282 | } 283 | 284 | .control-center 285 | .notification-row 286 | .notification-background 287 | .notification 288 | > *:last-child 289 | > * 290 | .notification-action:active { 291 | box-shadow: inset 0 0 0 1px #494d64; 292 | background-color: #7dc4e4; 293 | color: #cad3f5; 294 | } 295 | 296 | .control-center .notification-row .notification-background .close-button { 297 | margin: 7px; 298 | padding: 2px; 299 | border-radius: 8px; 300 | color: #24273a; 301 | background-color: #ee99a0; 302 | } 303 | 304 | .close-button { 305 | border-radius: 8px; 306 | } 307 | 308 | .control-center .notification-row .notification-background .close-button:hover { 309 | background-color: #ed8796; 310 | color: #24273a; 311 | } 312 | 313 | .control-center 314 | .notification-row 315 | .notification-background 316 | .close-button:active { 317 | background-color: #ed8796; 318 | color: #24273a; 319 | } 320 | 321 | .control-center .notification-row .notification-background:hover { 322 | box-shadow: inset 0 0 0 1px #494d64; 323 | background-color: #8087a2; 324 | color: #cad3f5; 325 | } 326 | 327 | .control-center .notification-row .notification-background:active { 328 | box-shadow: inset 0 0 0 1px #494d64; 329 | background-color: #7dc4e4; 330 | color: #cad3f5; 331 | } 332 | 333 | .notification.critical progress { 334 | background-color: #ed8796; 335 | } 336 | 337 | .notification.low progress, 338 | .notification.normal progress { 339 | background-color: #8aadf4; 340 | } 341 | 342 | .control-center-dnd { 343 | margin-top: 5px; 344 | border-radius: 8px; 345 | background: #363a4f; 346 | border: 1px solid #494d64; 347 | box-shadow: none; 348 | } 349 | 350 | .control-center-dnd:checked { 351 | background: #363a4f; 352 | } 353 | 354 | .control-center-dnd slider { 355 | background: #494d64; 356 | border-radius: 8px; 357 | } 358 | 359 | .widget-dnd { 360 | margin: 0px; 361 | font-size: 1.1rem; 362 | } 363 | 364 | .widget-dnd > switch { 365 | font-size: initial; 366 | border-radius: 8px; 367 | background: #363a4f; 368 | border: 1px solid #494d64; 369 | box-shadow: none; 370 | } 371 | 372 | .widget-dnd > switch:checked { 373 | background: #363a4f; 374 | } 375 | 376 | .widget-dnd > switch slider { 377 | background: #494d64; 378 | border-radius: 8px; 379 | border: 1px solid #6e738d; 380 | } 381 | 382 | .widget-mpris .widget-mpris-player { 383 | background: #363a4f; 384 | padding: 7px; 385 | } 386 | 387 | .widget-mpris .widget-mpris-title { 388 | font-size: 1.2rem; 389 | } 390 | 391 | .widget-mpris .widget-mpris-subtitle { 392 | font-size: 0.8rem; 393 | } 394 | 395 | .widget-menubar > box > .menu-button-bar > button > label { 396 | font-size: 3rem; 397 | padding: 0.5rem 2rem; 398 | } 399 | 400 | .widget-menubar > box > .menu-button-bar > :last-child { 401 | color: #ed8796; 402 | } 403 | 404 | .power-buttons button:hover, 405 | .powermode-buttons button:hover, 406 | .screenshot-buttons button:hover { 407 | background: #363a4f; 408 | } 409 | 410 | .control-center .widget-label > label { 411 | color: #cad3f5; 412 | font-size: 2rem; 413 | } 414 | 415 | .widget-buttons-grid { 416 | padding-top: 1rem; 417 | } 418 | 419 | .widget-buttons-grid > flowbox > flowboxchild > button label { 420 | font-size: 2.5rem; 421 | } 422 | 423 | .widget-volume { 424 | padding-top: 1rem; 425 | } 426 | 427 | .widget-volume label { 428 | font-size: 1.5rem; 429 | color: #7dc4e4; 430 | } 431 | 432 | .widget-volume trough highlight { 433 | background: #7dc4e4; 434 | } 435 | 436 | .widget-backlight trough highlight { 437 | background: #eed49f; 438 | } 439 | 440 | .widget-backlight scale { 441 | margin-right: 1rem; 442 | } 443 | 444 | .widget-backlight label { 445 | font-size: 1.5rem; 446 | color: #eed49f; 447 | } 448 | 449 | .widget-backlight .KB { 450 | padding-bottom: 1rem; 451 | } 452 | 453 | .image { 454 | padding-right: 0.5rem; 455 | } 456 | -------------------------------------------------------------------------------- /modules/home-manager/services/waybar/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Install and configure waybar via home-manager module 3 | programs.waybar = { 4 | enable = true; 5 | settings = { 6 | mainBar = { 7 | layer = "top"; 8 | position = "top"; 9 | exclusive = true; 10 | passthrough = false; 11 | fixed-center = true; 12 | ipc = true; 13 | margin-top = 3; 14 | margin-left = 4; 15 | margin-right = 4; 16 | 17 | modules-left = [ 18 | "hyprland/workspaces" 19 | "cpu" 20 | "temperature" 21 | "memory" 22 | "backlight" 23 | ]; 24 | 25 | modules-center = [ 26 | "clock" 27 | "custom/notification" 28 | ]; 29 | 30 | modules-right = [ 31 | "privacy" 32 | "custom/recorder" 33 | "hyprland/language" 34 | "tray" 35 | "bluetooth" 36 | "pulseaudio" 37 | "pulseaudio#microphone" 38 | "battery" 39 | ]; 40 | 41 | backlight = { 42 | interval = 2; 43 | align = 0; 44 | rotate = 0; 45 | format = "{icon} {percent}%"; 46 | format-icons = ["󰃞" "󰃟" "󰃝" "󰃠"]; 47 | icon-size = 10; 48 | on-scroll-up = "brightnessctl set +5%"; 49 | on-scroll-down = "brightnessctl set 5%-"; 50 | smooth-scrolling-threshold = 1; 51 | }; 52 | 53 | battery = { 54 | interval = 60; 55 | align = 0; 56 | rotate = 0; 57 | full-at = 100; 58 | design-capacity = false; 59 | states = { 60 | good = 95; 61 | warning = 30; 62 | critical = 20; 63 | }; 64 | format = "{icon} {capacity}%"; 65 | format-charging = " {capacity}%"; 66 | format-plugged = " {capacity}%"; 67 | format-full = "{icon} Full"; 68 | format-alt = "{icon} {time}"; 69 | format-icons = [ 70 | "" 71 | "" 72 | "" 73 | "" 74 | "" 75 | ]; 76 | format-time = "{H}h {M}min"; 77 | tooltip = true; 78 | tooltip-format = "{timeTo} {power}w"; 79 | }; 80 | 81 | bluetooth = { 82 | format = ""; 83 | format-connected = " {num_connections}"; 84 | tooltip-format = " {device_alias}"; 85 | tooltip-format-connected = "{device_enumerate}"; 86 | tooltip-format-enumerate-connected = "Name: {device_alias}\nBattery: {device_battery_percentage}%"; 87 | on-click = "blueman-manager"; 88 | }; 89 | 90 | clock = { 91 | format = "{:%b %d %H:%M}"; 92 | format-alt = " {:%H:%M  %Y, %d %B, %A}"; 93 | tooltip-format = "{calendar}"; 94 | calendar = { 95 | mode = "year"; 96 | mode-mon-col = 3; 97 | weeks-pos = "right"; 98 | on-scroll = 1; 99 | format = { 100 | months = "{}"; 101 | days = "{}"; 102 | weeks = "W{}"; 103 | weekdays = "{}"; 104 | today = "{}"; 105 | }; 106 | }; 107 | }; 108 | 109 | cpu = { 110 | format = "󰍛 {usage}%"; 111 | interval = 1; 112 | }; 113 | 114 | "hyprland/language" = { 115 | format = "{short}"; 116 | }; 117 | 118 | "hyprland/workspaces" = { 119 | all-outputs = true; 120 | format = "{name}"; 121 | on-click = "activate"; 122 | show-special = false; 123 | sort-by-number = true; 124 | }; 125 | 126 | memory = { 127 | interval = 10; 128 | format = "󰾆 {used:0.1f}G"; 129 | format-alt = "󰾆 {percentage}%"; 130 | format-alt-click = "click"; 131 | tooltip = true; 132 | tooltip-format = "{used:0.1f}GB/{total:0.1f}G"; 133 | on-click-right = "foot --title btop sh -c 'btop'"; 134 | }; 135 | 136 | privacy = { 137 | icon-size = 14; 138 | modules = [ 139 | { 140 | type = "screenshare"; 141 | tooltip = true; 142 | } 143 | ]; 144 | }; 145 | 146 | pulseaudio = { 147 | format = "{icon} {volume}%"; 148 | format-muted = ""; 149 | format-icons = { 150 | default = [ 151 | "" 152 | "" 153 | " " 154 | ]; 155 | }; 156 | on-click = "pavucontrol"; 157 | on-scroll-up = "pamixer -i 5"; 158 | on-scroll-down = "pamixer -d 5"; 159 | scroll-step = 5; 160 | on-click-right = "pamixer -t"; 161 | smooth-scrolling-threshold = 1; 162 | ignored-sinks = ["Easy Effects Sink"]; 163 | }; 164 | 165 | "pulseaudio#microphone" = { 166 | format = "{format_source}"; 167 | format-source = " {volume}%"; 168 | format-source-muted = ""; 169 | on-click = "pavucontrol"; 170 | on-click-right = "pamixer --default-source -t"; 171 | on-scroll-up = "pamixer --default-source -i 5"; 172 | on-scroll-down = "pamixer --default-source -d 5"; 173 | }; 174 | 175 | temperature = { 176 | interval = 10; 177 | tooltip = false; 178 | hwmon-path = "/sys/class/hwmon/hwmon1/temp1_input"; 179 | critical-threshold = 82; 180 | format-critical = "{icon} {temperatureC}°C"; 181 | format = "󰈸 {temperatureC}°C"; 182 | }; 183 | 184 | tray = { 185 | spacing = 20; 186 | }; 187 | 188 | "custom/notification" = { 189 | tooltip = false; 190 | format = "{icon}"; 191 | format-icons = { 192 | notification = ""; 193 | none = ""; 194 | dnd-notification = ""; 195 | dnd-none = ""; 196 | inhibited-notification = ""; 197 | inhibited-none = ""; 198 | dnd-inhibited-notification = ""; 199 | dnd-inhibited-none = ""; 200 | }; 201 | return-type = "json"; 202 | exec-if = "which swaync-client"; 203 | exec = "swaync-client -swb"; 204 | on-click = "swaync-client -t -sw"; 205 | on-click-right = "swaync-client -d -sw"; 206 | escape = true; 207 | }; 208 | 209 | "custom/recorder" = { 210 | format = ""; 211 | tooltip = false; 212 | return-type = "json"; 213 | exec = "echo '{\"class\": \"recording\"}'"; 214 | exec-if = "pgrep wf-recorder"; 215 | interval = 1; 216 | on-click = "screen-recorder"; 217 | }; 218 | }; 219 | }; 220 | style = '' 221 | * { 222 | font-family: "JetBrainsMono Nerd Font"; 223 | font-weight: bold; 224 | min-height: 0; 225 | font-size: 100%; 226 | font-feature-settings: '"zero", "ss01", "ss02", "ss03", "ss04", "ss05", "cv31"'; 227 | padding: 0px; 228 | margin-top: 1px; 229 | margin-bottom: 1px; 230 | } 231 | 232 | window#waybar { 233 | background: rgba(0, 0, 0, 0); 234 | } 235 | 236 | window#waybar.hidden { 237 | opacity: 0.5; 238 | } 239 | 240 | tooltip { 241 | background: #24273A; 242 | border-radius: 8px; 243 | } 244 | 245 | tooltip label { 246 | color: #cad3f5; 247 | margin-right: 5px; 248 | margin-left: 5px; 249 | } 250 | 251 | .modules-right, 252 | .modules-center, 253 | .modules-left { 254 | background-color: rgba(0, 0, 0, 0.6); 255 | border: 0px solid #b4befe; 256 | border-radius: 8px; 257 | } 258 | 259 | #workspaces button { 260 | padding: 2px; 261 | color: #6e738d; 262 | margin-right: 5px; 263 | } 264 | 265 | #workspaces button.active { 266 | color: #dfdfdf; 267 | border-radius: 3px 3px 3px 3px; 268 | } 269 | 270 | #workspaces button.focused { 271 | color: #d8dee9; 272 | } 273 | 274 | #workspaces button.urgent { 275 | color: #ed8796; 276 | border-radius: 8px; 277 | } 278 | 279 | #workspaces button:hover { 280 | color: #dfdfdf; 281 | border-radius: 3px; 282 | } 283 | 284 | #backlight, 285 | #battery, 286 | #bluetooth, 287 | #clock, 288 | #cpu, 289 | #custom-notification, 290 | #custom-recorder, 291 | #language, 292 | #memory, 293 | #privacy, 294 | #pulseaudio, 295 | #temperature, 296 | #tray, 297 | #workspaces { 298 | color: #dfdfdf; 299 | padding: 0px 10px; 300 | border-radius: 8px; 301 | } 302 | 303 | #temperature.critical { 304 | background-color: #ff0000; 305 | } 306 | 307 | @keyframes blink { 308 | to { 309 | color: #000000; 310 | } 311 | } 312 | 313 | #taskbar button.active { 314 | background-color: #7f849c; 315 | } 316 | 317 | #battery.critical:not(.charging) { 318 | color: #f53c3c; 319 | animation-name: blink; 320 | animation-duration: 0.5s; 321 | animation-timing-function: linear; 322 | animation-iteration-count: infinite; 323 | animation-direction: alternate; 324 | } 325 | 326 | #custom-recorder { 327 | color: #ff2800; 328 | } 329 | 330 | #privacy { 331 | color: #f5a97f; 332 | } 333 | ''; 334 | }; 335 | } 336 | -------------------------------------------------------------------------------- /modules/nixos/common/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | outputs, 4 | lib, 5 | config, 6 | userConfig, 7 | pkgs, 8 | ... 9 | }: { 10 | # Nixpkgs configuration 11 | nixpkgs = { 12 | overlays = [ 13 | outputs.overlays.stable-packages 14 | ]; 15 | 16 | config = { 17 | allowUnfree = true; 18 | }; 19 | }; 20 | 21 | # Register flake inputs for nix commands 22 | nix.registry = lib.mapAttrs (_: flake: {inherit flake;}) (lib.filterAttrs (_: lib.isType "flake") inputs); 23 | 24 | # Add inputs to legacy channels 25 | nix.nixPath = ["/etc/nix/path"]; 26 | environment.etc = 27 | lib.mapAttrs' (name: value: { 28 | name = "nix/path/${name}"; 29 | value.source = value.flake; 30 | }) 31 | config.nix.registry; 32 | 33 | # Nix settings 34 | nix.settings = { 35 | experimental-features = "nix-command flakes"; 36 | auto-optimise-store = true; 37 | }; 38 | 39 | # Boot settings 40 | boot = { 41 | kernelPackages = pkgs.linuxKernel.packages.linux_6_14; 42 | consoleLogLevel = 0; 43 | initrd.verbose = false; 44 | kernelParams = ["quiet" "splash"]; 45 | loader.efi.canTouchEfiVariables = true; 46 | loader.systemd-boot.enable = true; 47 | loader.timeout = 0; 48 | plymouth.enable = true; 49 | 50 | # v4l (virtual camera) module settings 51 | kernelModules = ["v4l2loopback"]; 52 | extraModulePackages = with config.boot.kernelPackages; [ 53 | v4l2loopback 54 | ]; 55 | extraModprobeConfig = '' 56 | options v4l2loopback exclusive_caps=1 card_label="Virtual Camera" 57 | ''; 58 | }; 59 | 60 | # Networking 61 | networking.networkmanager.enable = true; 62 | 63 | # Disable systemd services that are affecting the boot time 64 | systemd.services = { 65 | NetworkManager-wait-online.enable = false; 66 | plymouth-quit-wait.enable = false; 67 | }; 68 | 69 | # Timezone 70 | time.timeZone = "Europe/Warsaw"; 71 | 72 | # Internationalization 73 | i18n.defaultLocale = "en_US.UTF-8"; 74 | i18n.extraLocaleSettings = { 75 | LC_ADDRESS = "en_IE.UTF-8"; 76 | LC_IDENTIFICATION = "en_IE.UTF-8"; 77 | LC_MEASUREMENT = "en_IE.UTF-8"; 78 | LC_MONETARY = "en_IE.UTF-8"; 79 | LC_NAME = "en_IE.UTF-8"; 80 | LC_NUMERIC = "en_IE.UTF-8"; 81 | LC_PAPER = "en_IE.UTF-8"; 82 | LC_TELEPHONE = "en_IE.UTF-8"; 83 | LC_TIME = "en_IE.UTF-8"; 84 | }; 85 | 86 | # Input settings 87 | services.libinput.enable = true; 88 | 89 | # xserver settings 90 | services.xserver = { 91 | enable = true; 92 | xkb.layout = "pl"; 93 | xkb.variant = ""; 94 | excludePackages = with pkgs; [xterm]; 95 | displayManager.gdm.enable = true; 96 | }; 97 | 98 | # Enable Wayland support in Chromium and Electron based applications 99 | # Remove decorations for QT apps 100 | # Set cursor size 101 | environment.sessionVariables = { 102 | NIXOS_OZONE_WL = "1"; 103 | QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; 104 | XCURSOR_SIZE = "24"; 105 | }; 106 | 107 | # PATH configuration 108 | environment.localBinInPath = true; 109 | 110 | # Disable CUPS printing 111 | services.printing.enable = false; 112 | 113 | # Enable devmon for device management 114 | services.devmon.enable = true; 115 | 116 | # Enable PipeWire for sound 117 | services.pulseaudio.enable = false; 118 | security.rtkit.enable = true; 119 | services.pipewire = { 120 | enable = true; 121 | alsa.enable = true; 122 | alsa.support32Bit = true; 123 | pulse.enable = true; 124 | jack.enable = true; 125 | }; 126 | 127 | # Enable flatpak service 128 | services.flatpak.enable = true; 129 | 130 | # User configuration 131 | users.users.${userConfig.name} = { 132 | description = userConfig.fullName; 133 | extraGroups = ["networkmanager" "wheel" "docker"]; 134 | isNormalUser = true; 135 | shell = pkgs.zsh; 136 | }; 137 | 138 | # Set User's avatar 139 | system.activationScripts.script.text = '' 140 | mkdir -p /var/lib/AccountsService/{icons,users} 141 | cp ${userConfig.avatar} /var/lib/AccountsService/icons/${userConfig.name} 142 | 143 | touch /var/lib/AccountsService/users/${userConfig.name} 144 | 145 | if ! grep -q "^Icon=" /var/lib/AccountsService/users/${userConfig.name}; then 146 | if ! grep -q "^\[User\]" /var/lib/AccountsService/users/${userConfig.name}; then 147 | echo "[User]" >> /var/lib/AccountsService/users/${userConfig.name} 148 | fi 149 | echo "Icon=/var/lib/AccountsService/icons/${userConfig.name}" >> /var/lib/AccountsService/users/${userConfig.name} 150 | fi 151 | ''; 152 | 153 | # Passwordless sudo 154 | security.sudo.wheelNeedsPassword = false; 155 | 156 | # System packages 157 | environment.systemPackages = with pkgs; [ 158 | gcc 159 | glib 160 | gnumake 161 | killall 162 | mesa 163 | ]; 164 | 165 | # Docker configuration 166 | virtualisation.docker.enable = true; 167 | virtualisation.docker.rootless.enable = true; 168 | virtualisation.docker.rootless.setSocketVariable = true; 169 | 170 | # Zsh configuration 171 | programs.zsh.enable = true; 172 | 173 | # Fonts configuration 174 | fonts.packages = with pkgs; [ 175 | nerd-fonts.jetbrains-mono 176 | nerd-fonts.meslo-lg 177 | roboto 178 | ]; 179 | 180 | # Additional services 181 | services.locate.enable = true; 182 | 183 | # OpenSSH daemon 184 | services.openssh.enable = true; 185 | } 186 | -------------------------------------------------------------------------------- /modules/nixos/desktop/hyprland/default.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | # Call dbus-update-activation-environment on login 3 | services.xserver.updateDbusEnvironment = true; 4 | 5 | # Enables support for Bluetooth 6 | hardware.bluetooth = { 7 | enable = true; 8 | powerOnBoot = true; 9 | }; 10 | 11 | # Enable Bluetooth support 12 | services.blueman.enable = true; 13 | 14 | # Enable Hyprland 15 | programs.hyprland = { 16 | enable = true; 17 | }; 18 | 19 | # Enable security services 20 | services.gnome.gnome-keyring.enable = true; 21 | security.polkit.enable = true; 22 | security.pam.services = { 23 | hyprlock = {}; 24 | gdm.enableGnomeKeyring = true; 25 | }; 26 | 27 | # List of Hyprland specific packages 28 | environment.systemPackages = with pkgs; [ 29 | file-roller # archive manager 30 | gnome-calculator 31 | gnome-pomodoro 32 | gnome-text-editor 33 | loupe # image viewer 34 | nautilus # file manager 35 | seahorse # keyring manager 36 | totem # Video player 37 | 38 | brightnessctl 39 | grim 40 | hypridle 41 | hyprlock 42 | hyprpaper 43 | hyprpicker 44 | libnotify 45 | networkmanagerapplet 46 | pamixer 47 | slurp 48 | wf-recorder 49 | wlr-randr 50 | wlsunset 51 | ]; 52 | } 53 | -------------------------------------------------------------------------------- /modules/nixos/programs/steam/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Steam gaming platform configuration 3 | programs.steam = { 4 | enable = true; 5 | remotePlay.openFirewall = true; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /modules/nixos/services/tlp/default.nix: -------------------------------------------------------------------------------- 1 | {...}: { 2 | # Set TLP power profile 3 | services = { 4 | tlp = { 5 | enable = true; 6 | settings = { 7 | CPU_SCALING_GOVERNOR_ON_AC = "schedutil"; 8 | CPU_SCALING_GOVERNOR_ON_BAT = "schedutil"; 9 | 10 | CPU_ENERGY_PERF_POLICY_ON_AC = "balance_power"; 11 | CPU_ENERGY_PERF_POLICY_ON_BAT = "balance_power"; 12 | 13 | PLATFORM_PROFILE_ON_AC = "low-power"; 14 | PLATFORM_PROFILE_ON_BAT = "low-power"; 15 | 16 | USB_EXCLUDE_BTUSB = 1; 17 | 18 | RADEON_DPM_PERF_LEVEL_ON_AC = "auto"; 19 | RADEON_DPM_PERF_LEVEL_ON_BAT = "auto"; 20 | 21 | DISK_IOSCHED = ["none"]; 22 | 23 | # Battery charge thresholds for on-road usage 24 | START_CHARGE_THRESH_BAT0 = 85; 25 | STOP_CHARGE_THRESH_BAT0 = 90; 26 | }; 27 | }; 28 | power-profiles-daemon = { 29 | enable = false; 30 | }; 31 | }; 32 | 33 | # Disable fingerprint reader 34 | services.fprintd.enable = false; 35 | } 36 | -------------------------------------------------------------------------------- /overlays/default.nix: -------------------------------------------------------------------------------- 1 | {inputs, ...}: { 2 | # When applied, the stable nixpkgs set (declared in the flake inputs) will 3 | # be accessible through 'pkgs.stable' 4 | stable-packages = final: _prev: { 5 | stable = import inputs.nixpkgs-stable { 6 | system = final.system; 7 | config.allowUnfree = true; 8 | }; 9 | }; 10 | } 11 | --------------------------------------------------------------------------------