forked from jan-leila/nix-config
		
	main #5
					 62 changed files with 1582 additions and 894 deletions
				
			
		
							
								
								
									
										30
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								README.md
									
										
									
									
									
								
							|  | @ -41,30 +41,32 @@ nix multi user, multi system, configuration with `sops` secret management, `home | |||
| 
 | ||||
| ## Research topics | ||||
| - Look into this for auto rotating sops keys `https://technotim.live/posts/rotate-sops-encryption-keys/` | ||||
| - Look into this for flake templates https://nix.dev/manual/nix/2.22/command-ref/new-cli/nix3-flake-init | ||||
| - Look into this for npins https://jade.fyi/blog/pinning-nixos-with-npins/ | ||||
| - https://nixos-and-flakes.thiscute.world/ | ||||
| - nix config mcp https://github.com/utensils/mcp-nixos | ||||
| 
 | ||||
| # Tasks: | ||||
| 
 | ||||
| ## Tech Debt | ||||
| - monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) | ||||
| - syncthing folder passwords | ||||
| - nfs export should be backed by the same values for server and client | ||||
| ## New Features | ||||
| - offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) | ||||
| - samba mounts | ||||
| - crab-hole | ||||
| - figure out why syncthing and jellyfins permissions don't propagate downwards | ||||
| - figure out steam vr things? | ||||
| - Open GL? | ||||
| - rotate sops encryption keys periodically (and somehow sync between devices?) | ||||
| - auto turn off on power loss - nut | ||||
| - zfs email after scrubbing # TODO: test this | ||||
| - wake on LAN for updates | ||||
| - ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix | ||||
| - SMART test with email results | ||||
| - fix nfs | ||||
| - samba mounts | ||||
| - offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) | ||||
| - Create Tor guard/relay server | ||||
| - migrate away from flakes and move to npins | ||||
| - whisper | ||||
| - nix mcp | ||||
| - zfs encryption FIDO2 2fa (look into shavee) | ||||
| - Secure Boot - https://github.com/nix-community/lanzaboote | ||||
| - SMART test with email results | ||||
| - Create Tor guard/relay server | ||||
| - rotate sops encryption keys periodically (and somehow sync between devices?) | ||||
| - wake on LAN for updates | ||||
| - remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html | ||||
| - migrate away from flakes and move to npins | ||||
| - fix nfs | ||||
| - fix home assistant | ||||
| - create adguard server | ||||
| - ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix | ||||
|  | @ -1,26 +1,23 @@ | |||
| {pkgs, ...}: { | ||||
|   config = { | ||||
|     gnome = { | ||||
|       extraWindowControls = true; | ||||
|       colorScheme = "prefer-dark"; | ||||
|       clockFormat = "24h"; | ||||
|       extensions = [ | ||||
|         pkgs.gnomeExtensions.dash-to-dock | ||||
|       ]; | ||||
|       hotkeys = { | ||||
|         "Open Terminal" = { | ||||
|           binding = "<Super>t"; | ||||
|           command = "kgx"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     dconf = { | ||||
|       enable = true; | ||||
|       settings = { | ||||
|         "org/gnome/desktop/interface".color-scheme = "prefer-dark"; | ||||
| 
 | ||||
|         "org/gnome/desktop/wm/preferences".button-layout = ":minimize,maximize,close"; | ||||
| 
 | ||||
|         "org/gnome/shell" = { | ||||
|           disable-user-extensions = false; # enables user extensions | ||||
|           enabled-extensions = [ | ||||
|             # Put UUIDs of extensions that you want to enable here. | ||||
|             # If the extension you want to enable is packaged in nixpkgs, | ||||
|             # you can easily get its UUID by accessing its extensionUuid | ||||
|             # field (look at the following example). | ||||
|             pkgs.gnomeExtensions.dash-to-dock.extensionUuid | ||||
| 
 | ||||
|             # Alternatively, you can manually pass UUID as a string. | ||||
|             # "dash-to-dock@micxgx.gmail.com" | ||||
|           ]; | ||||
|         }; | ||||
| 
 | ||||
|         "org/gnome/shell/extensions/dash-to-dock" = { | ||||
|           "dock-position" = "LEFT"; | ||||
|           "intellihide-mode" = "ALL_WINDOWS"; | ||||
|  | @ -29,18 +26,6 @@ | |||
|           "show-mounts" = false; | ||||
|         }; | ||||
| 
 | ||||
|         "org/gnome/settings-daemon/plugins/media-keys" = { | ||||
|           custom-keybindings = [ | ||||
|             "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/" | ||||
|           ]; | ||||
|         }; | ||||
| 
 | ||||
|         "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = { | ||||
|           binding = "<Super>t"; | ||||
|           command = "kgx"; | ||||
|           name = "Open Terminal"; | ||||
|         }; | ||||
| 
 | ||||
|         "org/gnome/shell" = { | ||||
|           favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; | ||||
|           # app-picker-layout = | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| { | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
|  | @ -83,30 +84,11 @@ | |||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     user = { | ||||
|       continue = { | ||||
|         enable = true; | ||||
|         docs = { | ||||
|           "Continue Docs" = { | ||||
|             startUrl = "https://docs.continue.dev"; | ||||
|           }; | ||||
|           "Nixpkgs" = { | ||||
|             startUrl = "https://ryantm.github.io/nixpkgs/#preface"; | ||||
|           }; | ||||
|           "Nix Manual" = { | ||||
|             startUrl = "https://nixos.org/manual/nixos/stable/"; | ||||
|           }; | ||||
|           "Home manager Manual" = { | ||||
|             startUrl = "https://nix-community.github.io/home-manager/"; | ||||
|           }; | ||||
|           "Nix Docs" = { | ||||
|             startUrl = "https://nix.dev/index.html"; | ||||
|           }; | ||||
|           "Linux Man Page" = { | ||||
|             startUrl = "https://linux.die.net/man/"; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|     # TODO: move this into a fonts module | ||||
|     home.packages = with pkgs; [ | ||||
|       aileron | ||||
|       nerd-fonts.open-dyslexic | ||||
|     ]; | ||||
|     fonts.fontconfig.enable = true; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -67,10 +67,6 @@ in { | |||
| 
 | ||||
|       home.packages = ( | ||||
|         (with pkgs; [ | ||||
|           aileron | ||||
| 
 | ||||
|           gnomeExtensions.dash-to-dock | ||||
| 
 | ||||
|           proxmark3 | ||||
|         ]) | ||||
|         ++ ( | ||||
|  | @ -112,6 +108,8 @@ in { | |||
|             (lib.mkIf hardware.piperMouse.enable piper) | ||||
|             (lib.mkIf hardware.openRGB.enable openrgb) | ||||
|             (lib.mkIf hardware.viaKeyboard.enable via) | ||||
| 
 | ||||
|             (lib.mkIf osConfig.host.ai.enable claude-code) | ||||
|           ]) | ||||
|         ) | ||||
|       ); | ||||
|  |  | |||
|  | @ -72,6 +72,8 @@ | |||
|           deutsch-de-language-pack | ||||
|           dictionary-german | ||||
| 
 | ||||
|           tab-session-manager | ||||
| 
 | ||||
|           # ( | ||||
|           #   buildFirefoxXpiAddon rec { | ||||
|           #     pname = "italiano-it-language-pack"; | ||||
|  | @ -140,7 +142,6 @@ | |||
|             "placements" = { | ||||
|               "widget-overflow-fixed-list" = []; | ||||
|               "unified-extensions-area" = [ | ||||
|                 "privacy_privacy_com-browser-action" | ||||
|                 # bitwarden | ||||
|                 "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" | ||||
|                 "ublock0_raymondhill_net-browser-action" | ||||
|  |  | |||
|  | @ -1,31 +1,24 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   inputs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: let | ||||
|   nix-development-enabled = osConfig.host.nix-development.enable; | ||||
|   ai-tooling-enabled = config.user.continue.enable && osConfig.host.ai.enable; | ||||
|   ai-tooling-enabled = osConfig.host.ai.enable; | ||||
| in { | ||||
|   config = lib.mkIf config.user.isDesktopUser { | ||||
|     nixpkgs = { | ||||
|       overlays = [ | ||||
|         inputs.nix-vscode-extensions.overlays.default | ||||
|   imports = [ | ||||
|     ./user-words.nix | ||||
|   ]; | ||||
|     }; | ||||
| 
 | ||||
|   config = lib.mkIf config.user.isDesktopUser { | ||||
|     programs = { | ||||
|       bash.shellAliases = { | ||||
|         code = "codium"; | ||||
|       }; | ||||
| 
 | ||||
|       vscode = let | ||||
|         extensions = inputs.nix-vscode-extensions.extensions.${pkgs.system}; | ||||
|         open-vsx = extensions.open-vsx; | ||||
|         vscode-marketplace = extensions.vscode-marketplace; | ||||
|       in { | ||||
|       vscode = { | ||||
|         package = pkgs.vscodium; | ||||
| 
 | ||||
|         mutableExtensionsDir = false; | ||||
|  | @ -36,80 +29,59 @@ in { | |||
| 
 | ||||
|           userSettings = lib.mkMerge [ | ||||
|             { | ||||
|               "workbench.colorTheme" = "Atom One Dark"; | ||||
|               "cSpell.userWords" = import ./user-words.nix; | ||||
|               "javascript.updateImportsOnFileMove.enabled" = "always"; | ||||
|               "editor.tabSize" = 2; | ||||
|               "editor.insertSpaces" = false; | ||||
|             } | ||||
|             (lib.mkIf nix-development-enabled { | ||||
|               "nix.enableLanguageServer" = true; | ||||
|               "nix.serverPath" = "nil"; | ||||
|               "[nix]" = { | ||||
|                 "editor.defaultFormatter" = "kamadorueda.alejandra"; | ||||
|                 "editor.formatOnPaste" = true; | ||||
|                 "editor.formatOnSave" = true; | ||||
|                 "editor.formatOnType" = true; | ||||
|               }; | ||||
|               "alejandra.program" = "alejandra"; | ||||
|               "nixpkgs" = { | ||||
|                 "expr" = "import <nixpkgs> {}"; | ||||
|               }; | ||||
|             }) | ||||
|             (lib.mkIf ai-tooling-enabled { | ||||
|               "continue.telemetryEnabled" = false; | ||||
|             }) | ||||
|           ]; | ||||
| 
 | ||||
|           extensions = ( | ||||
|             with open-vsx; | ||||
|               [ | ||||
|           extraExtensions = { | ||||
|             # vs code feel | ||||
|             oneDark.enable = true; | ||||
|             atomKeybindings.enable = true; | ||||
|             openRemoteSsh.enable = true; | ||||
| 
 | ||||
|             # html development | ||||
|             autoRenameTag.enable = true; | ||||
|             liveServer.enable = true; | ||||
| 
 | ||||
|             # js development | ||||
|             es7ReactJsSnippets.enable = true; | ||||
|             tauriVscode.enable = true; | ||||
|             vscodeEslint.enable = true; | ||||
|             vscodeJest.enable = true; | ||||
|             vscodeStandard.enable = true; | ||||
|             vscodeStylelint.enable = true; | ||||
| 
 | ||||
|             nearley.enable = true; | ||||
| 
 | ||||
|             # astro development | ||||
|             vscodeMdx.enable = true; | ||||
|             astroVscode.enable = true; | ||||
| 
 | ||||
|             # nix development | ||||
|             alejandra.enable = nix-development-enabled; | ||||
|             nixIde.enable = nix-development-enabled; | ||||
| 
 | ||||
|             # go development | ||||
|             go.enable = true; | ||||
| 
 | ||||
|             # claude development | ||||
|             claudeDev.enable = ai-tooling-enabled; | ||||
| 
 | ||||
|             # misc extensions | ||||
|             evenBetterToml.enable = true; | ||||
|           }; | ||||
| 
 | ||||
|           extensions = let | ||||
|             extension-pkgs = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|           in ( | ||||
|             with extension-pkgs.open-vsx; [ | ||||
|               # vs code feel extensions | ||||
|                 ms-vscode.atom-keybindings | ||||
|                 akamud.vscode-theme-onedark | ||||
|               streetsidesoftware.code-spell-checker | ||||
|               streetsidesoftware.code-spell-checker-german | ||||
|               streetsidesoftware.code-spell-checker-italian | ||||
|                 jeanp413.open-remote-ssh | ||||
| 
 | ||||
|                 # html extensions | ||||
|                 formulahendry.auto-rename-tag | ||||
|                 ms-vscode.live-server | ||||
| 
 | ||||
|                 # js extensions | ||||
|                 dsznajder.es7-react-js-snippets | ||||
|                 dbaeumer.vscode-eslint | ||||
|                 standard.vscode-standard | ||||
|                 firsttris.vscode-jest-runner | ||||
|                 stylelint.vscode-stylelint | ||||
|                 tauri-apps.tauri-vscode | ||||
| 
 | ||||
|                 # go extensions | ||||
|                 golang.go | ||||
| 
 | ||||
|                 # astro blog extensions | ||||
|                 astro-build.astro-vscode | ||||
|                 unifiedjs.vscode-mdx | ||||
| 
 | ||||
|                 # misc extensions | ||||
|                 tamasfe.even-better-toml | ||||
|             ] | ||||
|               ++ (lib.lists.optionals nix-development-enabled [ | ||||
|                 # nix extensions | ||||
|                 pinage404.nix-extension-pack | ||||
|                 jnoortheen.nix-ide | ||||
|                 kamadorueda.alejandra | ||||
|               ]) | ||||
|               ++ ( | ||||
|                 with vscode-marketplace; | ||||
|                   [ | ||||
|                     # js extensions | ||||
|                     karyfoundation.nearley | ||||
|                   ] | ||||
|                   ++ (lib.lists.optionals ai-tooling-enabled [ | ||||
|                     continue.continue | ||||
|                   ]) | ||||
|               ) | ||||
|           ); | ||||
|         }; | ||||
|       }; | ||||
|  |  | |||
|  | @ -1,6 +1,126 @@ | |||
| [ | ||||
| { | ||||
|   pkgs, | ||||
|   lib, | ||||
|   ... | ||||
| }: { | ||||
|   config.programs.vscode.profiles.default.userSettings = { | ||||
|     "cSpell.userWords" = [ | ||||
|       "leyla" | ||||
|   "webdav" | ||||
|     ]; | ||||
| 
 | ||||
|     "cSpell.languageSettings" = [ | ||||
|       { | ||||
|         "languageId" = "nix"; | ||||
|         "locale" = "*"; | ||||
|         "dictionaries" = [ | ||||
|           "applications" | ||||
|           "ai-words" | ||||
|           "nix-words" | ||||
| 
 | ||||
|           # We need to include all other dictionaries in the nix language settings because they exist in this file | ||||
|           # TODO: see if there is a way to make this only apply for this file | ||||
|           "js-words" | ||||
|         ]; | ||||
|       } | ||||
|       { | ||||
|         "languageId" = "javascript,typescript,js,ts"; | ||||
|         "locale" = "*"; | ||||
|         "dictionaries" = [ | ||||
|           "js-words" | ||||
|         ]; | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     "cSpell.customDictionaries" = { | ||||
|       applications = { | ||||
|         name = "applications"; | ||||
|         description = "application names"; | ||||
|         path = pkgs.writeText "applications.txt" (lib.strings.concatLines [ | ||||
|           "ollama" | ||||
|           "syncthing" | ||||
|           "immich" | ||||
|           "sonos" | ||||
|           "makemkv" | ||||
|           "hass" | ||||
|           "qbittorent" | ||||
|           "prostudiomasters" | ||||
|           "protonmail" | ||||
|           "pulseaudio" | ||||
|         ]); | ||||
|       }; | ||||
| 
 | ||||
|       ai-words = { | ||||
|         name = "ai-words"; | ||||
|         description = "common words used for ai development"; | ||||
|         path = pkgs.writeText "ai-words.txt" (lib.strings.concatLines [ | ||||
|           "ollama" | ||||
|           "deepseek" | ||||
|           "qwen" | ||||
|         ]); | ||||
|       }; | ||||
| 
 | ||||
|       nix-words = { | ||||
|         name = "nix-words"; | ||||
|         description = "words used in nix configurations"; | ||||
|         path = pkgs.writeText "nix-words.txt" (lib.strings.concatLines [ | ||||
|           "pname" | ||||
|           "direnv" | ||||
|           "tmpfiles" | ||||
|           "Networkd" | ||||
|           "networkmanager" | ||||
|           "dialout" | ||||
|           "adbusers" | ||||
|           "authkey" | ||||
|           "netdevs" | ||||
|           "atomix" | ||||
|           "geary" | ||||
|           "gedit" | ||||
|           "hitori" | ||||
|           "iagno" | ||||
|           "alsa" | ||||
|           "timezoned" | ||||
|           "pipewire" | ||||
|           "rtkit" | ||||
|           "disko" | ||||
|           "ashift" | ||||
|           "autotrim" | ||||
|           "canmount" | ||||
|           "mountpoint" | ||||
|           "xattr" | ||||
|           "acltype" | ||||
|           "relatime" | ||||
|           "keyformat" | ||||
|           "keylocation" | ||||
|           "vdevs" | ||||
| 
 | ||||
|           # codium extensions | ||||
|           "akamud" | ||||
|           "onedark" | ||||
|           "jeanp" | ||||
|           "dsznajder" | ||||
|           "dbaeumer" | ||||
|           "orta" | ||||
|           "tauri" | ||||
|           "unifiedjs" | ||||
|           "tamasfe" | ||||
|           "pinage" | ||||
|           "jnoortheen" | ||||
|           "kamadorueda" | ||||
|           "karyfoundation" | ||||
|           "nearley" | ||||
| 
 | ||||
|           # nix.optimise is spelled wrong | ||||
|           "optimise" | ||||
| ] | ||||
|         ]); | ||||
|       }; | ||||
| 
 | ||||
|       js-words = { | ||||
|         name = "js-words"; | ||||
|         description = "words used in js development"; | ||||
|         path = pkgs.writeText "js-words.txt" (lib.strings.concatLines [ | ||||
|           "webdav" | ||||
|         ]); | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -17,6 +17,12 @@ | |||
|     "services/zfs_smtp_token" = { | ||||
|       sopsFile = "${inputs.secrets}/defiant-services.yaml"; | ||||
|     }; | ||||
|     "services/paperless_password" = { | ||||
|       sopsFile = "${inputs.secrets}/defiant-services.yaml"; | ||||
|       mode = "0700"; | ||||
|       owner = "paperless"; | ||||
|       group = "paperless"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   host = { | ||||
|  | @ -36,7 +42,7 @@ | |||
|         host = "smtp.protonmail.ch"; | ||||
|         port = 587; | ||||
|         to = "leyla@jan-leila.com"; | ||||
|         user = "leyla@jan-leila.com"; | ||||
|         user = "noreply@jan-leila.com"; | ||||
|         tokenFile = config.sops.secrets."services/zfs_smtp_token".path; | ||||
|       }; | ||||
|       pool = { | ||||
|  | @ -109,24 +115,11 @@ | |||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|     # home-assistant = { | ||||
|     #   enable = false; | ||||
|     #   subdomain = "home"; | ||||
|     # }; | ||||
|     adguardhome = { | ||||
|       enable = false; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   systemd.network = { | ||||
|     enable = true; | ||||
| 
 | ||||
|     # config = { | ||||
|     #   routeTables = { | ||||
|     #     p2p = 1; | ||||
|     #   }; | ||||
|     # }; | ||||
| 
 | ||||
|     netdevs = { | ||||
|       "10-bond0" = { | ||||
|         netdevConfig = { | ||||
|  | @ -139,23 +132,20 @@ | |||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       # "15-p2p0" = { | ||||
|       # "20-wg0" = { | ||||
|       #   netdevConfig = { | ||||
|       #     Kind = "wireguard"; | ||||
|       #     Name = "p2p0"; | ||||
|       #     MTUBytes = "1280"; | ||||
|       #     Name = "wg0"; | ||||
|       #   }; | ||||
|       #   wireguardConfig = { | ||||
|       #     PrivateKeyFile = config.sops.secrets."vpn-keys/proton-wireguard/defiant-p2p".path; | ||||
|       #     ListenPort = 51820; | ||||
|       #     # RouteTable = "p2p"; | ||||
|       #   }; | ||||
|       #   wireguardPeers = [ | ||||
|       #     { | ||||
|       #       PublicKey = "rRO6yJim++Ezz6scCLMaizI+taDjU1pzR2nfW6qKbW0="; | ||||
|       #       Endpoint = "185.230.126.146:51820"; | ||||
|       #       AllowedIPs = ["0.0.0.0/0"]; | ||||
|       #       RouteTable = "off"; | ||||
|       #     } | ||||
|       #   ]; | ||||
|       # }; | ||||
|  | @ -177,17 +167,25 @@ | |||
|         dns = ["192.168.1.1"]; | ||||
|       }; | ||||
| 
 | ||||
|       # "45-p2p0" = { | ||||
|       #   matchConfig.Name = "p2p0"; | ||||
|       # For some reason this isn't working. It looks like traffic goes out and comes back but doesn't get correctly routed back to the wg interface on the return trip | ||||
|       # debugging steps: | ||||
|       # try sending data on the interface `ping -I wg0 8.8.8.8` | ||||
|       # view all traffic on the interface `sudo tshark -i wg0` | ||||
|       # see what applications are listening to port 14666 (thats what we currently have qbittorent set up to use) `ss -tuln | grep 14666` | ||||
|       # "50-wg0" = { | ||||
|       #   matchConfig.Name = "wg0"; | ||||
|       #   networkConfig = { | ||||
|       #     DHCP = "no"; | ||||
|       #   }; | ||||
|       #   address = [ | ||||
|       #     "10.2.0.2/32" | ||||
|       #   ]; | ||||
|       #   routes = [ | ||||
|       #     { | ||||
|       #       Destination = "0.0.0.0/0"; | ||||
|       #     } | ||||
|       #   ]; | ||||
|       #   linkConfig.RequiredForOnline = false; | ||||
|       #   # routes = [ | ||||
|       #   #   { | ||||
|       #   #     Destination = "10.2.0.2/32"; | ||||
|       #   #     Gateway = "10.2.0.1"; | ||||
|       #   #   } | ||||
|       #   # ]; | ||||
|       # }; | ||||
|     }; | ||||
|   }; | ||||
|  | @ -196,13 +194,7 @@ | |||
|   boot.kernelParams = ["zfs.zfs_arc_max=53687091200"]; | ||||
| 
 | ||||
|   services = { | ||||
|     # TODO: move zfs scrubbing into module | ||||
|     zfs = { | ||||
|       autoScrub.enable = true; | ||||
|       autoSnapshot.enable = true; | ||||
|     }; | ||||
| 
 | ||||
|     # temp enable desktop enviroment for setup | ||||
|     # temp enable desktop environment for setup | ||||
|     # Enable the X11 windowing system. | ||||
|     xserver.enable = true; | ||||
| 
 | ||||
|  | @ -220,6 +212,10 @@ | |||
| 
 | ||||
|       acceleration = false; | ||||
| 
 | ||||
|       environmentVariables = { | ||||
|         OLLAMA_KEEP_ALIVE = "24h"; | ||||
|       }; | ||||
| 
 | ||||
|       loadModels = [ | ||||
|         # conversation models | ||||
|         "llama3.1:8b" | ||||
|  | @ -236,6 +232,10 @@ | |||
|         # agent models | ||||
|         "qwen3:8b" | ||||
|         "qwen3:32b" | ||||
|         "qwen3:235b-a22b" | ||||
| 
 | ||||
|         "qwen3-coder:30b" | ||||
|         "qwen3-coder:30b-a3b-fp16" | ||||
| 
 | ||||
|         # embedding models | ||||
|         "nomic-embed-text:latest" | ||||
|  | @ -282,17 +282,35 @@ | |||
|       subdomain = "search"; | ||||
|     }; | ||||
| 
 | ||||
|     virt-home-assistant = { | ||||
|     actual = { | ||||
|       enable = false; | ||||
|       networkBridge = "bond0"; | ||||
|       hostDevice = "0x10c4:0xea60"; | ||||
|       subdomain = "budget"; | ||||
|     }; | ||||
| 
 | ||||
|     home-assistant = { | ||||
|       enable = true; | ||||
|       subdomain = "home"; | ||||
|       openFirewall = true; | ||||
|       database = "postgres"; | ||||
| 
 | ||||
|       extensions = { | ||||
|         sonos.enable = true; | ||||
|         jellyfin.enable = true; | ||||
|         wyoming.enable = true; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     paperless = { | ||||
|       enable = true; | ||||
|       subdomain = "documents"; | ||||
|       passwordFile = config.sops.secrets."services/paperless_password".path; | ||||
|     }; | ||||
| 
 | ||||
|     qbittorrent = { | ||||
|       enable = true; | ||||
|       mediaDir = "/srv/qbittorent"; | ||||
|       openFirewall = true; | ||||
|       webPort = 8084; | ||||
|       webuiPort = 8084; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -126,6 +126,13 @@ | |||
|     }; | ||||
| 
 | ||||
|     syncthing.enable = true; | ||||
| 
 | ||||
|     ollama = { | ||||
|       enable = true; | ||||
|       loadModels = [ | ||||
|         "llama3.1:8b" | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   # Enable touchpad support (enabled default in most desktopManager). | ||||
|  |  | |||
							
								
								
									
										142
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										142
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							|  | @ -7,11 +7,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1750680230, | ||||
|         "narHash": "sha256-kD88T/NqmcgfOBFAwphN30ccaUdj6K6+LG0XdM2w2LA=", | ||||
|         "lastModified": 1755519972, | ||||
|         "narHash": "sha256-bU4nqi3IpsUZJeyS8Jk85ytlX61i4b0KCxXX9YcOgVc=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "disko", | ||||
|         "rev": "8fd2d6c75009ac75f9a6fb18c33a239806778d01", | ||||
|         "rev": "4073ff2f481f9ef3501678ff479ed81402caae6d", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -28,11 +28,11 @@ | |||
|       }, | ||||
|       "locked": { | ||||
|         "dir": "pkgs/firefox-addons", | ||||
|         "lastModified": 1750737804, | ||||
|         "narHash": "sha256-wClGd2PhxdjjphR6wIgoiDcR+Gfg4/+FyseSOjIIzVU=", | ||||
|         "lastModified": 1755921820, | ||||
|         "narHash": "sha256-xTRXoaGtuIi4VvJNGuHC8DPHnEIJUqVtt7kqU8MdXes=", | ||||
|         "owner": "rycee", | ||||
|         "repo": "nur-expressions", | ||||
|         "rev": "aaaf4fec792bad465ea4a35c0be5bc2a54f33095", | ||||
|         "rev": "c43149f02063de9b0d75c2b45f54631bd82667b2", | ||||
|         "type": "gitlab" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -75,39 +75,6 @@ | |||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_2": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_2" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1731533236, | ||||
|         "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flakey-profile": { | ||||
|       "locked": { | ||||
|         "lastModified": 1712898590, | ||||
|         "narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=", | ||||
|         "owner": "lf-", | ||||
|         "repo": "flakey-profile", | ||||
|         "rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "lf-", | ||||
|         "repo": "flakey-profile", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "home-manager": { | ||||
|       "inputs": { | ||||
|         "nixpkgs": [ | ||||
|  | @ -115,11 +82,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1750730235, | ||||
|         "narHash": "sha256-rZErlxiV7ssvI8t7sPrKU+fRigNc2KvoKZG3gtUtK50=", | ||||
|         "lastModified": 1755914636, | ||||
|         "narHash": "sha256-VJ+Gm6YsHlPfUCpmRQxvdiZW7H3YPSrdVOewQHAhZN8=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "d07e9cceb4994ed64a22b9b36f8b76923e87ac38", | ||||
|         "rev": "8b55a6ac58b678199e5bba701aaff69e2b3281c0", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -143,41 +110,6 @@ | |||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "lix": { | ||||
|       "flake": false, | ||||
|       "locked": { | ||||
|         "lastModified": 1746827285, | ||||
|         "narHash": "sha256-hsFe4Tsqqg4l+FfQWphDtjC79WzNCZbEFhHI8j2KJzw=", | ||||
|         "rev": "47aad376c87e2e65967f17099277428e4b3f8e5a", | ||||
|         "type": "tarball", | ||||
|         "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/47aad376c87e2e65967f17099277428e4b3f8e5a.tar.gz?rev=47aad376c87e2e65967f17099277428e4b3f8e5a" | ||||
|       }, | ||||
|       "original": { | ||||
|         "type": "tarball", | ||||
|         "url": "https://git.lix.systems/lix-project/lix/archive/2.93.0.tar.gz" | ||||
|       } | ||||
|     }, | ||||
|     "lix-module": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils", | ||||
|         "flakey-profile": "flakey-profile", | ||||
|         "lix": "lix", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1746838955, | ||||
|         "narHash": "sha256-11R4K3iAx4tLXjUs+hQ5K90JwDABD/XHhsM9nkeS5N8=", | ||||
|         "rev": "cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc", | ||||
|         "type": "tarball", | ||||
|         "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc.tar.gz?rev=cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc" | ||||
|       }, | ||||
|       "original": { | ||||
|         "type": "tarball", | ||||
|         "url": "https://git.lix.systems/lix-project/nixos-module/archive/2.93.0.tar.gz" | ||||
|       } | ||||
|     }, | ||||
|     "nix-darwin": { | ||||
|       "inputs": { | ||||
|         "nixpkgs": [ | ||||
|  | @ -185,11 +117,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1750618568, | ||||
|         "narHash": "sha256-w9EG5FOXrjXGfbqCcQg9x1lMnTwzNDW5BMXp8ddy15E=", | ||||
|         "lastModified": 1755825449, | ||||
|         "narHash": "sha256-XkiN4NM9Xdy59h69Pc+Vg4PxkSm9EWl6u7k6D5FZ5cM=", | ||||
|         "owner": "LnL7", | ||||
|         "repo": "nix-darwin", | ||||
|         "rev": "1dd19f19e4b53a1fd2e8e738a08dd5fe635ec7e5", | ||||
|         "rev": "8df64f819698c1fee0c2969696f54a843b2231e8", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -221,17 +153,17 @@ | |||
|     }, | ||||
|     "nix-vscode-extensions": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_2", | ||||
|         "flake-utils": "flake-utils", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1750730765, | ||||
|         "narHash": "sha256-MIcOcvxqAXUv2TJjf19aVXdtVrD8Gkcfi4W4pKkT0Lw=", | ||||
|         "lastModified": 1755914146, | ||||
|         "narHash": "sha256-ew98ilw4NTodKlILnr3ndsT0Aj9JhqC507JB3efa0pY=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "nix-vscode-extensions", | ||||
|         "rev": "1a1442e13dc1730de0443f80dcf02658365e999a", | ||||
|         "rev": "ff42a421ff1d415caa0125e6af6f3bd82e642838", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -242,11 +174,11 @@ | |||
|     }, | ||||
|     "nixos-hardware": { | ||||
|       "locked": { | ||||
|         "lastModified": 1750431636, | ||||
|         "narHash": "sha256-vnzzBDbCGvInmfn2ijC4HsIY/3W1CWbwS/YQoFgdgPg=", | ||||
|         "lastModified": 1755330281, | ||||
|         "narHash": "sha256-aJHFJWP9AuI8jUGzI77LYcSlkA9wJnOIg4ZqftwNGXA=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixos-hardware", | ||||
|         "rev": "1552a9f4513f3f0ceedcf90320e48d3d47165712", | ||||
|         "rev": "3dac8a872557e0ca8c083cdcfc2f218d18e113b0", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -258,11 +190,11 @@ | |||
|     }, | ||||
|     "nixpkgs": { | ||||
|       "locked": { | ||||
|         "lastModified": 1750506804, | ||||
|         "narHash": "sha256-VLFNc4egNjovYVxDGyBYTrvVCgDYgENp5bVi9fPTDYc=", | ||||
|         "lastModified": 1755615617, | ||||
|         "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", | ||||
|         "owner": "nixos", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "4206c4cb56751df534751b058295ea61357bbbaa", | ||||
|         "rev": "20075955deac2583bb12f07151c2df830ef346b4", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -279,7 +211,6 @@ | |||
|         "flake-compat": "flake-compat", | ||||
|         "home-manager": "home-manager", | ||||
|         "impermanence": "impermanence", | ||||
|         "lix-module": "lix-module", | ||||
|         "nix-darwin": "nix-darwin", | ||||
|         "nix-syncthing": "nix-syncthing", | ||||
|         "nix-vscode-extensions": "nix-vscode-extensions", | ||||
|  | @ -293,11 +224,11 @@ | |||
|     "secrets": { | ||||
|       "flake": false, | ||||
|       "locked": { | ||||
|         "lastModified": 1749061163, | ||||
|         "narHash": "sha256-WflcbitH7ErNZBFqZCdy1ODUqKF51xbu2zYfqA35+1M=", | ||||
|         "lastModified": 1752531440, | ||||
|         "narHash": "sha256-04tQ3EUrtmZ7g6fVUkZC4AbAG+Z7lng79qU3jsiqWJY=", | ||||
|         "ref": "refs/heads/main", | ||||
|         "rev": "1c5c059c0c7b6ce691993262fe10a2b63e1c31ba", | ||||
|         "revCount": 19, | ||||
|         "rev": "f016767c13aa36dde91503f7a9f01bdd02468045", | ||||
|         "revCount": 20, | ||||
|         "type": "git", | ||||
|         "url": "ssh://git@git.jan-leila.com/jan-leila/nix-config-secrets.git" | ||||
|       }, | ||||
|  | @ -313,11 +244,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1750119275, | ||||
|         "narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=", | ||||
|         "lastModified": 1754988908, | ||||
|         "narHash": "sha256-t+voe2961vCgrzPFtZxha0/kmFSHFobzF00sT8p9h0U=", | ||||
|         "owner": "Mic92", | ||||
|         "repo": "sops-nix", | ||||
|         "rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2", | ||||
|         "rev": "3223c7a92724b5d804e9988c6b447a0d09017d48", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -360,21 +291,6 @@ | |||
|         "repo": "default", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "systems_2": { | ||||
|       "locked": { | ||||
|         "lastModified": 1681028828, | ||||
|         "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", | ||||
|         "owner": "nix-systems", | ||||
|         "repo": "default", | ||||
|         "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "nix-systems", | ||||
|         "repo": "default", | ||||
|         "type": "github" | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "root": "root", | ||||
|  |  | |||
|  | @ -5,10 +5,10 @@ | |||
|     # base packages | ||||
|     nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; | ||||
| 
 | ||||
|     lix-module = { | ||||
|       url = "https://git.lix.systems/lix-project/nixos-module/archive/2.93.0.tar.gz"; | ||||
|       inputs.nixpkgs.follows = "nixpkgs"; | ||||
|     }; | ||||
|     # lix-module = { | ||||
|     #   url = "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-1.tar.gz"; | ||||
|     #   inputs.nixpkgs.follows = "nixpkgs"; | ||||
|     # }; | ||||
| 
 | ||||
|     # secret encryption | ||||
|     sops-nix = { | ||||
|  |  | |||
|  | @ -2,5 +2,6 @@ | |||
| {inputs, ...}: { | ||||
|   nixpkgs.overlays = [ | ||||
|     inputs.steam-fetcher.overlays.default | ||||
|     inputs.nix-vscode-extensions.overlays.default | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										42
									
								
								modules/common-modules/pkgs/codium-extensions/ai-code.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								modules/common-modules/pkgs/codium-extensions/ai-code.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| { | ||||
|   buildNpmPackage, | ||||
|   vscode-utils, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: let | ||||
|   version = "0.0.1"; | ||||
|   pname = "ai-code"; | ||||
|   publisher = "jan-leila"; | ||||
|   vsix = buildNpmPackage { | ||||
|     inherit version pname; | ||||
| 
 | ||||
|     src = builtins.fetchGit { | ||||
|       url = "ssh://git@git.jan-leila.com/jan-leila/ai-code.git"; | ||||
|       rev = "d48e01713021dbb30de0ebbee2cfaf99e4e9b5a6"; | ||||
|     }; | ||||
| 
 | ||||
|     npmDepsHash = "sha256-kjMyEnT3dz0yH5Ydh+aGoFDocKpBYGRmfnwbEdvvgpY="; | ||||
| 
 | ||||
|     nativeBuildInputs = with pkgs; [ | ||||
|       vsce | ||||
|     ]; | ||||
| 
 | ||||
|     buildPhase = '' | ||||
|       ${pkgs.vsce}/bin/vsce package -o ${pname}.zip | ||||
|     ''; | ||||
| 
 | ||||
|     installPhase = '' | ||||
|       mkdir -p $out | ||||
|       mv ${pname}.zip $out/${pname}.zip | ||||
|     ''; | ||||
|   }; | ||||
| in | ||||
|   vscode-utils.buildVscodeExtension { | ||||
|     inherit pname version; | ||||
| 
 | ||||
|     src = "${vsix}/${pname}.zip"; | ||||
| 
 | ||||
|     vscodeExtUniqueId = "${publisher}.${pname}"; | ||||
|     vscodeExtPublisher = publisher; | ||||
|     vscodeExtName = pname; | ||||
|   } | ||||
|  | @ -0,0 +1,3 @@ | |||
| {pkgs, ...}: { | ||||
|   ai-code = pkgs.callPackage ./ai-code.nix {}; | ||||
| } | ||||
|  | @ -19,5 +19,8 @@ | |||
|     (final: prev: { | ||||
|       gdx-liftoff = pkgs.callPackage ./gdx-liftoff.nix {}; | ||||
|     }) | ||||
|     (final: prev: { | ||||
|       codium-extensions = pkgs.callPackage ./codium-extensions {}; | ||||
|     }) | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -1,73 +0,0 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: let | ||||
|   ai-tooling-enabled = config.user.continue.enable && osConfig.host.ai.enable; | ||||
| in { | ||||
|   options.user.continue = { | ||||
|     enable = lib.mkEnableOption "should continue be enabled on this machine"; | ||||
|     docs = lib.mkOption { | ||||
|       type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { | ||||
|         options = { | ||||
|           name = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|             default = name; | ||||
|           }; | ||||
|           startUrl = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|           }; | ||||
|         }; | ||||
|       })); | ||||
|     }; | ||||
|     context = lib.mkOption { | ||||
|       type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { | ||||
|         options = { | ||||
|           provider = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|             default = name; | ||||
|           }; | ||||
|         }; | ||||
|       })); | ||||
|       default = { | ||||
|         "code" = {}; | ||||
|         "docs" = {}; | ||||
|         "diff" = {}; | ||||
|         "terminal" = {}; | ||||
|         "problems" = {}; | ||||
|         "folder" = {}; | ||||
|         "codebase" = {}; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = | ||||
|     lib.mkIf ai-tooling-enabled | ||||
|     (lib.mkMerge [ | ||||
|       { | ||||
|         home = { | ||||
|           file = { | ||||
|             ".continue/config.yaml".source = (pkgs.formats.yaml {}).generate "continue-config" { | ||||
|               name = "Assistant"; | ||||
|               version = "1.0.0"; | ||||
|               schema = "v1"; | ||||
|               models = lib.attrsets.attrValues osConfig.host.ai.models; | ||||
|               context = lib.attrsets.attrValues config.user.continue.context; | ||||
|               docs = lib.attrsets.attrValues config.user.continue.docs; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       } | ||||
|       (lib.mkIf osConfig.host.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             ".continue/index" | ||||
|             ".continue/sessions" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       }) | ||||
|     ]); | ||||
| } | ||||
|  | @ -6,7 +6,7 @@ | |||
|     ./flipperzero.nix | ||||
|     ./i18n.nix | ||||
|     ./openssh.nix | ||||
|     ./continue.nix | ||||
|     ./gnome.nix | ||||
|     ./programs | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										106
									
								
								modules/home-manager-modules/gnome.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								modules/home-manager-modules/gnome.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.gnome = { | ||||
|     extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; | ||||
|     clockFormat = lib.mkOption { | ||||
|       type = lib.types.enum [ | ||||
|         "12h" | ||||
|         "24h" | ||||
|       ]; | ||||
|       default = "24h"; | ||||
|     }; | ||||
|     colorScheme = lib.mkOption { | ||||
|       type = lib.types.enum [ | ||||
|         "default" | ||||
|         "prefer-dark" | ||||
|         "prefer-light" | ||||
|       ]; | ||||
|       default = "default"; | ||||
|     }; | ||||
|     accentColor = lib.mkOption { | ||||
|       type = lib.types.enum [ | ||||
|         "blue" | ||||
|         "teal" | ||||
|         "green" | ||||
|         "yellow" | ||||
|         "orange" | ||||
|         "red" | ||||
|         "pink" | ||||
|         "purple" | ||||
|         "slate" | ||||
|       ]; | ||||
|       default = "blue"; | ||||
|     }; | ||||
|     extensions = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.package; | ||||
|       default = []; | ||||
|       description = "The set of extensions to install and enable in the user environment."; | ||||
|     }; | ||||
|     hotkeys = lib.mkOption { | ||||
|       type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { | ||||
|         options = { | ||||
|           key = lib.mkOption { | ||||
|             type = lib.types.strMatching "[a-zA-Z0-9-]+"; | ||||
|             default = builtins.replaceStrings [" " "/" "_"] ["-" "-" "-"] name; | ||||
|           }; | ||||
|           name = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|             default = name; | ||||
|           }; | ||||
|           binding = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|           }; | ||||
|           command = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|           }; | ||||
|         }; | ||||
|       })); | ||||
|       default = {}; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = { | ||||
|     home.packages = config.gnome.extensions; | ||||
|     dconf = { | ||||
|       settings = lib.mkMerge [ | ||||
|         { | ||||
|           "org/gnome/shell" = { | ||||
|             disable-user-extensions = false; # enables user extensions | ||||
|             enabled-extensions = builtins.map (extension: extension.extensionUuid) config.gnome.extensions; | ||||
|           }; | ||||
| 
 | ||||
|           "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; | ||||
| 
 | ||||
|           "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; | ||||
|           "org/gnome/desktop/interface".accent-color = config.gnome.accentColor; | ||||
|           "org/gnome/desktop/interface".clock-format = config.gnome.clockFormat; | ||||
|         } | ||||
|         ( | ||||
|           lib.mkMerge ( | ||||
|             builtins.map (value: let | ||||
|               entry = "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${value.key}"; | ||||
|             in { | ||||
|               ${entry} = { | ||||
|                 binding = value.binding; | ||||
|                 command = value.command; | ||||
|                 name = value.name; | ||||
|               }; | ||||
| 
 | ||||
|               "org/gnome/settings-daemon/plugins/media-keys" = { | ||||
|                 custom-keybindings = [ | ||||
|                   "/${entry}/" | ||||
|                 ]; | ||||
|               }; | ||||
|             }) | ||||
|             ( | ||||
|               lib.attrsets.mapAttrsToList (_: value: value) config.gnome.hotkeys | ||||
|             ) | ||||
|           ) | ||||
|         ) | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -1,29 +1,15 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.anki = { | ||||
|     enable = lib.mkEnableOption "enable anki"; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.programs.anki.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = with pkgs; [ | ||||
|         anki | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|   config = lib.mkIf (config.programs.anki.enable && osConfig.host.impermanence.enable) { | ||||
|     home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|       directories = [ | ||||
|         "${config.xdg.dataHome}/Anki2/" | ||||
|       ]; | ||||
|       allowOther = true; | ||||
|     }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -16,5 +16,6 @@ | |||
|     ./bruno.nix | ||||
|     ./dbeaver.nix | ||||
|     ./steam.nix | ||||
|     ./vscode | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										45
									
								
								modules/home-manager-modules/programs/vscode/aiCode.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								modules/home-manager-modules/programs/vscode/aiCode.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepository = pkgs.codium-extensions; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.aiCode = { | ||||
|           enable = lib.mkEnableOption "should the ai code extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "ai-code" {}; | ||||
|           ollamaHost = lib.mkOption { | ||||
|             type = lib.types.nullOr lib.types.str; | ||||
|             description = "what host should be used for ollama"; | ||||
|             default = null; | ||||
|           }; | ||||
|           inlineCompletion = { | ||||
|             enable = lib.mkOption { | ||||
|               type = lib.types.bool; | ||||
|               description = "should inline completion be enabled"; | ||||
|               default = true; | ||||
|             }; | ||||
|             model = lib.mkOption { | ||||
|               type = lib.types.nullOr lib.types.str; | ||||
|               description = "what model should be used for ollama"; | ||||
|               default = null; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.aiCode.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.aiCode.extension | ||||
|         ]; | ||||
|         userSettings = { | ||||
|           "aiCode.ollamaHost" = lib.mkIf (config.extraExtensions.aiCode.ollamaHost != null) config.extraExtensions.aiCode.ollamaHost; | ||||
|           "aiCode.inlineCompletion.enable" = config.extraExtensions.aiCode.inlineCompletion.enable; | ||||
|           "aiCode.inlineCompletion.model" = lib.mkIf (config.extraExtensions.aiCode.inlineCompletion.model != null) config.extraExtensions.aiCode.inlineCompletion.model; | ||||
|         }; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										34
									
								
								modules/home-manager-modules/programs/vscode/alejandra.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								modules/home-manager-modules/programs/vscode/alejandra.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.alejandra = { | ||||
|           enable = lib.mkEnableOption "Enable Alejandra extension for Nix formatting"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "alejandra" { | ||||
|             default = ["kamadorueda" "alejandra"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.alejandra.enable { | ||||
|         extensions = [config.extraExtensions.alejandra.extension]; | ||||
|         userSettings = { | ||||
|           "[nix]" = { | ||||
|             "editor.defaultFormatter" = "kamadorueda.alejandra"; | ||||
|             "editor.formatOnPaste" = true; | ||||
|             "editor.formatOnSave" = true; | ||||
|             "editor.formatOnType" = true; | ||||
|           }; | ||||
|           "alejandra.program" = "alejandra"; | ||||
|         }; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/astroVscode.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/astroVscode.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.astroVscode = { | ||||
|           enable = lib.mkEnableOption "should the astro-vscode extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "astro-vscode" { | ||||
|             default = ["astro-build" "astro-vscode"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.astroVscode.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.astroVscode.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.atomKeybindings = { | ||||
|           enable = lib.mkEnableOption "should the atom keybindings extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "atom-keybindings" { | ||||
|             default = ["ms-vscode" "atom-keybindings"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.atomKeybindings.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.atomKeybindings.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.autoRenameTag = { | ||||
|           enable = lib.mkEnableOption "should the auto-rename-tag extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "auto-rename-tag" { | ||||
|             default = ["formulahendry" "auto-rename-tag"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.autoRenameTag.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.autoRenameTag.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/claudeDev.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/claudeDev.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.claudeDev = { | ||||
|           enable = lib.mkEnableOption "should the claude-dev extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "claude-dev" { | ||||
|             default = ["saoudrizwan" "claude-dev"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.claudeDev.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.claudeDev.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										24
									
								
								modules/home-manager-modules/programs/vscode/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/home-manager-modules/programs/vscode/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./oneDark.nix | ||||
|     ./atomKeybindings.nix | ||||
|     ./aiCode.nix | ||||
|     ./alejandra.nix | ||||
|     ./nixIde.nix | ||||
|     ./autoRenameTag.nix | ||||
|     ./es7ReactJsSnippets.nix | ||||
|     ./liveServer.nix | ||||
|     ./tauriVscode.nix | ||||
|     ./vscodeEslint.nix | ||||
|     ./vscodeJest.nix | ||||
|     ./vscodeStandard.nix | ||||
|     ./vscodeStylelint.nix | ||||
|     ./go.nix | ||||
|     ./evenBetterToml.nix | ||||
|     ./openRemoteSsh.nix | ||||
|     ./astroVscode.nix | ||||
|     ./vscodeMdx.nix | ||||
|     ./claudeDev.nix | ||||
|     ./nearley.nix | ||||
|   ]; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.es7ReactJsSnippets = { | ||||
|           enable = lib.mkEnableOption "should the es7-react-js-snippets extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "es7-react-js-snippets" { | ||||
|             default = ["dsznajder" "es7-react-js-snippets"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.es7ReactJsSnippets.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.es7ReactJsSnippets.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.evenBetterToml = { | ||||
|           enable = lib.mkEnableOption "should the even-better-toml extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "even-better-toml" { | ||||
|             default = ["tamasfe" "even-better-toml"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.evenBetterToml.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.evenBetterToml.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/go.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/go.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.go = { | ||||
|           enable = lib.mkEnableOption "should the go extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "go" { | ||||
|             default = ["golang" "go"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.go.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.go.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/liveServer.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/liveServer.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.liveServer = { | ||||
|           enable = lib.mkEnableOption "should the live-server extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "live-server" { | ||||
|             default = ["ms-vscode" "live-server"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.liveServer.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.liveServer.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/nearley.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/nearley.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.vscode-marketplace; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.nearley = { | ||||
|           enable = lib.mkEnableOption "should the nearley extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "nearley" { | ||||
|             default = ["karyfoundation" "nearley"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.nearley.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.nearley.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										29
									
								
								modules/home-manager-modules/programs/vscode/nixIde.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								modules/home-manager-modules/programs/vscode/nixIde.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.nixIde = { | ||||
|           enable = lib.mkEnableOption "Enable Nix IDE extension"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "nix-ide" { | ||||
|             default = ["jnoortheen" "nix-ide"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.nixIde.enable { | ||||
|         extensions = [config.extraExtensions.nixIde.extension]; | ||||
|         userSettings = { | ||||
|           "nix.enableLanguageServer" = true; | ||||
|           "nix.serverPath" = "nil"; | ||||
|         }; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										30
									
								
								modules/home-manager-modules/programs/vscode/oneDark.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								modules/home-manager-modules/programs/vscode/oneDark.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.oneDark = { | ||||
|           enable = lib.mkEnableOption "should the one dark theme for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "onedark" { | ||||
|             default = ["akamud" "vscode-theme-onedark"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.oneDark.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.oneDark.extension | ||||
|         ]; | ||||
|         userSettings = { | ||||
|           "workbench.colorTheme" = "Atom One Dark"; | ||||
|         }; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.openRemoteSsh = { | ||||
|           enable = lib.mkEnableOption "should the open-remote-ssh extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "open-remote-ssh" { | ||||
|             default = ["jeanp413" "open-remote-ssh"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.openRemoteSsh.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.openRemoteSsh.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/tauriVscode.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/tauriVscode.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.tauriVscode = { | ||||
|           enable = lib.mkEnableOption "should the tauri-vscode extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "tauri-vscode" { | ||||
|             default = ["tauri-apps" "tauri-vscode"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.tauriVscode.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.tauriVscode.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.vscodeEslint = { | ||||
|           enable = lib.mkEnableOption "should the vscode-eslint extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "vscode-eslint" { | ||||
|             default = ["dbaeumer" "vscode-eslint"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.vscodeEslint.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.vscodeEslint.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/vscodeJest.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/vscodeJest.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.vscodeJest = { | ||||
|           enable = lib.mkEnableOption "should the vscode-jest extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "vscode-jest" { | ||||
|             default = ["orta" "vscode-jest"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.vscodeJest.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.vscodeJest.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										27
									
								
								modules/home-manager-modules/programs/vscode/vscodeMdx.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/home-manager-modules/programs/vscode/vscodeMdx.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.vscodeMdx = { | ||||
|           enable = lib.mkEnableOption "should the vscode-mdx extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "vscode-mdx" { | ||||
|             default = ["unifiedjs" "vscode-mdx"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.vscodeMdx.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.vscodeMdx.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.vscodeStandard = { | ||||
|           enable = lib.mkEnableOption "should the vscode-standard extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "vscode-standard" { | ||||
|             default = ["standard" "vscode-standard"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.vscodeStandard.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.vscodeStandard.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; | ||||
|   pkgsRepository = pkgsRepositories.open-vsx; | ||||
| in { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.vscodeStylelint = { | ||||
|           enable = lib.mkEnableOption "should the vscode-stylelint extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "vscode-stylelint" { | ||||
|             default = ["stylelint" "vscode-stylelint"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.vscodeStylelint.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.vscodeStylelint.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
|  | @ -22,7 +22,7 @@ | |||
|         gnome-characters # character set viewer | ||||
|         gnome-music # music player | ||||
|         gnome-photos # photo viewer | ||||
|         gnome-logs # log viwer | ||||
|         gnome-logs # log viewer | ||||
|         gnome-maps # map viewer | ||||
|         gnome-tour # welcome tour | ||||
|         hitori # sudoku game | ||||
|  | @ -32,7 +32,14 @@ | |||
|       ]; | ||||
|       services = { | ||||
|         # Enable CUPS to print documents. | ||||
|         printing.enable = true; | ||||
|         printing = { | ||||
|           enable = true; | ||||
|           drivers = [ | ||||
|             pkgs.hplip | ||||
|             pkgs.gutenprint | ||||
|             pkgs.gutenprintBin | ||||
|           ]; | ||||
|         }; | ||||
| 
 | ||||
|         xserver = { | ||||
|           # Enable the X11 windowing system. | ||||
|  |  | |||
|  | @ -136,6 +136,8 @@ in { | |||
|       }; | ||||
|       accounts = { | ||||
|         zfs_notifications = { | ||||
|           auth = true; | ||||
|           tls = true; | ||||
|           host = config.host.storage.notifications.host; | ||||
|           passwordeval = "cat ${config.host.storage.notifications.tokenFile}"; | ||||
|           user = config.host.storage.notifications.user; | ||||
|  | @ -149,14 +151,13 @@ in { | |||
|       autoSnapshot.enable = true; | ||||
| 
 | ||||
|       zed = lib.mkIf config.host.storage.notifications.enable { | ||||
|         # this option is broken we are just going to disable it | ||||
|         enableMail = false; | ||||
|         enableMail = true; | ||||
| 
 | ||||
|         settings = { | ||||
|           ZED_DEBUG_LOG = "/tmp/zed.debug.log"; | ||||
|           ZED_EMAIL_ADDR = [config.host.storage.notifications.to]; | ||||
|           ZED_EMAIL_PROG = "${pkgs.msmtp}/bin/msmtp"; | ||||
|           ZED_EMAIL_OPTS = "@ADDRESS@"; | ||||
|           ZED_EMAIL_OPTS = "-a zfs_notifications @ADDRESS@"; | ||||
| 
 | ||||
|           ZED_NOTIFY_INTERVAL_SECS = 3600; | ||||
|           ZED_NOTIFY_VERBOSE = true; | ||||
|  |  | |||
|  | @ -25,6 +25,18 @@ | |||
|           } | ||||
|         ]; | ||||
| 
 | ||||
|         # fixes issues with /var/lib/private not having the correct permissions https://github.com/nix-community/impermanence/issues/254 | ||||
|         system.activationScripts."createPersistentStorageDirs".deps = ["var-lib-private-permissions" "users" "groups"]; | ||||
|         system.activationScripts = { | ||||
|           "var-lib-private-permissions" = { | ||||
|             deps = ["specialfs"]; | ||||
|             text = '' | ||||
|               mkdir -p /persist/system/root/var/lib/private | ||||
|               chmod 0700 /persist/system/root/var/lib/private | ||||
|             ''; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         programs.fuse.userAllowOther = true; | ||||
| 
 | ||||
|         boot.initrd.postResumeCommands = lib.mkAfter '' | ||||
|  |  | |||
|  | @ -28,10 +28,6 @@ | |||
|         }; | ||||
|       })) | ||||
|       (lib.mkIf config.host.impermanence.enable { | ||||
|         # TODO: move this somewhere common | ||||
|         systemd.tmpfiles.rules = [ | ||||
|           "d /var/lib/private 0700 root root" | ||||
|         ]; | ||||
|         environment.persistence."/persist/system/root" = { | ||||
|           enable = true; | ||||
|           hideMounts = true; | ||||
|  |  | |||
							
								
								
									
										54
									
								
								modules/nixos-modules/server/actual.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								modules/nixos-modules/server/actual.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   dataDirectory = "/var/lib/actual/"; | ||||
| in { | ||||
|   options.services.actual = { | ||||
|     subdomain = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "actual"; | ||||
|       description = "subdomain of base domain that actual will be hosted at"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.actual.enable (lib.mkMerge [ | ||||
|     { | ||||
|       systemd.tmpfiles.rules = [ | ||||
|         "d ${dataDirectory} 2770 actual actual" | ||||
|       ]; | ||||
|       host = { | ||||
|         reverse_proxy.subdomains.${config.services.actual.subdomain} = { | ||||
|           target = "http://localhost:${toString config.services.actual.settings.port}"; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       services.actual = { | ||||
|         settings = { | ||||
|           ACTUAL_DATA_DIR = dataDirectory; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|     (lib.mkIf config.services.fail2ban.enable { | ||||
|       # TODO: configuration for fail2ban for actual | ||||
|     }) | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = config.services.actual.settings.ACTUAL_DATA_DIR == dataDirectory; | ||||
|           message = "actual data location does not match persistence"; | ||||
|         } | ||||
|       ]; | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = dataDirectory; | ||||
|             user = "actual"; | ||||
|             group = "actual"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
|  | @ -1,72 +0,0 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   dnsPort = 53; | ||||
| in { | ||||
|   options.host.adguardhome = { | ||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; | ||||
|     directory = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "/var/lib/AdGuardHome/"; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf config.host.adguardhome.enable (lib.mkMerge [ | ||||
|     { | ||||
|       services.adguardhome = { | ||||
|         enable = true; | ||||
|         mutableSettings = false; | ||||
|         settings = { | ||||
|           dns = { | ||||
|             bootstrap_dns = [ | ||||
|               "1.1.1.1" | ||||
|               "9.9.9.9" | ||||
|             ]; | ||||
|             upstream_dns = [ | ||||
|               "dns.quad9.net" | ||||
|             ]; | ||||
|           }; | ||||
|           filtering = { | ||||
|             protection_enabled = true; | ||||
|             filtering_enabled = true; | ||||
| 
 | ||||
|             parental_enabled = false; # Parental control-based DNS requests filtering. | ||||
|             safe_search = { | ||||
|               enabled = false; # Enforcing "Safe search" option for search engines, when possible. | ||||
|             }; | ||||
|           }; | ||||
|           # The following notation uses map | ||||
|           # to not have to manually create {enabled = true; url = "";} for every filter | ||||
|           # This is, however, fully optional | ||||
|           filters = | ||||
|             map (url: { | ||||
|               enabled = true; | ||||
|               url = url; | ||||
|             }) [ | ||||
|               "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt" | ||||
|               "https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt" # The Big List of Hacked Malware Web Sites | ||||
|               "https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt" # malicious url blocklist | ||||
|             ]; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       networking.firewall.allowedTCPPorts = [ | ||||
|         dnsPort | ||||
|       ]; | ||||
|     } | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         enable = true; | ||||
|         hideMounts = true; | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = config.host.adguardhome.directory; | ||||
|             user = "adguardhome"; | ||||
|             group = "adguardhome"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
|  | @ -8,9 +8,11 @@ | |||
|     ./jellyfin.nix | ||||
|     ./forgejo.nix | ||||
|     ./searx.nix | ||||
|     ./virt-home-assistant.nix | ||||
|     ./adguardhome.nix | ||||
|     ./home-assistant.nix | ||||
|     ./wyoming.nix | ||||
|     ./immich.nix | ||||
|     ./qbittorent.nix | ||||
|     ./paperless.nix | ||||
|     ./actual.nix | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -16,20 +16,6 @@ in { | |||
|             failregex = "limiting requests, excess:.* by zone.*client: <HOST>" | ||||
|           '') | ||||
|         ); | ||||
|         # "fail2ban/filter.d/hass.local".text = lib.mkIf config.services.home-assistant.enable ( | ||||
|         #   pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|         #     [INCLUDES] | ||||
|         #     before = common.conf | ||||
| 
 | ||||
|         #     [Definition] | ||||
|         #     failregex = ^%(__prefix_line)s.*Login attempt or request with invalid authentication from <HOST>.*$ | ||||
| 
 | ||||
|         #     ignoreregex = | ||||
| 
 | ||||
|         #     [Init] | ||||
|         #     datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S | ||||
|         #   '') | ||||
|         # ); | ||||
|       }; | ||||
| 
 | ||||
|       services.fail2ban = { | ||||
|  | @ -61,16 +47,6 @@ in { | |||
|             bantime = 600; | ||||
|             maxretry = 5; | ||||
|           }; | ||||
|           # home-assistant-iptables.settings = lib.mkIf config.services.home-assistant.enable { | ||||
|           #   enabled = true; | ||||
|           #   filter = "hass"; | ||||
|           #   action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|           #   logpath = "${config.services.home-assistant.configDir}/*.log"; | ||||
|           #   backend = "auto"; | ||||
|           #   findtime = 600; | ||||
|           #   bantime = 600; | ||||
|           #   maxretry = 5; | ||||
|           # }; | ||||
|           # TODO; figure out if there is any fail2ban things we can do on searx | ||||
|           # searx-iptables.settings = lib.mkIf config.services.searx.enable {}; | ||||
|         }; | ||||
|  |  | |||
|  | @ -28,6 +28,12 @@ in { | |||
|           extraUsers = { | ||||
|             ${db_user} = { | ||||
|               isClient = true; | ||||
|               createUser = true; | ||||
|             }; | ||||
|           }; | ||||
|           extraDatabases = { | ||||
|             ${db_user} = { | ||||
|               name = db_user; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  |  | |||
|  | @ -1,130 +1,229 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   inputs, | ||||
|   ... | ||||
| }: let | ||||
|   configDir = "/var/lib/hass"; | ||||
|   dbUser = "hass"; | ||||
| in { | ||||
|   options.host.home-assistant = { | ||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; | ||||
|   options.services.home-assistant = { | ||||
|     subdomain = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "subdomain of base domain that home-assistant will be hosted at"; | ||||
|       default = "home-assistant"; | ||||
|     }; | ||||
| 
 | ||||
|     database = lib.mkOption { | ||||
|       type = lib.types.enum [ | ||||
|         "builtin" | ||||
|         "postgres" | ||||
|       ]; | ||||
|       description = "what database do we want to use"; | ||||
|       default = "builtin"; | ||||
|     }; | ||||
| 
 | ||||
|   config = lib.mkIf config.host.home-assistant.enable (lib.mkMerge [ | ||||
|     { | ||||
|       virtualisation.libvirt = { | ||||
|         swtpm.enable = true; | ||||
|         connections."qemu:///session" = { | ||||
|           networks = [ | ||||
|             { | ||||
|               definition = inputs.nix-virt.lib.network.writeXML (inputs.nix-virt.lib.network.templates.bridge | ||||
|                 { | ||||
|                   uuid = "d57e37e2-311f-4e5c-a484-97c2210c2770"; | ||||
|                   subnet_byte = 71; | ||||
|                 }); | ||||
|               active = true; | ||||
|             } | ||||
|           ]; | ||||
|           domains = [ | ||||
|             { | ||||
|               definition = inputs.nix-virt.lib.domain.writeXML (inputs.nix-virt.lib.domain.templates.linux | ||||
|                 { | ||||
|                   name = "Home Assistant"; | ||||
|                   uuid = "c5cc0efc-6101-4c1d-be31-acbba203ccde"; | ||||
|                   memory = { | ||||
|                     count = 4; | ||||
|                     unit = "GiB"; | ||||
|     extensions = { | ||||
|       sonos = { | ||||
|         enable = lib.mkEnableOption "enable the sonos plugin"; | ||||
|         port = lib.mkOption { | ||||
|           type = lib.types.int; | ||||
|           default = 1400; | ||||
|           description = "what port to use for sonos discovery"; | ||||
|         }; | ||||
|                   # storage_vol = { | ||||
|                   #   pool = "MyPool"; | ||||
|                   #   volume = "Penguin.qcow2"; | ||||
|                   # }; | ||||
|                 }); | ||||
|             } | ||||
|       }; | ||||
|       jellyfin = { | ||||
|         enable = lib.mkEnableOption "enable the jellyfin plugin"; | ||||
|       }; | ||||
|       wyoming = { | ||||
|         enable = lib.mkEnableOption "enable wyoming"; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [ | ||||
|     { | ||||
|       host = { | ||||
|         reverse_proxy.subdomains.${config.services.home-assistant.subdomain} = { | ||||
|           target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; | ||||
| 
 | ||||
|           websockets.enable = true; | ||||
|           forwardHeaders.enable = true; | ||||
| 
 | ||||
|           extraConfig = '' | ||||
|             add_header Upgrade $http_upgrade; | ||||
|             add_header Connection \"upgrade\"; | ||||
| 
 | ||||
|             proxy_buffering off; | ||||
| 
 | ||||
|             proxy_read_timeout 90; | ||||
|           ''; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       services.home-assistant = { | ||||
|         configDir = configDir; | ||||
|         extraComponents = [ | ||||
|           "default_config" | ||||
|           "esphome" | ||||
|           "met" | ||||
|           "radio_browser" | ||||
|           "isal" | ||||
|           "zha" | ||||
|           "webostv" | ||||
|           "tailscale" | ||||
|           "syncthing" | ||||
|           "analytics_insights" | ||||
|           "unifi" | ||||
|           "openweathermap" | ||||
|           "ollama" | ||||
|           "mobile_app" | ||||
|           "logbook" | ||||
|           "ssdp" | ||||
|           "usb" | ||||
|           "webhook" | ||||
|           "bluetooth" | ||||
|           "dhcp" | ||||
|           "energy" | ||||
|           "history" | ||||
|           "backup" | ||||
|           "assist_pipeline" | ||||
|           "conversation" | ||||
|           "sun" | ||||
|           "zeroconf" | ||||
|           "cpuspeed" | ||||
|         ]; | ||||
|         config = { | ||||
|           http = { | ||||
|             server_port = 8123; | ||||
|             use_x_forwarded_for = true; | ||||
|             trusted_proxies = ["127.0.0.1" "::1"]; | ||||
|             ip_ban_enabled = true; | ||||
|             login_attempts_threshold = 10; | ||||
|           }; | ||||
|           homeassistant = { | ||||
|             external_url = "https://${config.services.home-assistant.subdomain}.${config.host.reverse_proxy.hostname}"; | ||||
|             # internal_url = "http://192.168.1.2:8123"; | ||||
|           }; | ||||
|           recorder.db_url = "postgresql://@/${dbUser}"; | ||||
|           "automation manual" = []; | ||||
|           "automation ui" = "!include automations.yaml"; | ||||
|           mobile_app = {}; | ||||
|         }; | ||||
|         extraPackages = python3Packages: | ||||
|           with python3Packages; [ | ||||
|             hassil | ||||
|             numpy | ||||
|             gtts | ||||
|           ]; | ||||
|       }; | ||||
| 
 | ||||
|       # TODO: configure /var/lib/hass/secrets.yaml via sops | ||||
| 
 | ||||
|       networking.firewall.allowedUDPPorts = [ | ||||
|         1900 | ||||
|       ]; | ||||
| 
 | ||||
|       systemd.tmpfiles.rules = [ | ||||
|         "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" | ||||
|       ]; | ||||
|     } | ||||
|     (lib.mkIf (config.services.home-assistant.extensions.sonos.enable) { | ||||
|       services.home-assistant.extraComponents = ["sonos"]; | ||||
|       networking.firewall.allowedTCPPorts = [ | ||||
|         config.services.home-assistant.extensions.sonos.port | ||||
|       ]; | ||||
|     }) | ||||
|     (lib.mkIf (config.services.home-assistant.extensions.jellyfin.enable) { | ||||
|       services.home-assistant.extraComponents = ["jellyfin"]; | ||||
|       # TODO: configure port, address, and login information here | ||||
|     }) | ||||
|     (lib.mkIf (config.services.home-assistant.extensions.wyoming.enable) { | ||||
|       services.home-assistant.extraComponents = ["wyoming"]; | ||||
|       services.wyoming.enable = true; | ||||
|     }) | ||||
|     (lib.mkIf (config.services.home-assistant.database == "postgres") { | ||||
|       host = { | ||||
|         postgres = { | ||||
|           enable = true; | ||||
|           extraUsers = { | ||||
|             ${dbUser} = { | ||||
|               isClient = true; | ||||
|               createUser = true; | ||||
|             }; | ||||
|           }; | ||||
|           extraDatabases = { | ||||
|             ${dbUser} = { | ||||
|               name = dbUser; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       # systemd.tmpfiles.rules = [ | ||||
|       #   "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" | ||||
|       # ]; | ||||
|       # services.home-assistant = { | ||||
|       #   enable = true; | ||||
|       #   configDir = configDir; | ||||
|       #   extraComponents = [ | ||||
|       #     "met" | ||||
|       #     "radio_browser" | ||||
|       #     "isal" | ||||
|       #     "zha" | ||||
|       #     "jellyfin" | ||||
|       #     "webostv" | ||||
|       #     "tailscale" | ||||
|       #     "syncthing" | ||||
|       #     "sonos" | ||||
|       #     "analytics_insights" | ||||
|       #     "unifi" | ||||
|       #     "openweathermap" | ||||
|       #   ]; | ||||
|       #   config = { | ||||
|       #     http = { | ||||
|       #       server_port = 8082; | ||||
|       #       use_x_forwarded_for = true; | ||||
|       #       trusted_proxies = ["127.0.0.1" "::1"]; | ||||
|       #       ip_ban_enabled = true; | ||||
|       #       login_attempts_threshold = 10; | ||||
|       #     }; | ||||
|       #     # recorder.db_url = "postgresql://@/${db_user}"; | ||||
|       #     "automation manual" = []; | ||||
|       #     "automation ui" = "!include automations.yaml"; | ||||
|       #   }; | ||||
|       #   extraPackages = python3Packages: | ||||
|       #     with python3Packages; [ | ||||
|       #       hassil | ||||
|       #       numpy | ||||
|       #       gtts | ||||
|       #     ]; | ||||
|       # }; | ||||
|       # host = { | ||||
|       #   reverse_proxy.subdomains.${config.host.home-assistant.subdomain} = { | ||||
|       #     target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; | ||||
|       services.home-assistant = { | ||||
|         extraPackages = python3Packages: | ||||
|           with python3Packages; [ | ||||
|             psycopg2 | ||||
|           ]; | ||||
|       }; | ||||
| 
 | ||||
|       #     websockets.enable = true; | ||||
|       #     forwardHeaders.enable = true; | ||||
|       systemd.services.home-assistant = { | ||||
|         requires = [ | ||||
|           config.systemd.services.postgresql.name | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|     (lib.mkIf config.services.fail2ban.enable { | ||||
|       environment.etc = { | ||||
|         "fail2ban/filter.d/hass.local".text = lib.mkIf config.services.home-assistant.enable ( | ||||
|           pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|             [INCLUDES] | ||||
|             before = common.conf | ||||
| 
 | ||||
|       #     extraConfig = '' | ||||
|       #       add_header Upgrade $http_upgrade; | ||||
|       #       add_header Connection \"upgrade\"; | ||||
|             [Definition] | ||||
|             failregex = ^%(__prefix_line)s.*Login attempt or request with invalid authentication from <HOST>.*$ | ||||
| 
 | ||||
|       #       proxy_buffering off; | ||||
|             ignoreregex = | ||||
| 
 | ||||
|       #       proxy_read_timeout 90; | ||||
|       #     ''; | ||||
|       #   }; | ||||
|       # }; | ||||
|     } | ||||
|             [Init] | ||||
|             datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S | ||||
|           '') | ||||
|         ); | ||||
|       }; | ||||
| 
 | ||||
|       services.fail2ban = { | ||||
|         jails = { | ||||
|           home-assistant-iptables.settings = lib.mkIf config.services.home-assistant.enable { | ||||
|             enabled = true; | ||||
|             filter = "hass"; | ||||
|             action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|             logpath = "${config.services.home-assistant.configDir}/*.log"; | ||||
|             backend = "auto"; | ||||
|             findtime = 600; | ||||
|             bantime = 600; | ||||
|             maxretry = 5; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }) | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       # assertions = [ | ||||
|       #   { | ||||
|       #     assertion = config.services.home-assistant.configDir == configDir; | ||||
|       #     message = "home assistant config directory does not match persistence"; | ||||
|       #   } | ||||
|       # ]; | ||||
|       # environment.persistence."/persist/system/root" = { | ||||
|       #   enable = true; | ||||
|       #   hideMounts = true; | ||||
|       #   directories = [ | ||||
|       #     { | ||||
|       #       directory = configDir; | ||||
|       #       user = "hass"; | ||||
|       #       group = "hass"; | ||||
|       #     } | ||||
|       #   ]; | ||||
|       # }; | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = config.services.home-assistant.configDir == configDir; | ||||
|           message = "home assistant config directory does not match persistence"; | ||||
|         } | ||||
|       ]; | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         enable = true; | ||||
|         hideMounts = true; | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = configDir; | ||||
|             user = "hass"; | ||||
|             group = "hass"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
|  |  | |||
|  | @ -52,10 +52,15 @@ in { | |||
|         ]; | ||||
| 
 | ||||
|         networking.firewall.allowedTCPPorts = [jellyfinPort dlanPort]; | ||||
| 
 | ||||
|         systemd.tmpfiles.rules = [ | ||||
|           "d ${config.services.jellyfin.media_directory} 2770 jellyfin jellyfin_media" | ||||
|           "A ${config.services.jellyfin.media_directory} -    -        -               - u:jellyfin:rwX,g:jellyfin_media:rwX,o::-" | ||||
|         ]; | ||||
|       } | ||||
|       (lib.mkIf config.services.fail2ban.enable { | ||||
|         environment.etc = { | ||||
|           "fail2ban/filter.d/jellyfin.local".text = lib.mkIf config.services.jellyfin.enable ( | ||||
|           "fail2ban/filter.d/jellyfin.local".text = ( | ||||
|             pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|               [Definition] | ||||
|               failregex = "^.*Authentication request for .* has been denied \\\(IP: \"<ADDR>\"\\\)\\\." | ||||
|  | @ -65,7 +70,7 @@ in { | |||
| 
 | ||||
|         services.fail2ban = { | ||||
|           jails = { | ||||
|             jellyfin-iptables.settings = lib.mkIf config.services.jellyfin.enable { | ||||
|             jellyfin-iptables.settings = { | ||||
|               enabled = true; | ||||
|               filter = "jellyfin"; | ||||
|               action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|  |  | |||
							
								
								
									
										110
									
								
								modules/nixos-modules/server/paperless.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								modules/nixos-modules/server/paperless.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,110 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: let | ||||
|   dataDir = "/var/lib/paperless"; | ||||
| in { | ||||
|   options.services.paperless = { | ||||
|     subdomain = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "subdomain of base domain that paperless will be hosted at"; | ||||
|       default = "paperless"; | ||||
|     }; | ||||
|     database = { | ||||
|       user = lib.mkOption { | ||||
|         type = lib.types.str; | ||||
|         description = "what is the user and database that we are going to use for paperless"; | ||||
|         default = "paperless"; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.paperless.enable (lib.mkMerge [ | ||||
|     { | ||||
|       host = { | ||||
|         reverse_proxy.subdomains.${config.services.paperless.subdomain} = { | ||||
|           target = "http://${config.services.paperless.address}:${toString config.services.paperless.port}"; | ||||
| 
 | ||||
|           websockets.enable = true; | ||||
|           forwardHeaders.enable = true; | ||||
| 
 | ||||
|           extraConfig = '' | ||||
|             # allow large file uploads | ||||
|             client_max_body_size 50000M; | ||||
|           ''; | ||||
|         }; | ||||
|         postgres = { | ||||
|           enable = true; | ||||
|           extraUsers = { | ||||
|             ${config.services.paperless.database.user} = { | ||||
|               isClient = true; | ||||
|               createUser = true; | ||||
|             }; | ||||
|           }; | ||||
|           extraDatabases = { | ||||
|             ${config.services.paperless.database.user} = { | ||||
|               name = config.services.paperless.database.user; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       services.paperless = { | ||||
|         configureTika = true; | ||||
|         settings = { | ||||
|           PAPERLESS_URL = "https://${config.services.paperless.subdomain}.${config.host.reverse_proxy.hostname}"; | ||||
| 
 | ||||
|           PAPERLESS_DBENGINE = "postgresql"; | ||||
|           PAPERLESS_DBHOST = "/run/postgresql"; | ||||
|           PAPERLESS_DBNAME = config.services.paperless.database.user; | ||||
|           PAPERLESS_DBUSER = config.services.paperless.database.user; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|     (lib.mkIf config.services.fail2ban.enable { | ||||
|       environment.etc = { | ||||
|         "fail2ban/filter.d/paperless.local".text = ( | ||||
|           pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|             [Definition] | ||||
|             failregex = Login failed for user `.*` from (?:IP|private IP) `<HOST>`\.$ | ||||
|             ignoreregex = | ||||
| 
 | ||||
|           '') | ||||
|         ); | ||||
|       }; | ||||
| 
 | ||||
|       services.fail2ban = { | ||||
|         jails = { | ||||
|           paperless.settings = { | ||||
|             enabled = true; | ||||
|             filter = "paperless"; | ||||
|             action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|             logpath = "${config.services.paperless.dataDir}/log/*.log"; | ||||
|             backend = "auto"; | ||||
|             findtime = 600; | ||||
|             bantime = 600; | ||||
|             maxretry = 5; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }) | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = config.services.paperless.dataDir == dataDir; | ||||
|           message = "paperless data location does not match persistence"; | ||||
|         } | ||||
|       ]; | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = dataDir; | ||||
|             user = "paperless"; | ||||
|             group = "paperless"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
|  | @ -4,7 +4,7 @@ | |||
|   ... | ||||
| }: { | ||||
|   options.host.podman = { | ||||
|     enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; | ||||
|     enable = lib.mkEnableOption "should podman be enabled on this computer"; | ||||
|     macvlan = { | ||||
|       subnet = lib.mkOption { | ||||
|         type = lib.types.str; | ||||
|  |  | |||
|  | @ -1,115 +1,20 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   qbittorent_data_directory = "/var/lib/qbittorrent"; | ||||
|   qbittorent_profile_directory = "/var/lib/qBittorrent/"; | ||||
| in { | ||||
|   options.services.qbittorrent = { | ||||
|     enable = lib.mkEnableOption "should the headless qbittorrent service be enabled"; | ||||
| 
 | ||||
|     dataDir = lib.mkOption { | ||||
|       type = lib.types.path; | ||||
|       default = "/var/lib/qbittorrent"; | ||||
|       description = lib.mdDoc '' | ||||
|         The directory where qBittorrent stores its data files. | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     mediaDir = lib.mkOption { | ||||
|       type = lib.types.path; | ||||
|       description = lib.mdDoc '' | ||||
|         The directory to create to store qbittorrent media. | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     user = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "qbittorrent"; | ||||
|       description = lib.mdDoc '' | ||||
|         User account under which qBittorrent runs. | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     group = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "qbittorrent"; | ||||
|       description = lib.mdDoc '' | ||||
|         Group under which qBittorrent runs. | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     webPort = lib.mkOption { | ||||
|       type = lib.types.port; | ||||
|       default = 8080; | ||||
|       description = lib.mdDoc '' | ||||
|         qBittorrent web UI port. | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|     openFirewall = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = false; | ||||
|       description = "Open services.qBittorrent.webPort to the outside network."; | ||||
|     }; | ||||
| 
 | ||||
|     package = lib.mkOption { | ||||
|       type = lib.types.package; | ||||
|       default = pkgs.qbittorrent-nox; | ||||
|       defaultText = lib.literalExpression "pkgs.qbittorrent-nox"; | ||||
|       description = "The qbittorrent package to use."; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.qbittorrent.enable (lib.mkMerge [ | ||||
|     { | ||||
|       networking.firewall = lib.mkIf config.services.qbittorrent.openFirewall { | ||||
|         allowedTCPPorts = [config.services.qbittorrent.webPort]; | ||||
|       }; | ||||
| 
 | ||||
|       systemd.services.qbittorrent = { | ||||
|         # based on the plex.nix service module and | ||||
|         # https://github.com/qbittorrent/qBittorrent/blob/master/dist/unix/systemd/qbittorrent-nox%40.service.in | ||||
|         description = "qBittorrent-nox service"; | ||||
|         documentation = ["man:qbittorrent-nox(1)"]; | ||||
|         after = ["network.target"]; | ||||
|         wantedBy = ["multi-user.target"]; | ||||
| 
 | ||||
|         serviceConfig = { | ||||
|           Type = "simple"; | ||||
|           User = config.services.qbittorrent.user; | ||||
|           Group = config.services.qbittorrent.group; | ||||
| 
 | ||||
|           # Run the pre-start script with full permissions (the "!" prefix) so it | ||||
|           # can create the data directory if necessary. | ||||
|           ExecStartPre = let | ||||
|             preStartScript = pkgs.writeScript "qbittorrent-run-prestart" '' | ||||
|               #!${pkgs.bash}/bin/bash | ||||
| 
 | ||||
|               # Create data directory if it doesn't exist | ||||
|               if ! test -d "$QBT_PROFILE"; then | ||||
|                 echo "Creating initial qBittorrent data directory in: $QBT_PROFILE" | ||||
|                 install -d -m 0755 -o "${config.services.qbittorrent.user}" -g "${config.services.qbittorrent.group}" "$QBT_PROFILE" | ||||
|               fi | ||||
|             ''; | ||||
|           in "!${preStartScript}"; | ||||
| 
 | ||||
|           #ExecStart = "${pkgs.qbittorrent-nox}/bin/qbittorrent-nox"; | ||||
|           ExecStart = "${config.services.qbittorrent.package}/bin/qbittorrent-nox"; | ||||
|           # To prevent "Quit & shutdown daemon" from working; we want systemd to | ||||
|           # manage it! | ||||
|           #Restart = "on-success"; | ||||
|           #UMask = "0002"; | ||||
|           #LimitNOFILE = cfg.openFilesLimit; | ||||
|         }; | ||||
| 
 | ||||
|         environment = { | ||||
|           QBT_PROFILE = config.services.qbittorrent.dataDir; | ||||
|           QBT_WEBUI_PORT = toString config.services.qbittorrent.webPort; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       fileSystems."/persist/system/qbittorrent".neededForBoot = true; | ||||
| 
 | ||||
|  | @ -126,7 +31,7 @@ in { | |||
| 
 | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = config.services.qbittorrent.dataDir == qbittorent_data_directory; | ||||
|           assertion = config.services.qbittorrent.profileDir == qbittorent_profile_directory; | ||||
|           message = "qbittorrent data directory does not match persistence"; | ||||
|         } | ||||
|       ]; | ||||
|  | @ -135,7 +40,7 @@ in { | |||
|         "/persist/system/root" = { | ||||
|           directories = [ | ||||
|             { | ||||
|               directory = qbittorent_data_directory; | ||||
|               directory = qbittorent_profile_directory; | ||||
|               user = "qbittorrent"; | ||||
|               group = "qbittorrent"; | ||||
|             } | ||||
|  |  | |||
|  | @ -1,155 +0,0 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: { | ||||
|   options.services.virt-home-assistant = { | ||||
|     enable = lib.mkEnableOption "Wether to enable home assistant virtual machine"; | ||||
|     networkBridge = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "what network bridge should we attach to the image"; | ||||
|     }; | ||||
|     hostDevice = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "what host devices should be attached to the image"; | ||||
|     }; | ||||
|     initialVersion = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "what home assistant image version should we pull for initial instal"; | ||||
|       default = "15.0"; | ||||
|     }; | ||||
|     imageName = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "where should the image be installed to"; | ||||
|       default = "home-assistant.qcow2"; | ||||
|     }; | ||||
|     installLocation = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "where should the image be installed to"; | ||||
|       default = "/etc/hass"; | ||||
|     }; | ||||
|     virtualMachineName = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "what name should we give the virtual machine"; | ||||
|       default = "home-assistant"; | ||||
|     }; | ||||
|     subdomain = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       description = "subdomain of base domain that home-assistant will be hosted at"; | ||||
|       default = "home-assistant"; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf config.services.virt-home-assistant.enable (lib.mkMerge [ | ||||
|     { | ||||
|       # environment.systemPackages = with pkgs; [ | ||||
|       #   virt-manager | ||||
|       # ]; | ||||
| 
 | ||||
|       # TODO: move this to external module and just have an assertion here that its enabled | ||||
|       # enable virtualization on the system | ||||
|       virtualisation = { | ||||
|         libvirtd = { | ||||
|           enable = true; | ||||
|           qemu.ovmf.enable = true; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       # TODO: deactivation script? | ||||
|       # create service to install and start the container | ||||
|       systemd.services.virt-install-home-assistant = let | ||||
|         # TODO: all of these need to be escaped to be used in commands reliably | ||||
|         bridgedNetwork = config.services.virt-home-assistant.networkBridge; | ||||
|         hostDevice = config.services.virt-home-assistant.hostDevice; | ||||
|         virtualMachineName = config.services.virt-home-assistant.virtualMachineName; | ||||
|         imageName = config.services.virt-home-assistant.imageName; | ||||
|         installLocation = config.services.virt-home-assistant.installLocation; | ||||
|         installImage = "${installLocation}/${imageName}"; | ||||
|         initialVersion = config.services.virt-home-assistant.initialVersion; | ||||
| 
 | ||||
|         home-assistant-qcow2 = pkgs.fetchurl { | ||||
|           name = "home-assistant.qcow2"; | ||||
|           url = "https://github.com/home-assistant/operating-system/releases/download/${initialVersion}/haos_ova-${initialVersion}.qcow2.xz"; | ||||
|           hash = "sha256-V1BEjvvLNbMMKJVyMCmipjQ/3owoJteeVxoF9LDHo1U="; | ||||
|           postFetch = '' | ||||
|             cp $out src.xz | ||||
|             rm -r $out | ||||
|             ${pkgs.xz}/bin/unxz src.xz --stdout > $out/${imageName} | ||||
|           ''; | ||||
|         }; | ||||
| 
 | ||||
|         # Write a script to install the Home Assistant OS qcow2 image | ||||
|         virtInstallScript = pkgs.writeShellScriptBin "virt-install-hass" '' | ||||
|           # Copy the initial image out of the package store to the install location if we don't have one yet | ||||
|           if [ ! -f ${installImage} ]; then | ||||
|             cp ${home-assistant-qcow2} ${installLocation} | ||||
|           fi | ||||
| 
 | ||||
|           # Check if VM already exists, and other pre-conditions | ||||
|           if ! ${pkgs.libvirt}/bin/virsh list --all | grep -q ${virtualMachineName}; then | ||||
|             ${pkgs.virt-manager}/bin/virt-install --name ${virtualMachineName} \ | ||||
|               --description "Home Assistant OS" \ | ||||
|               --os-variant=generic \ | ||||
|               --boot uefi \ | ||||
|               --ram=2048 \ | ||||
|               --vcpus=2 \ | ||||
|               --import \ | ||||
|               --disk ${installImage},bus=sata \ | ||||
|               --network bridge=${bridgedNetwork} \ | ||||
|               --host-device ${hostDevice} \ | ||||
|               --graphics none | ||||
|             ${pkgs.libvirt}/bin/virsh autostart ${virtualMachineName} | ||||
|           fi | ||||
|         ''; | ||||
|       in { | ||||
|         description = "Install and start Home Assistant"; | ||||
|         wantedBy = ["multi-user.target"]; | ||||
|         after = ["local-fs.target"]; | ||||
|         requires = ["libvirtd.service"]; | ||||
|         serviceConfig.Type = "oneshot"; | ||||
|         serviceConfig = { | ||||
|           ExecStart = "${virtInstallScript}/bin/virt-install-hass"; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       # TODO: figure out what we need to proxy to the virtual image | ||||
|       # host = { | ||||
|       #   reverse_proxy.subdomains.${config.services.virt-home-assistant.subdomain} = { | ||||
|       #     target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; | ||||
| 
 | ||||
|       #     websockets.enable = true; | ||||
|       #     forwardHeaders.enable = true; | ||||
| 
 | ||||
|       #     extraConfig = '' | ||||
|       #       add_header Upgrade $http_upgrade; | ||||
|       #       add_header Connection \"upgrade\"; | ||||
| 
 | ||||
|       #       proxy_buffering off; | ||||
| 
 | ||||
|       #       proxy_read_timeout 90; | ||||
|       #     ''; | ||||
|       #   }; | ||||
|       # }; | ||||
|     } | ||||
|     (lib.mkIf config.services.fail2ban.enable { | ||||
|       # TODO: figure out how to write a config for this, prob based on nginx proxy logs? | ||||
|     }) | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       # assertions = [ | ||||
|       #   { | ||||
|       #     assertion = config.services.virt-home-assistant.installLocation == configDir; | ||||
|       #     message = "home assistant install location does not match persistence"; | ||||
|       #   } | ||||
|       # ]; | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         enable = true; | ||||
|         hideMounts = true; | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = config.services.virt-home-assistant.installLocation; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
							
								
								
									
										63
									
								
								modules/nixos-modules/server/wyoming.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								modules/nixos-modules/server/wyoming.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.services.wyoming.enable = lib.mkEnableOption "should wyoming be enabled on this device"; | ||||
|   config = lib.mkIf config.services.wyoming.enable (lib.mkMerge [ | ||||
|     { | ||||
|       services.wyoming = { | ||||
|         # Text to speech | ||||
|         piper = { | ||||
|           servers = { | ||||
|             "en" = { | ||||
|               enable = true; | ||||
|               # see https://github.com/rhasspy/rhasspy3/blob/master/programs/tts/piper/script/download.py | ||||
|               voice = "en-us-amy-low"; | ||||
|               uri = "tcp://0.0.0.0:10200"; | ||||
|               speaker = 0; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         # Speech to text | ||||
|         faster-whisper = { | ||||
|           servers = { | ||||
|             "en" = { | ||||
|               enable = true; | ||||
|               # see https://github.com/rhasspy/rhasspy3/blob/master/programs/asr/faster-whisper/script/download.py | ||||
|               model = "tiny-int8"; | ||||
|               language = "en"; | ||||
|               uri = "tcp://0.0.0.0:10300"; | ||||
|               device = "cpu"; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         openwakeword = { | ||||
|           enable = true; | ||||
|           uri = "tcp://0.0.0.0:10400"; | ||||
|           preloadModels = [ | ||||
|             "ok_nabu" | ||||
|           ]; | ||||
|           # TODO: custom models | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       # needs access to /proc/cpuinfo | ||||
|       systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset = lib.mkForce "all"; | ||||
|     } | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         enable = true; | ||||
|         hideMounts = true; | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = "/var/lib/private/wyoming"; | ||||
|             mode = "0700"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
|  | @ -11,6 +11,7 @@ in { | |||
|     { | ||||
|       systemd = lib.mkIf config.services.syncthing.enable { | ||||
|         tmpfiles.rules = [ | ||||
|           "A ${mountDir} -    -        -               - u:syncthing:rwX,g:syncthing:rwX,o::-" | ||||
|           "d ${mountDir} 2755 syncthing syncthing -" | ||||
|           "d ${config.services.syncthing.dataDir} 775 syncthing syncthing -" | ||||
|           "d ${config.services.syncthing.configDir} 755 syncthing syncthing -" | ||||
|  |  | |||
|  | @ -17,13 +17,14 @@ | |||
|     eve = 1002; | ||||
|     jellyfin = 2000; | ||||
|     forgejo = 2002; | ||||
|     adguardhome = 2003; | ||||
|     hass = 2004; | ||||
|     syncthing = 2007; | ||||
|     ollama = 2008; | ||||
|     git = 2009; | ||||
|     immich = 2010; | ||||
|     qbittorrent = 2011; | ||||
|     paperless = 2012; | ||||
|     actual = 2013; | ||||
|   }; | ||||
| 
 | ||||
|   gids = { | ||||
|  | @ -33,13 +34,14 @@ | |||
|     jellyfin_media = 2001; | ||||
|     jellyfin = 2000; | ||||
|     forgejo = 2002; | ||||
|     adguardhome = 2003; | ||||
|     hass = 2004; | ||||
|     syncthing = 2007; | ||||
|     ollama = 2008; | ||||
|     git = 2009; | ||||
|     immich = 2010; | ||||
|     qbittorrent = 2011; | ||||
|     paperless = 2012; | ||||
|     actual = 2013; | ||||
|   }; | ||||
| 
 | ||||
|   users = config.users.users; | ||||
|  | @ -127,12 +129,6 @@ in { | |||
|             group = config.users.users.forgejo.name; | ||||
|           }; | ||||
| 
 | ||||
|           adguardhome = { | ||||
|             uid = lib.mkForce uids.adguardhome; | ||||
|             isSystemUser = true; | ||||
|             group = config.users.users.adguardhome.name; | ||||
|           }; | ||||
| 
 | ||||
|           hass = { | ||||
|             uid = lib.mkForce uids.hass; | ||||
|             isSystemUser = true; | ||||
|  | @ -166,9 +162,21 @@ in { | |||
| 
 | ||||
|           qbittorrent = { | ||||
|             uid = lib.mkForce uids.qbittorrent; | ||||
|             isNormalUser = true; | ||||
|             isSystemUser = true; | ||||
|             group = config.users.users.qbittorrent.name; | ||||
|           }; | ||||
| 
 | ||||
|           paperless = { | ||||
|             uid = lib.mkForce uids.paperless; | ||||
|             isSystemUser = true; | ||||
|             group = config.users.users.paperless.name; | ||||
|           }; | ||||
| 
 | ||||
|           actual = { | ||||
|             uid = lib.mkForce uids.actual; | ||||
|             isSystemUser = true; | ||||
|             group = config.users.users.actual.name; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         groups = { | ||||
|  | @ -219,14 +227,6 @@ in { | |||
|             ]; | ||||
|           }; | ||||
| 
 | ||||
|           adguardhome = { | ||||
|             gid = lib.mkForce gids.adguardhome; | ||||
|             members = [ | ||||
|               users.adguardhome.name | ||||
|               # leyla | ||||
|             ]; | ||||
|           }; | ||||
| 
 | ||||
|           hass = { | ||||
|             gid = lib.mkForce gids.hass; | ||||
|             members = [ | ||||
|  | @ -273,6 +273,20 @@ in { | |||
|               leyla | ||||
|             ]; | ||||
|           }; | ||||
| 
 | ||||
|           paperless = { | ||||
|             gid = lib.mkForce gids.paperless; | ||||
|             members = [ | ||||
|               users.paperless.name | ||||
|             ]; | ||||
|           }; | ||||
| 
 | ||||
|           actual = { | ||||
|             gid = lib.mkForce gids.actual; | ||||
|             members = [ | ||||
|               users.actual.name | ||||
|             ]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| Subproject commit 1c5c059c0c7b6ce691993262fe10a2b63e1c31ba | ||||
| Subproject commit f016767c13aa36dde91503f7a9f01bdd02468045 | ||||
|  | @ -65,7 +65,7 @@ flake=${flake:-$target} | |||
| mode=${mode:-switch} | ||||
| user=${user:-$USER} | ||||
| 
 | ||||
| command="nixos-rebuild $mode --use-remote-sudo --ask-sudo-password --flake .#$flake" | ||||
| command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake" | ||||
| 
 | ||||
| if [[ $host ]]; | ||||
| then | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
|   nix-syncthing = inputs.nix-syncthing; | ||||
|   disko = inputs.disko; | ||||
|   impermanence = inputs.impermanence; | ||||
|   lix-module = inputs.lix-module; | ||||
|   # lix-module = inputs.lix-module; | ||||
| 
 | ||||
|   systems = [ | ||||
|     "aarch64-darwin" | ||||
|  | @ -83,7 +83,7 @@ in { | |||
|           impermanence.nixosModules.impermanence | ||||
|           home-manager.nixosModules.home-manager | ||||
|           disko.nixosModules.disko | ||||
|           lix-module.nixosModules.default | ||||
|           # lix-module.nixosModules.default | ||||
|           ../modules/nixos-modules | ||||
|           ../configurations/nixos/${host} | ||||
|         ]; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue