forked from jan-leila/nix-config
		
	Compare commits
	
		
			62 commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e1a5ddde95 | |||
| c0e2e7ba4a | |||
| 69ccbffd86 | |||
| f9c27c82b6 | |||
| e57c1df6e5 | |||
| df663e5438 | |||
| f91f20be7c | |||
| ec802a2462 | |||
| bb5c94ec2c | |||
| 81a6588537 | |||
| 758cbd17f7 | |||
| f72a6da013 | |||
| 7ad6a83dfa | |||
| c97d43957d | |||
| 5114f52607 | |||
| 30a042d709 | |||
| 89793fca6a | |||
| a8af8930fa | |||
| ecec04a9ce | |||
| 7f74060713 | |||
| c2435883f1 | |||
| 0f5507c328 | |||
| ad04be6534 | |||
| 4dd285c122 | |||
| 466926b919 | |||
| db8d36dadc | |||
| b17f8d49d5 | |||
| 455a98810a | |||
| 3f107f8d1e | |||
| 539af51473 | |||
| f21777b1fb | |||
| 290c0692bb | |||
| d19d535d85 | |||
| e8f7331b6c | |||
| ebf7ea3cf7 | |||
| dd165d48fe | |||
| 260e37e016 | |||
| 0c88746da1 | |||
| 46890110f8 | |||
| 290db94f42 | |||
| b05bfc31fe | |||
| 85a6f4a006 | |||
| 69ec14ef79 | |||
| 5ccfe1a337 | |||
| 62bb650878 | |||
| 488ef1e94a | |||
| 59dc4a7ee1 | |||
| 6afdcce951 | |||
| e895fa5edd | |||
| f02cb08570 | |||
| 352ca6fccf | |||
| c953571f2f | |||
| d87462981e | |||
| 75dcac8d17 | |||
| 80ad498f94 | |||
| 6d5a07e08f | |||
| 337f03b4e7 | |||
| a51a364ce9 | |||
| ee6d48fe49 | |||
| c81fa77a29 | |||
| 32c7086394 | |||
| f80ae02e47 | 
					 153 changed files with 3089 additions and 1922 deletions
				
			
		|  | @ -3,4 +3,12 @@ | |||
| 
 | ||||
| echo "restoring stashed changes" | ||||
| 
 | ||||
| git stash pop -q | ||||
| # Find the most recent pre-commit stash and restore it | ||||
| recent_stash=$(git stash list | grep "pre-commit-stash-" | head -n 1 | cut -d: -f1) | ||||
| 
 | ||||
| if [ -n "$recent_stash" ]; then | ||||
|     echo "Found recent pre-commit stash: $recent_stash" | ||||
|     git stash pop -q "$recent_stash" | ||||
| else | ||||
|     echo "No pre-commit stash found to restore" | ||||
| fi | ||||
|  |  | |||
							
								
								
									
										32
									
								
								.hooks/post-merge
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								.hooks/post-merge
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| #!/usr/bin/env nix-shell | ||||
| #! nix-shell -i bash ../shell.nix | ||||
| 
 | ||||
| # Get current branch name | ||||
| current_branch=$(git branch --show-current) | ||||
| 
 | ||||
| # Only perform actions if we're on main branch and a merge just completed | ||||
| if [ "$current_branch" = "main" ]; then | ||||
|     echo "Post-merge on main branch - running nix flake check" | ||||
|      | ||||
|     # Run nix flake check after merge into main | ||||
|     nix flake check | ||||
|      | ||||
|     if [ ! $? -eq 0 ]; then | ||||
|         echo "Warning: nix flake check failed after merge into main" | ||||
|         echo "Please fix the issues as soon as possible" | ||||
|     else | ||||
|         echo "nix flake check passed after merge" | ||||
|     fi | ||||
|      | ||||
|     # Check if there are any pre-commit stashes to restore | ||||
|     recent_stash=$(git stash list | grep "pre-commit-stash-" | head -n 1 | cut -d: -f1) | ||||
|      | ||||
|     if [ -n "$recent_stash" ]; then | ||||
|         echo "Post-merge: restoring pre-commit stash on main branch" | ||||
|         git stash pop -q "$recent_stash" | ||||
|     else | ||||
|         echo "Post-merge: no pre-commit stash to restore on main branch" | ||||
|     fi | ||||
| else | ||||
|     echo "Post-merge: no action needed on branch '$current_branch'" | ||||
| fi | ||||
|  | @ -1,14 +1,24 @@ | |||
| #!/usr/bin/env nix-shell | ||||
| #! nix-shell -i bash ../shell.nix | ||||
| 
 | ||||
| echo "stashing all uncommitted changes" | ||||
| git stash -q --keep-index | ||||
| # Get current branch name | ||||
| current_branch=$(git branch --show-current) | ||||
| 
 | ||||
| echo "checking flakes all compile" | ||||
| nix flake check | ||||
| echo "stashing all uncommitted changes with named stash (excluding hooks)" | ||||
| git stash push -q --keep-index -m "pre-commit-stash-$(date +%s)" -- ':!.hooks/' | ||||
| 
 | ||||
| if [ ! $? -eq 0 ]; then | ||||
| # Only run nix flake check if we're on main branch | ||||
| if [ "$current_branch" = "main" ]; then | ||||
|     echo "On main branch - checking flakes all compile" | ||||
|     nix flake check | ||||
| 
 | ||||
|     if [ ! $? -eq 0 ]; then | ||||
|         echo "Error: nix flake check failed on main branch" | ||||
|         exit 1 | ||||
|     fi | ||||
|     echo "nix flake check passed" | ||||
| else | ||||
|     echo "Not on main branch - skipping nix flake check" | ||||
| fi | ||||
| 
 | ||||
| echo "running linter" | ||||
|  |  | |||
							
								
								
									
										37
									
								
								.hooks/pre-merge-commit
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										37
									
								
								.hooks/pre-merge-commit
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| #!/usr/bin/env nix-shell | ||||
| #! nix-shell -i bash ../shell.nix | ||||
| 
 | ||||
| # Get the target branch (the branch being merged into) | ||||
| target_branch="" | ||||
| 
 | ||||
| # Check if we're in the middle of a merge | ||||
| if [ -f .git/MERGE_HEAD ]; then | ||||
|     # We're in a merge, check if the current branch is main | ||||
|     current_branch=$(git branch --show-current) | ||||
|     if [ "$current_branch" = "main" ]; then | ||||
|         target_branch="main" | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| # If we're merging into main, run nix flake check | ||||
| if [ "$target_branch" = "main" ]; then | ||||
|     echo "Merging into main branch - running nix flake check..." | ||||
|      | ||||
|     echo "stashing all uncommitted changes with named stash (excluding hooks)" | ||||
|     git stash push -q --keep-index -m "pre-merge-stash-$(date +%s)" -- ':!.hooks/' | ||||
| 
 | ||||
|     echo "checking flakes all compile" | ||||
|     nix flake check | ||||
| 
 | ||||
|     if [ ! $? -eq 0 ]; then | ||||
|         echo "Error: nix flake check failed. Merge aborted." | ||||
|         echo "Please fix the issues and try merging again." | ||||
|         exit 1 | ||||
|     fi | ||||
|      | ||||
|     echo "nix flake check passed. Merge can proceed." | ||||
| else | ||||
|     echo "Not merging into main branch, skipping nix flake check." | ||||
| fi | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										91
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										91
									
								
								README.md
									
										
									
									
									
								
							|  | @ -43,39 +43,66 @@ nix multi user, multi system, configuration with `sops` secret management, `home | |||
| - Look into this for auto rotating sops keys `https://technotim.live/posts/rotate-sops-encryption-keys/` | ||||
| - Look into this for npins https://jade.fyi/blog/pinning-nixos-with-npins/ | ||||
| - https://nixos-and-flakes.thiscute.world/ | ||||
| - proton mail now has an smtp server we could use that for our zfs and SMART test emails | ||||
| 
 | ||||
| # Tasks: | ||||
| 
 | ||||
| ## Chores: | ||||
| - [ ] test out crab hole service | ||||
| 
 | ||||
| ## 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/) | ||||
| - nfs export should be backed by the same values for server and client | ||||
| ## New Features | ||||
| - crab-hole | ||||
| - figure out why syncthing and jellyfins permissions don't propagate downwards | ||||
| - figure out steam vr things? | ||||
| - auto turn off on power loss - nut | ||||
| - zfs email after scrubbing # TODO: test this | ||||
| - SMART test with email results | ||||
| - 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 | ||||
| - zfs encryption FIDO2 2fa (look into shavee) | ||||
| - Secure Boot - https://github.com/nix-community/lanzaboote | ||||
| - 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 | ||||
| - ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix | ||||
| - panoramax instance | ||||
| - mastodon instance | ||||
| - rework the reverse_proxy.nix file so that it is a normally named service. Then also change it so that we can hook into it with both a base domain and a subdomain to make migrating to vpn accessible services easier | ||||
| - move searx, home-assistant, actual, jellyfin, paperless, and immich to only be accessible via vpn | ||||
| - make radarr, sonarr, and bazarr accessible over vpn | ||||
| - create some sort of service that allows uploading files to jellyfin | ||||
| 	- auto sort files into where they should go with some combination of filebot cli and picard cli | ||||
| - graphana accessible though tailscale | ||||
| - fix panoramax package | ||||
| - actual instance | ||||
| - intergrade radarr, sonarr, and bazarr | ||||
| - claude code MCP servers should bundle node with them so they work in all environments | ||||
| - [ ] 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/) | ||||
| - [ ] migrate away from flakes and move to npins | ||||
| 
 | ||||
| ## Broken things | ||||
| - [ ] figure out steam vr things? | ||||
| - [ ] whisper was having issues | ||||
| 
 | ||||
| ## Data Integrity | ||||
| - [ ] zfs email after scrubbing # TODO: test this | ||||
| - [ ] SMART test with email results | ||||
| - [ ] zfs encryption FIDO2 2fa (look into shavee) | ||||
| - [ ] rotate sops encryption keys periodically (and somehow sync between devices?) | ||||
| - [ ] Secure Boot - https://github.com/nix-community/lanzaboote | ||||
| - [ ] auto turn off on power loss - nut | ||||
| - [ ] secondary server with data sync. Maybe a Pi with a usb hdd enclosure and use rtcwake to only turn on once a week to sync data over tailscale with connection initiated from pi's side. We could probably put this at LZ. Hoping for it to draw only like $1 of power a month. Initial sync should probably be done here before we move it over because that will take a while. Data should be encrypted so that devices doesn't have access to it. Project will prob cost like $1800 | ||||
| 
 | ||||
| ## Data Access | ||||
| - [ ] nfs export should be backed by the same values for server and client | ||||
| - [ ] 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) | ||||
| - [ ] figure out why syncthing and jellyfins permissions don't propagate downwards | ||||
| - [ ] make radarr, sonarr, and bazarr accessible over vpn | ||||
| - [ ] move searx, home-assistant, actual, vikunja, jellyfin, paperless, and immich to only be accessible via vpn | ||||
| 
 | ||||
| ## Services | ||||
| - [ ] vikunja service for project management | ||||
| - [ ] Penpot services (need to make this custom) | ||||
| - [ ] minecraft server with old world file | ||||
| - [ ] Create Tor guard/relay server | ||||
| - [ ] mastodon instance | ||||
| - [ ] screeps server | ||||
| - [ ] storj server | ||||
| 
 | ||||
| ## DevOps | ||||
| - [ ] wake on LAN for updates | ||||
| - [ ] remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html | ||||
| - [ ] ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix | ||||
| - [ ] fix panoramax package | ||||
| - [ ] claude code MCP servers should bundle node with them so they work in all environments | ||||
| 
 | ||||
| ## Observability | ||||
| - [ ] graphana for dashboards | ||||
| - [ ] prometheus and loki for metric and log collection | ||||
| 	- [ ] zfs storage usage | ||||
| 	- [ ] zfs drive health status | ||||
| 	- [ ] service version lag | ||||
| 	- [ ] network/cpu/ram utilization | ||||
| 	- [ ] http latency | ||||
| 	- [ ] postgres db load | ||||
| 	- [ ] nginx queries | ||||
| - [ ] ntfy.sh for push notifications | ||||
| - [ ] kuma for uptime visualization | ||||
| 
 | ||||
| ## Packages | ||||
| - [ ] Custom private fork of MultiMC | ||||
|  | @ -1,12 +1,39 @@ | |||
| {pkgs, ...}: { | ||||
| { | ||||
|   osConfig, | ||||
|   lib, | ||||
|   ... | ||||
| }: { | ||||
|   config = { | ||||
|     gnome = lib.mkMerge [ | ||||
|       { | ||||
|         colorScheme = "prefer-dark"; | ||||
|         accentColor = "slate"; | ||||
|         clockFormat = "24h"; | ||||
|         nightLight = { | ||||
|           enable = true; | ||||
|           automatic = false; | ||||
|           fromTime = 12.0; | ||||
|           toTime = 11.999999999999; | ||||
|           temperature = 2700; | ||||
|         }; | ||||
|         extraWindowControls = true; | ||||
|         extensions = { | ||||
|           dash-to-panel = { | ||||
|             enable = true; | ||||
|           }; | ||||
|         }; | ||||
|       } | ||||
| 
 | ||||
|       (lib.mkIf (osConfig.networking.hostName == "horizon") { | ||||
|         displayScaling = 125; | ||||
|         experimentalFeatures = { | ||||
|           scaleMonitorFramebuffer = true; | ||||
|         }; | ||||
|       }) | ||||
|     ]; | ||||
| 
 | ||||
|     dconf = { | ||||
|       enable = true; | ||||
|       settings = { | ||||
|         "org/gnome/shell".enabled-extensions = [ | ||||
|           pkgs.gnomeExtensions.dash-to-panel.extensionUuid | ||||
|         ]; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ in { | |||
|     home.packages = lib.lists.optionals userConfig.isDesktopUser ( | ||||
|       with pkgs; [ | ||||
|         gnomeExtensions.dash-to-panel | ||||
|         claude-code | ||||
|       ] | ||||
|     ); | ||||
| 
 | ||||
|  | @ -31,9 +32,11 @@ in { | |||
|       (lib.mkIf (config.user.isDesktopUser || config.user.isTerminalUser) { | ||||
|         git = { | ||||
|           enable = true; | ||||
|           userName = "Eve"; | ||||
|           userEmail = "evesnrobins@gmail.com"; | ||||
|           extraConfig.init.defaultBranch = "main"; | ||||
|           settings = { | ||||
|             user.name = "Eve"; | ||||
|             user.email = "evesnrobins@gmail.com"; | ||||
|             init.defaultBranch = "main"; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         openssh = { | ||||
|  | @ -61,6 +64,22 @@ in { | |||
|         piper.enable = hardware.piperMouse.enable; | ||||
|         krita.enable = true; | ||||
|         ungoogled-chromium.enable = true; | ||||
| 
 | ||||
|         inkscape.enable = true; | ||||
|         obsidian.enable = true; | ||||
|         obs-studio.enable = true; | ||||
|         kdenlive.enable = true; | ||||
|         tor-browser.enable = true; | ||||
|         olympus.enable = true; | ||||
|         libreoffice.enable = true; | ||||
| 
 | ||||
|         claude-code.enable = osConfig.host.ai.enable; | ||||
| 
 | ||||
|         # Windows applications that we need to figure out how to install | ||||
|         guild-wars-2.enable = false; | ||||
|         vortex.enable = false; | ||||
|         dungeon-draft.enable = false; | ||||
|         vmware-workstation.enable = true; | ||||
|       }) | ||||
|     ]; | ||||
|   }; | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| {osConfig, ...}: { | ||||
|   impermanence.fallbackPersistence.enable = false; | ||||
| 
 | ||||
|   home = { | ||||
|     username = osConfig.users.users.git.name; | ||||
|     homeDirectory = osConfig.users.users.git.home; | ||||
|  |  | |||
|  | @ -1,31 +1,43 @@ | |||
| {pkgs, ...}: { | ||||
| {...}: { | ||||
|   config = { | ||||
|     gnome = { | ||||
|       extraWindowControls = true; | ||||
|       colorScheme = "prefer-dark"; | ||||
|       clockFormat = "24h"; | ||||
|       extensions = [ | ||||
|         pkgs.gnomeExtensions.dash-to-dock | ||||
|       ]; | ||||
|       nightLight = { | ||||
|         enable = true; | ||||
|         automatic = false; | ||||
|         fromTime = 12.0; | ||||
|         toTime = 11.999999999999; | ||||
|         temperature = 2700; | ||||
|       }; | ||||
|       extensions = { | ||||
|         dash-to-dock = { | ||||
|           enable = true; | ||||
|           options = { | ||||
|             "dock-position" = "LEFT"; | ||||
|             "intellihide-mode" = "ALL_WINDOWS"; | ||||
|             "show-trash" = false; | ||||
|             "require-pressure-to-show" = false; | ||||
|             "show-mounts" = false; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       hotkeys = { | ||||
|         "Open Terminal" = { | ||||
|           binding = "<Super>t"; | ||||
|           command = "kgx"; | ||||
|         }; | ||||
|         "Open Firefox" = { | ||||
|           binding = "<Super>f"; | ||||
|           command = "firefox"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     dconf = { | ||||
|       enable = true; | ||||
|       settings = { | ||||
|         "org/gnome/shell/extensions/dash-to-dock" = { | ||||
|           "dock-position" = "LEFT"; | ||||
|           "intellihide-mode" = "ALL_WINDOWS"; | ||||
|           "show-trash" = false; | ||||
|           "require-pressure-to-show" = false; | ||||
|           "show-mounts" = false; | ||||
|         }; | ||||
| 
 | ||||
|         "org/gnome/shell" = { | ||||
|           favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; | ||||
|           # app-picker-layout = | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ | |||
|   ]; | ||||
| 
 | ||||
|   config = { | ||||
|     impermanence.enable = osConfig.host.impermanence.enable; | ||||
| 
 | ||||
|     # Home Manager needs a bit of information about you and the paths it should | ||||
|     # manage. | ||||
|     home = { | ||||
|  | @ -87,7 +89,6 @@ | |||
|     # TODO: move this into a fonts module | ||||
|     home.packages = with pkgs; [ | ||||
|       aileron | ||||
|       nerd-fonts.open-dyslexic | ||||
|     ]; | ||||
|     fonts.fontconfig.enable = true; | ||||
|   }; | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf osConfig.host.impermanence.enable { | ||||
|   config = lib.mkIf (config.impermanence.enable) { | ||||
|     home.persistence."/persist/home/leyla" = { | ||||
|       directories = [ | ||||
|         "desktop" | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| in { | ||||
|   imports = [ | ||||
|     ./vscode | ||||
|     ./firefox.nix | ||||
|     ./firefox | ||||
|     ./direnv.nix | ||||
|     ./openssh.nix | ||||
|     ./git.nix | ||||
|  |  | |||
|  | @ -1,344 +0,0 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   inputs, | ||||
|   ... | ||||
| }: { | ||||
|   config = { | ||||
|     programs.firefox = { | ||||
|       profiles.leyla = { | ||||
|         settings = { | ||||
|           "browser.search.defaultenginename" = "Searx"; | ||||
|           "browser.search.order.1" = "Searx"; | ||||
|         }; | ||||
| 
 | ||||
|         search = { | ||||
|           force = true; | ||||
|           default = "Searx"; | ||||
|           engines = { | ||||
|             "Nix Packages" = { | ||||
|               urls = [ | ||||
|                 { | ||||
|                   template = "https://search.nixos.org/packages"; | ||||
|                   params = [ | ||||
|                     { | ||||
|                       name = "type"; | ||||
|                       value = "packages"; | ||||
|                     } | ||||
|                     { | ||||
|                       name = "query"; | ||||
|                       value = "{searchTerms}"; | ||||
|                     } | ||||
|                   ]; | ||||
|                 } | ||||
|               ]; | ||||
|               icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; | ||||
|               definedAliases = ["@np"]; | ||||
|             }; | ||||
|             "NixOS Wiki" = { | ||||
|               urls = [{template = "https://nixos.wiki/index.php?search={searchTerms}";}]; | ||||
|               icon = "https://nixos.wiki/favicon.png"; | ||||
|               updateInterval = 24 * 60 * 60 * 1000; # every day | ||||
|               definedAliases = ["@nw"]; | ||||
|             }; | ||||
|             "Searx" = { | ||||
|               urls = [{template = "https://search.jan-leila.com/?q={searchTerms}";}]; | ||||
|               icon = "https://nixos.wiki/favicon.png"; | ||||
|               updateInterval = 24 * 60 * 60 * 1000; # every day | ||||
|               definedAliases = ["@searx"]; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         extensions.packages = with inputs.firefox-addons.packages.${pkgs.system}; [ | ||||
|           bitwarden | ||||
|           terms-of-service-didnt-read | ||||
|           multi-account-containers | ||||
|           shinigami-eyes | ||||
| 
 | ||||
|           ublock-origin | ||||
|           sponsorblock | ||||
|           dearrow | ||||
|           df-youtube | ||||
|           return-youtube-dislikes | ||||
| 
 | ||||
|           privacy-badger | ||||
|           decentraleyes | ||||
|           clearurls | ||||
|           localcdn | ||||
| 
 | ||||
|           snowflake | ||||
| 
 | ||||
|           deutsch-de-language-pack | ||||
|           dictionary-german | ||||
| 
 | ||||
|           tab-session-manager | ||||
| 
 | ||||
|           # ( | ||||
|           #   buildFirefoxXpiAddon rec { | ||||
|           #     pname = "italiano-it-language-pack"; | ||||
|           #     version = "132.0.20241110.231641"; | ||||
|           #     addonId = "langpack-it@firefox.mozilla.org"; | ||||
|           #     url = "https://addons.mozilla.org/firefox/downloads/file/4392453/italiano_it_language_pack-${version}.xpi"; | ||||
|           #     sha256 = ""; | ||||
|           #     meta = with lib; | ||||
|           #     { | ||||
|           #       description = "Firefox Language Pack for Italiano (it) – Italian"; | ||||
|           #       license = licenses.mpl20; | ||||
|           #       mozPermissions = []; | ||||
|           #       platforms = platforms.all; | ||||
|           #     }; | ||||
|           #   } | ||||
|           # ) | ||||
|           # ( | ||||
|           #   buildFirefoxXpiAddon rec { | ||||
|           #     pname = "dizionario-italiano"; | ||||
|           #     version = "5.1"; | ||||
|           #     addonId = "it-IT@dictionaries.addons.mozilla.org"; | ||||
|           #     url = "https://addons.mozilla.org/firefox/downloads/file/1163874/dizionario_italiano-${version}.xpi"; | ||||
|           #     sha256 = ""; | ||||
|           #     meta = with lib; | ||||
|           #     { | ||||
|           #       description = "Add support for Italian to spellchecking"; | ||||
|           #       license = licenses.gpl3; | ||||
|           #       mozPermissions = []; | ||||
|           #       platforms = platforms.all; | ||||
|           #     }; | ||||
|           #   } | ||||
|           # ) | ||||
|         ]; | ||||
| 
 | ||||
|         settings = { | ||||
|           # Disable irritating first-run stuff | ||||
|           "browser.disableResetPrompt" = true; | ||||
|           "browser.download.panel.shown" = true; | ||||
|           "browser.feeds.showFirstRunUI" = false; | ||||
|           "browser.messaging-system.whatsNewPanel.enabled" = false; | ||||
|           "browser.rights.3.shown" = true; | ||||
|           "browser.shell.checkDefaultBrowser" = false; | ||||
|           "browser.shell.defaultBrowserCheckCount" = 1; | ||||
|           "browser.startup.homepage_override.mstone" = "ignore"; | ||||
|           "browser.uitour.enabled" = false; | ||||
|           "startup.homepage_override_url" = ""; | ||||
|           "trailhead.firstrun.didSeeAboutWelcome" = true; | ||||
|           "browser.bookmarks.restore_default_bookmarks" = false; | ||||
|           "browser.bookmarks.addedImportButton" = true; | ||||
|           "browser.newtabpage.activity-stream.feeds.section.topstories" = false; | ||||
| 
 | ||||
|           # Usage Experience | ||||
|           "browser.startup.homepage" = "about:home"; | ||||
|           "browser.download.useDownloadDir" = false; | ||||
|           "browser.uiCustomization.state" = builtins.toJSON { | ||||
|             "currentVersion" = 20; | ||||
|             "newElementCount" = 6; | ||||
|             "dirtyAreaCache" = [ | ||||
|               "nav-bar" | ||||
|               "PersonalToolbar" | ||||
|               "toolbar-menubar" | ||||
|               "TabsToolbar" | ||||
|               "unified-extensions-area" | ||||
|               "vertical-tabs" | ||||
|             ]; | ||||
|             "placements" = { | ||||
|               "widget-overflow-fixed-list" = []; | ||||
|               "unified-extensions-area" = [ | ||||
|                 # bitwarden | ||||
|                 "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" | ||||
|                 "ublock0_raymondhill_net-browser-action" | ||||
|                 "sponsorblocker_ajay_app-browser-action" | ||||
|                 "dearrow_ajay_app-browser-action" | ||||
|                 "jid1-mnnxcxisbpnsxq_jetpack-browser-action" | ||||
|                 "_testpilot-containers-browser-action" | ||||
|                 "addon_simplelogin-browser-action" | ||||
|                 "_74145f27-f039-47ce-a470-a662b129930a_-browser-action" | ||||
|                 "jid1-bofifl9vbdl2zq_jetpack-browser-action" | ||||
|                 "dfyoutube_example_com-browser-action" | ||||
|                 "_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action" | ||||
|                 "_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action" | ||||
|                 "_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browse-action" | ||||
|                 "jid0-3guet1r69sqnsrca5p8kx9ezc3u_jetpack-browser-action" | ||||
|               ]; | ||||
|               "nav-bar" = [ | ||||
|                 "back-button" | ||||
|                 "forward-button" | ||||
|                 "stop-reload-button" | ||||
|                 "urlbar-container" | ||||
|                 "downloads-button" | ||||
|                 "unified-extensions-button" | ||||
|                 "reset-pbm-toolbar-button" | ||||
|               ]; | ||||
|               "toolbar-menubar" = [ | ||||
|                 "menubar-items" | ||||
|               ]; | ||||
|               "TabsToolbar" = [ | ||||
|                 "firefox-view-button" | ||||
|                 "tabbrowser-tabs" | ||||
|                 "new-tab-button" | ||||
|                 "alltabs-button" | ||||
|               ]; | ||||
|               "vertical-tabs" = []; | ||||
|               "PersonalToolbar" = [ | ||||
|                 "import-button" | ||||
|                 "personal-bookmarks" | ||||
|               ]; | ||||
|             }; | ||||
|             "seen" = [ | ||||
|               "save-to-pocket-button" | ||||
|               "developer-button" | ||||
|               "privacy_privacy_com-browser-action" | ||||
|               "sponsorblocker_ajay_app-browser-action" | ||||
|               "ublock0_raymondhill_net-browser-action" | ||||
|               "addon_simplelogin-browser-action" | ||||
|               "dearrow_ajay_app-browser-action" | ||||
|               "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" | ||||
|               "_74145f27-f039-47ce-a470-a662b129930a_-browser-action" | ||||
|               "jid1-bofifl9vbdl2zq_jetpack-browser-action" | ||||
|               "dfyoutube_example_com-browser-action" | ||||
|               "_testpilot-containers-browser-action" | ||||
|               "_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action" | ||||
|               "jid1-mnnxcxisbpnsxq_jetpack-browser-action" | ||||
|               "_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action" | ||||
|               "_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browser-action" | ||||
|               "jid0-3guet1r69sqnsrca5p8kx9ezc3u_jetpack-browser-action" | ||||
|             ]; | ||||
|           }; | ||||
|           "browser.newtabpage.activity-stream.feeds.topsites" = false; | ||||
|           "browser.newtabpage.activity-stream.showSponsoredTopSites" = false; | ||||
|           "browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts" = false; | ||||
|           "browser.newtabpage.blocked" = lib.genAttrs [ | ||||
|             # Facebook | ||||
|             "4gPpjkxgZzXPVtuEoAL9Ig==" | ||||
|             # Reddit | ||||
|             "gLv0ja2RYVgxKdp0I5qwvA==" | ||||
|             # Amazon | ||||
|             "K00ILysCaEq8+bEqV/3nuw==" | ||||
|             # Twitter | ||||
|             "T9nJot5PurhJSy8n038xGA==" | ||||
|           ] (_: 1); | ||||
|           "identity.fxaccounts.enabled" = false; | ||||
| 
 | ||||
|           # Security | ||||
|           "privacy.trackingprotection.enabled" = true; | ||||
|           "dom.security.https_only_mode" = true; | ||||
| 
 | ||||
|           "extensions.formautofill.addresses.enabled" = false; | ||||
|           "extensions.formautofill.creditCards.enabled" = false; | ||||
|           "signon.rememberSignons" = false; | ||||
|           "privacy.sanitize.sanitizeOnShutdown" = true; | ||||
|           "privacy.clearOnShutdown_v2.cache" = true; | ||||
|           "privacy.clearOnShutdown_v2.cookiesAndStorage" = true; | ||||
|           "privacy.clearOnShutdown_v2.historyFormDataAndDownloads" = true; | ||||
|           "urlclassifier.trackingSkipURLs" = ""; | ||||
|           "urlclassifier.features.socialtracking.skipURLs" = ""; | ||||
|           "dom.security.https_only_mode_pbm" = true; | ||||
|           "dom.security.https_only_mode_error_page_user_suggestions" = true; | ||||
| 
 | ||||
|           # Disable telemetry | ||||
|           "app.shield.optoutstudies.enabled" = false; | ||||
|           "browser.discovery.enabled" = false; | ||||
|           "browser.newtabpage.activity-stream.feeds.telemetry" = false; | ||||
|           "browser.newtabpage.activity-stream.telemetry" = false; | ||||
|           "browser.ping-centre.telemetry" = false; | ||||
|           "datareporting.healthreport.service.enabled" = false; | ||||
|           "datareporting.healthreport.uploadEnabled" = false; | ||||
|           "datareporting.policy.dataSubmissionEnabled" = false; | ||||
|           "datareporting.sessions.current.clean" = true; | ||||
|           "devtools.onboarding.telemetry.logged" = false; | ||||
|           "toolkit.telemetry.archive.enabled" = false; | ||||
|           "toolkit.telemetry.bhrPing.enabled" = false; | ||||
|           "toolkit.telemetry.enabled" = false; | ||||
|           "toolkit.telemetry.firstShutdownPing.enabled" = false; | ||||
|           "toolkit.telemetry.hybridContent.enabled" = false; | ||||
|           "toolkit.telemetry.newProfilePing.enabled" = false; | ||||
|           "toolkit.telemetry.prompted" = 2; | ||||
|           "toolkit.telemetry.rejected" = true; | ||||
|           "toolkit.telemetry.reportingpolicy.firstRun" = false; | ||||
|           "toolkit.telemetry.server" = ""; | ||||
|           "toolkit.telemetry.shutdownPingSender.enabled" = false; | ||||
|           "toolkit.telemetry.unified" = false; | ||||
|           "toolkit.telemetry.unifiedIsOptIn" = false; | ||||
|           "toolkit.telemetry.updatePing.enabled" = false; | ||||
|         }; | ||||
| 
 | ||||
|         bookmarks = { | ||||
|           force = true; | ||||
|           settings = [ | ||||
|             { | ||||
|               name = "Media"; | ||||
|               url = "https://media.jan-leila.com/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Photos"; | ||||
|               url = "https://photos.jan-leila.com"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Git"; | ||||
|               url = "https://git.jan-leila.com/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Home Automation"; | ||||
|               url = "https://home.jan-leila.com/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Mail"; | ||||
|               url = "https://mail.protonmail.com"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Open Street Map"; | ||||
|               url = "https://www.openstreetmap.org/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Password Manager"; | ||||
|               url = "https://vault.bitwarden.com/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Mastodon"; | ||||
|               url = "https://mspsocial.net"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Linked In"; | ||||
|               url = "https://www.linkedin.com/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "Job Search"; | ||||
|               url = "https://www.jobsinnetwork.com/?state=cleaned_history&language%5B%5D=en&query=react&locations.countryCode%5B%5D=IT&locations.countryCode%5B%5D=DE&locations.countryCode%5B%5D=NL&experience%5B%5D=medior&experience%5B%5D=junior&page=1"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             { | ||||
|               name = "React Docs"; | ||||
|               url = "https://react.dev/"; | ||||
|               keyword = ""; | ||||
|               tags = [""]; | ||||
|             } | ||||
|             # Template | ||||
|             # { | ||||
|             #   name = ""; | ||||
|             #   url = ""; | ||||
|             #   keyword = ""; | ||||
|             #   tags = [""]; | ||||
|             # } | ||||
|           ]; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										149
									
								
								configurations/home-manager/leyla/packages/firefox/bookmarks.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								configurations/home-manager/leyla/packages/firefox/bookmarks.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,149 @@ | |||
| {...}: { | ||||
|   programs.firefox = { | ||||
|     profiles.leyla = { | ||||
|       bookmarks = { | ||||
|         force = true; | ||||
|         settings = [ | ||||
|           # Personal Services | ||||
|           { | ||||
|             name = "Media"; | ||||
|             url = "https://media.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Photos"; | ||||
|             url = "https://photos.jan-leila.com"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Git"; | ||||
|             url = "https://git.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Home Automation"; | ||||
|             url = "https://home.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Search"; | ||||
|             url = "https://search.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Budget"; | ||||
|             url = "https://budget.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Documents"; | ||||
|             url = "https://documents.jan-leila.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
| 
 | ||||
|           # Defiant Server Services | ||||
|           { | ||||
|             name = "QBittorrent"; | ||||
|             url = "http://defiant:8084"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Sonarr"; | ||||
|             url = "http://defiant:8989"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Radarr"; | ||||
|             url = "http://defiant:7878"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Bazarr"; | ||||
|             url = "http://defiant:6767"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Lidarr"; | ||||
|             url = "http://defiant:8686"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Jackett"; | ||||
|             url = "http://defiant:9117"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
|           { | ||||
|             name = "Crab-hole DNS"; | ||||
|             url = "http://defiant:8085"; | ||||
|             keyword = ""; | ||||
|             tags = ["defiant"]; | ||||
|           } | ||||
| 
 | ||||
|           # External Services | ||||
|           { | ||||
|             name = "Mail"; | ||||
|             url = "https://mail.protonmail.com"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Open Street Map"; | ||||
|             url = "https://www.openstreetmap.org/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Password Manager"; | ||||
|             url = "https://vault.bitwarden.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Mastodon"; | ||||
|             url = "https://mspsocial.net"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Linked In"; | ||||
|             url = "https://www.linkedin.com/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "Job Search"; | ||||
|             url = "https://www.jobsinnetwork.com/?state=cleaned_history&language%5B%5D=en&query=react&locations.countryCode%5B%5D=IT&locations.countryCode%5B%5D=DE&locations.countryCode%5B%5D=NL&experience%5B%5D=medior&experience%5B%5D=junior&page=1"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           { | ||||
|             name = "React Docs"; | ||||
|             url = "https://react.dev/"; | ||||
|             keyword = ""; | ||||
|             tags = [""]; | ||||
|           } | ||||
|           # Template | ||||
|           # { | ||||
|           #   name = ""; | ||||
|           #   url = ""; | ||||
|           #   keyword = ""; | ||||
|           #   tags = [""]; | ||||
|           # } | ||||
|         ]; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   inputs, | ||||
|   ... | ||||
| }: { | ||||
|   imports = [ | ||||
|     ./firefox.nix | ||||
|     ./bookmarks.nix | ||||
|     ./harden.nix | ||||
|   ]; | ||||
| 
 | ||||
|   config = { | ||||
|     programs.firefox = { | ||||
|       enable = true; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										221
									
								
								configurations/home-manager/leyla/packages/firefox/firefox.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								configurations/home-manager/leyla/packages/firefox/firefox.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,221 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   inputs, | ||||
|   ... | ||||
| }: { | ||||
|   programs.firefox = { | ||||
|     profiles.leyla = { | ||||
|       settings = { | ||||
|         "browser.search.defaultenginename" = "Searx"; | ||||
|         "browser.search.order.1" = "Searx"; | ||||
|       }; | ||||
| 
 | ||||
|       search = { | ||||
|         force = true; | ||||
|         default = "Searx"; | ||||
|         engines = { | ||||
|           "Nix Packages" = { | ||||
|             urls = [ | ||||
|               { | ||||
|                 template = "https://search.nixos.org/packages"; | ||||
|                 params = [ | ||||
|                   { | ||||
|                     name = "type"; | ||||
|                     value = "packages"; | ||||
|                   } | ||||
|                   { | ||||
|                     name = "query"; | ||||
|                     value = "{searchTerms}"; | ||||
|                   } | ||||
|                 ]; | ||||
|               } | ||||
|             ]; | ||||
|             icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; | ||||
|             definedAliases = ["@np"]; | ||||
|           }; | ||||
|           "NixOS Wiki" = { | ||||
|             urls = [{template = "https://nixos.wiki/index.php?search={searchTerms}";}]; | ||||
|             icon = "https://nixos.wiki/favicon.png"; | ||||
|             updateInterval = 24 * 60 * 60 * 1000; # every day | ||||
|             definedAliases = ["@nw"]; | ||||
|           }; | ||||
|           "Searx" = { | ||||
|             urls = [{template = "https://search.jan-leila.com/?q={searchTerms}";}]; | ||||
|             icon = "https://nixos.wiki/favicon.png"; | ||||
|             updateInterval = 24 * 60 * 60 * 1000; # every day | ||||
|             definedAliases = ["@searx"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       extensions.packages = with inputs.firefox-addons.packages.${pkgs.system}; [ | ||||
|         bitwarden | ||||
|         terms-of-service-didnt-read | ||||
|         multi-account-containers | ||||
|         shinigami-eyes | ||||
| 
 | ||||
|         ublock-origin | ||||
|         sponsorblock | ||||
|         dearrow | ||||
|         df-youtube | ||||
|         return-youtube-dislikes | ||||
| 
 | ||||
|         privacy-badger | ||||
|         decentraleyes | ||||
|         clearurls | ||||
|         localcdn | ||||
| 
 | ||||
|         snowflake | ||||
| 
 | ||||
|         deutsch-de-language-pack | ||||
|         dictionary-german | ||||
| 
 | ||||
|         tab-session-manager | ||||
| 
 | ||||
|         # (\ | ||||
|         #   buildFirefoxXpiAddon rec {\ | ||||
|         #     pname = "italiano-it-language-pack";\ | ||||
|         #     version = "132.0.20241110.231641";\ | ||||
|         #     addonId = "langpack-it@firefox.mozilla.org";\ | ||||
|         #     url = "https://addons.mozilla.org/firefox/downloads/file/4392453/italiano_it_language_pack-${version}.xpi";\ | ||||
|         #     sha256 = "";\ | ||||
|         #     meta = with lib;\ | ||||
|         #     {\ | ||||
|         #       description = "Firefox Language Pack for Italiano (it) – Italian";\ | ||||
|         #       license = licenses.mpl20;\ | ||||
|         #       mozPermissions = [];\ | ||||
|         #       platforms = platforms.all;\ | ||||
|         #     };\ | ||||
|         #   }\ | ||||
|         # )\ | ||||
|         # (\ | ||||
|         #   buildFirefoxXpiAddon rec {\ | ||||
|         #     pname = "dizionario-italiano";\ | ||||
|         #     version = "5.1";\ | ||||
|         #     addonId = "it-IT@dictionaries.addons.mozilla.org";\ | ||||
|         #     url = "https://addons.mozilla.org/firefox/downloads/file/1163874/dizionario_italiano-${version}.xpi";\ | ||||
|         #     sha256 = "";\ | ||||
|         #     meta = with lib;\ | ||||
|         #     {\ | ||||
|         #       description = "Add support for Italian to spellchecking";\ | ||||
|         #       license = licenses.gpl3;\ | ||||
|         #       mozPermissions = [];\ | ||||
|         #       platforms = platforms.all;\ | ||||
|         #     };\ | ||||
|         #   }\ | ||||
|         # )\ | ||||
|       ]; | ||||
| 
 | ||||
|       settings = { | ||||
|         # Disable irritating first-run stuff | ||||
|         "browser.disableResetPrompt" = true; | ||||
|         "browser.download.panel.shown" = true; | ||||
|         "browser.feeds.showFirstRunUI" = false; | ||||
|         "browser.messaging-system.whatsNewPanel.enabled" = false; | ||||
|         "browser.rights.3.shown" = true; | ||||
|         "browser.shell.checkDefaultBrowser" = false; | ||||
|         "browser.shell.defaultBrowserCheckCount" = 1; | ||||
|         "browser.startup.homepage_override.mstone" = "ignore"; | ||||
|         "browser.uitour.enabled" = false; | ||||
|         "startup.homepage_override_url" = ""; | ||||
|         "trailhead.firstrun.didSeeAboutWelcome" = true; | ||||
|         "browser.bookmarks.restore_default_bookmarks" = false; | ||||
|         "browser.bookmarks.addedImportButton" = true; | ||||
|         "browser.newtabpage.activity-stream.feeds.section.topstories" = false; | ||||
| 
 | ||||
|         # Usage Experience | ||||
|         "browser.startup.homepage" = "about:home"; | ||||
|         "browser.download.useDownloadDir" = false; | ||||
|         "browser.uiCustomization.state" = builtins.toJSON { | ||||
|           "currentVersion" = 20; | ||||
|           "newElementCount" = 6; | ||||
|           "dirtyAreaCache" = [ | ||||
|             "nav-bar" | ||||
|             "PersonalToolbar" | ||||
|             "toolbar-menubar" | ||||
|             "TabsToolbar" | ||||
|             "unified-extensions-area" | ||||
|             "vertical-tabs" | ||||
|           ]; | ||||
|           "placements" = { | ||||
|             "widget-overflow-fixed-list" = []; | ||||
|             "unified-extensions-area" = [ | ||||
|               # bitwarden | ||||
|               "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" | ||||
|               "ublock0_raymondhill_net-browser-action" | ||||
|               "sponsorblocker_ajay_app-browser-action" | ||||
|               "dearrow_ajay_app-browser-action" | ||||
|               "jid1-mnnxcxisbpnsxq_jetpack-browser-action" | ||||
|               "_testpilot-containers-browser-action" | ||||
|               "addon_simplelogin-browser-action" | ||||
|               "_74145f27-f039-47ce-a470-a662b129930a_-browser-action" | ||||
|               "jid1-bofifl9vbdl2zq_jetpack-browser-action" | ||||
|               "dfyoutube_example_com-browser-action" | ||||
|               "_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action" | ||||
|               "_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action" | ||||
|               "_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browse-action" | ||||
|               "jid0-3guet1r69sqnsrca5p8kx9ezc3u_jetpack-browser-action" | ||||
|             ]; | ||||
|             "nav-bar" = [ | ||||
|               "back-button" | ||||
|               "forward-button" | ||||
|               "stop-reload-button" | ||||
|               "urlbar-container" | ||||
|               "downloads-button" | ||||
|               "unified-extensions-button" | ||||
|               "reset-pbm-toolbar-button" | ||||
|             ]; | ||||
|             "toolbar-menubar" = [ | ||||
|               "menubar-items" | ||||
|             ]; | ||||
|             "TabsToolbar" = [ | ||||
|               "firefox-view-button" | ||||
|               "tabbrowser-tabs" | ||||
|               "new-tab-button" | ||||
|               "alltabs-button" | ||||
|             ]; | ||||
|             "vertical-tabs" = []; | ||||
|             "PersonalToolbar" = [ | ||||
|               "import-button" | ||||
|               "personal-bookmarks" | ||||
|             ]; | ||||
|           }; | ||||
|           "seen" = [ | ||||
|             "save-to-pocket-button" | ||||
|             "developer-button" | ||||
|             "privacy_privacy_com-browser-action" | ||||
|             "sponsorblocker_ajay_app-browser-action" | ||||
|             "ublock0_raymondhill_net-browser-action" | ||||
|             "addon_simplelogin-browser-action" | ||||
|             "dearrow_ajay_app-browser-action" | ||||
|             "_446900e4-71c2-419f-a6a7-df9c091e268b_-browser-action" | ||||
|             "_74145f27-f039-47ce-a470-a662b129930a_-browser-action" | ||||
|             "jid1-bofifl9vbdl2zq_jetpack-browser-action" | ||||
|             "dfyoutube_example_com-browser-action" | ||||
|             "_testpilot-containers-browser-action" | ||||
|             "_b86e4813-687a-43e6-ab65-0bde4ab75758_-browser-action" | ||||
|             "jid1-mnnxcxisbpnsxq_jetpack-browser-action" | ||||
|             "_762f9885-5a13-4abd-9c77-433dcd38b8fd_-browser-action" | ||||
|             "_b11bea1f-a888-4332-8d8a-cec2be7d24b9_-browser-action" | ||||
|             "jid0-3guet1r69sqnsrca5p8kx9ezc3u_jetpack-browser-action" | ||||
|           ]; | ||||
|         }; | ||||
|         "browser.newtabpage.activity-stream.feeds.topsites" = false; | ||||
|         "browser.newtabpage.activity-stream.showSponsoredTopSites" = false; | ||||
|         "browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts" = false; | ||||
|         "browser.newtabpage.blocked" = lib.genAttrs [ | ||||
|           # Facebook | ||||
|           "4gPpjkxgZzXPVtuEoAL9Ig==" | ||||
|           # Reddit | ||||
|           "gLv0ja2RYVgxKdp0I5qwvA==" | ||||
|           # Amazon | ||||
|           "K00ILysCaEq8+bEqV/3nuw==" | ||||
|           # Twitter | ||||
|           "T9nJot5PurhJSy8n038xGA==" | ||||
|         ] (_: 1); | ||||
|         "identity.fxaccounts.enabled" = false; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| {...}: { | ||||
|   programs.firefox = { | ||||
|     profiles.leyla = { | ||||
|       settings = { | ||||
|         # Security | ||||
|         "privacy.trackingprotection.enabled" = true; | ||||
|         "dom.security.https_only_mode" = true; | ||||
|         "dom.security.https_only_mode_pbm" = true; | ||||
|         "dom.security.https_only_mode_error_page_user_suggestions" = true; | ||||
| 
 | ||||
|         # Privacy & Data Protection | ||||
|         "extensions.formautofill.addresses.enabled" = false; | ||||
|         "extensions.formautofill.creditCards.enabled" = false; | ||||
|         "signon.rememberSignons" = false; | ||||
|         "privacy.sanitize.sanitizeOnShutdown" = true; | ||||
|         "privacy.clearOnShutdown_v2.cache" = true; | ||||
|         "privacy.clearOnShutdown_v2.cookiesAndStorage" = true; | ||||
|         "privacy.clearOnShutdown_v2.historyFormDataAndDownloads" = true; | ||||
|         "urlclassifier.trackingSkipURLs" = ""; | ||||
|         "urlclassifier.features.socialtracking.skipURLs" = ""; | ||||
| 
 | ||||
|         # Disable telemetry and data collection | ||||
|         "app.shield.optoutstudies.enabled" = false; | ||||
|         "browser.discovery.enabled" = false; | ||||
|         "browser.newtabpage.activity-stream.feeds.telemetry" = false; | ||||
|         "browser.newtabpage.activity-stream.telemetry" = false; | ||||
|         "browser.ping-centre.telemetry" = false; | ||||
|         "datareporting.healthreport.service.enabled" = false; | ||||
|         "datareporting.healthreport.uploadEnabled" = false; | ||||
|         "datareporting.policy.dataSubmissionEnabled" = false; | ||||
|         "datareporting.sessions.current.clean" = true; | ||||
|         "devtools.onboarding.telemetry.logged" = false; | ||||
|         "toolkit.telemetry.archive.enabled" = false; | ||||
|         "toolkit.telemetry.bhrPing.enabled" = false; | ||||
|         "toolkit.telemetry.enabled" = false; | ||||
|         "toolkit.telemetry.firstShutdownPing.enabled" = false; | ||||
|         "toolkit.telemetry.hybridContent.enabled" = false; | ||||
|         "toolkit.telemetry.newProfilePing.enabled" = false; | ||||
|         "toolkit.telemetry.prompted" = 2; | ||||
|         "toolkit.telemetry.rejected" = true; | ||||
|         "toolkit.telemetry.reportingpolicy.firstRun" = false; | ||||
|         "toolkit.telemetry.server" = ""; | ||||
|         "toolkit.telemetry.shutdownPingSender.enabled" = false; | ||||
|         "toolkit.telemetry.unified" = false; | ||||
|         "toolkit.telemetry.unifiedIsOptIn" = false; | ||||
|         "toolkit.telemetry.updatePing.enabled" = false; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -2,9 +2,11 @@ | |||
|   config = { | ||||
|     programs = { | ||||
|       git = { | ||||
|         userName = "Leyla Becker"; | ||||
|         userEmail = "git@jan-leila.com"; | ||||
|         extraConfig.init.defaultBranch = "main"; | ||||
|         settings = { | ||||
|           user.name = "Leyla Becker"; | ||||
|           user.email = "git@jan-leila.com"; | ||||
|           init.defaultBranch = "main"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ in { | |||
|               "javascript.updateImportsOnFileMove.enabled" = "always"; | ||||
|               "editor.tabSize" = 2; | ||||
|               "editor.insertSpaces" = false; | ||||
|               # "terminal.integrated.fontFamily" = "'Droid Sans Mono', 'monospace', monospace"; | ||||
|             } | ||||
|           ]; | ||||
| 
 | ||||
|  | @ -40,6 +41,7 @@ in { | |||
|             oneDark.enable = true; | ||||
|             atomKeybindings.enable = true; | ||||
|             openRemoteSsh.enable = true; | ||||
|             # openDyslexicFont.enable = false; | ||||
| 
 | ||||
|             # html development | ||||
|             autoRenameTag.enable = true; | ||||
|  | @ -67,6 +69,9 @@ in { | |||
|             # go development | ||||
|             go.enable = true; | ||||
| 
 | ||||
|             # rust development | ||||
|             rustAnalyzer.enable = true; | ||||
| 
 | ||||
|             # claude development | ||||
|             claudeDev = lib.mkIf ai-tooling-enabled { | ||||
|               enable = true; | ||||
|  |  | |||
|  | @ -57,7 +57,6 @@ | |||
|             "ata-ST18000NT001-3NF101_ZVTEF27J" | ||||
|             "ata-ST18000NE000-3G6101_ZVTJ7359" | ||||
|           ] | ||||
|           # TODO: this needs to be configured manually | ||||
|           [ | ||||
|             "ata-ST4000NE001-2MA101_WS2275P3" | ||||
|             "ata-ST4000NE001-2MA101_WS227B9F" | ||||
|  | @ -103,18 +102,6 @@ | |||
|         directories = ["leyla_documents" "eve_documents" "users_documents" "media"]; | ||||
|       }; | ||||
|     }; | ||||
|     reverse_proxy = { | ||||
|       enable = true; | ||||
|       enableACME = true; | ||||
|       hostname = "jan-leila.com"; | ||||
|     }; | ||||
|     postgres = { | ||||
|       extraUsers = { | ||||
|         leyla = { | ||||
|           isAdmin = true; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   systemd.network = { | ||||
|  | @ -226,6 +213,12 @@ | |||
|   }; | ||||
| 
 | ||||
|   services = { | ||||
|     # PostgreSQL database server | ||||
|     postgresql = { | ||||
|       enable = true; | ||||
|       adminUsers = ["leyla"]; | ||||
|     }; | ||||
| 
 | ||||
|     # temp enable desktop environment for setup | ||||
|     # Enable the X11 windowing system. | ||||
|     xserver.enable = true; | ||||
|  | @ -238,6 +231,16 @@ | |||
|       gnome.enable = true; | ||||
|     }; | ||||
| 
 | ||||
|     # Enable new reverse proxy system | ||||
|     reverseProxy = { | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|       acme = { | ||||
|         enable = true; | ||||
|         email = "jan-leila@protonmail.com"; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     ollama = { | ||||
|       enable = true; | ||||
|       exposePort = true; | ||||
|  | @ -295,35 +298,35 @@ | |||
| 
 | ||||
|     jellyfin = { | ||||
|       enable = true; | ||||
|       subdomain = "media"; | ||||
|       extraSubdomains = ["jellyfin"]; | ||||
|       domain = "media.jan-leila.com"; | ||||
|       extraDomains = ["jellyfin.jan-leila.com"]; | ||||
|     }; | ||||
| 
 | ||||
|     immich = { | ||||
|       enable = true; | ||||
|       subdomain = "photos"; | ||||
|       domain = "photos.jan-leila.com"; | ||||
|     }; | ||||
| 
 | ||||
|     forgejo = { | ||||
|       enable = true; | ||||
|       subdomain = "git"; | ||||
|       reverseProxy.domain = "git.jan-leila.com"; | ||||
|     }; | ||||
| 
 | ||||
|     searx = { | ||||
|       enable = true; | ||||
|       subdomain = "search"; | ||||
|       domain = "search.jan-leila.com"; | ||||
|     }; | ||||
| 
 | ||||
|     actual = { | ||||
|       enable = false; | ||||
|       subdomain = "budget"; | ||||
|       enable = true; | ||||
|       domain = "budget.jan-leila.com"; | ||||
|     }; | ||||
| 
 | ||||
|     home-assistant = { | ||||
|       enable = true; | ||||
|       subdomain = "home"; | ||||
|       domain = "home.jan-leila.com"; | ||||
|       openFirewall = true; | ||||
|       database = "postgres"; | ||||
|       postgres.enable = true; | ||||
| 
 | ||||
|       extensions = { | ||||
|         sonos.enable = true; | ||||
|  | @ -334,7 +337,7 @@ | |||
| 
 | ||||
|     paperless = { | ||||
|       enable = true; | ||||
|       subdomain = "documents"; | ||||
|       domain = "documents.jan-leila.com"; | ||||
|       passwordFile = config.sops.secrets."services/paperless_password".path; | ||||
|     }; | ||||
| 
 | ||||
|  | @ -343,6 +346,21 @@ | |||
|       openFirewall = true; | ||||
|     }; | ||||
| 
 | ||||
|     crab-hole = { | ||||
|       enable = true; | ||||
|       port = 8085; | ||||
|       openFirewall = true; | ||||
|       show_doc = true; | ||||
|       downstreams = { | ||||
|         host = { | ||||
|           enable = true; | ||||
|           openFirewall = true; | ||||
|         }; | ||||
|       }; | ||||
|       upstreams.cloudFlare.enable = true; | ||||
|       blocklists.ad_malware.enable = true; | ||||
|     }; | ||||
| 
 | ||||
|     qbittorrent = { | ||||
|       enable = true; | ||||
|       mediaDir = "/srv/qbittorent"; | ||||
|  | @ -350,21 +368,28 @@ | |||
|       webuiPort = 8084; | ||||
|     }; | ||||
| 
 | ||||
|     filebot-cleanup = { | ||||
|       enable = true; | ||||
|       licenseFile = "/srv/jellyfin/filebot_license.psm"; | ||||
|     }; | ||||
| 
 | ||||
|     sonarr = { | ||||
|       enable = false; | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|     radarr = { | ||||
|       enable = false; | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|     bazarr = { | ||||
|       enable = false; | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|     lidarr = { | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|     jackett = { | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|     flaresolverr = { | ||||
|       enable = true; | ||||
|       openFirewall = true; | ||||
|     }; | ||||
|   }; | ||||
|  |  | |||
|  | @ -4,6 +4,5 @@ | |||
|     ./hardware-configuration.nix | ||||
|     ./configuration.nix | ||||
|     ./packages.nix | ||||
|     ./filebot.nix | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -1,82 +0,0 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: | ||||
| with lib; let | ||||
|   cfg = config.services.filebot-cleanup; | ||||
| in { | ||||
|   options.services.filebot-cleanup = { | ||||
|     enable = mkEnableOption "Filebot cleanup service"; | ||||
| 
 | ||||
|     licenseFile = mkOption { | ||||
|       type = types.nullOr types.path; | ||||
|       default = null; | ||||
|       description = "Path to the Filebot license file"; | ||||
|     }; | ||||
| 
 | ||||
|     cleanupDirectory = mkOption { | ||||
|       type = types.str; | ||||
|       default = "/srv/jellyfin/filebot_cleanup"; | ||||
|       description = "Directory where cleaned up media files are stored"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|     users.groups.filebot_cleanup = {}; | ||||
|     users.users.filebot_cleanup = { | ||||
|       isSystemUser = true; | ||||
|       group = "filebot_cleanup"; | ||||
|       extraGroups = ["jellyfin_media"]; | ||||
|       home = cfg.cleanupDirectory; | ||||
|       createHome = true; | ||||
|     }; | ||||
| 
 | ||||
|     nixpkgs.config.allowUnfreePredicate = pkg: | ||||
|       builtins.elem (lib.getName pkg) [ | ||||
|         "filebot" | ||||
|       ]; | ||||
| 
 | ||||
|     environment.systemPackages = with pkgs; [ | ||||
|       filebot | ||||
|     ]; | ||||
| 
 | ||||
|     systemd.services.filebot-cleanup = { | ||||
|       description = "Filebot media cleanup service"; | ||||
|       serviceConfig = { | ||||
|         Type = "simple"; | ||||
|         User = "filebot_cleanup"; | ||||
|         Group = "filebot_cleanup"; | ||||
|         ExecStart = pkgs.writeShellScript "filebot-cleanup" '' | ||||
|           ${optionalString (cfg.licenseFile != null) '' | ||||
|             ${pkgs.filebot}/bin/filebot --license "${cfg.licenseFile}" | ||||
|           ''} | ||||
|           ${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Movies/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate | ||||
|           ${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Shows/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate | ||||
|         ''; | ||||
|         StandardOutput = "journal"; | ||||
|         StandardError = "journal"; | ||||
|       }; | ||||
|       wantedBy = ["multi-user.target"]; | ||||
|     }; | ||||
| 
 | ||||
|     environment.persistence = lib.mkIf config.host.impermanence.enable { | ||||
|       "/persist/system/jellyfin" = { | ||||
|         enable = true; | ||||
|         hideMounts = true; | ||||
|         files = [ | ||||
|           cfg.licenseFile | ||||
|         ]; | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = cfg.cleanupDirectory; | ||||
|             user = "filebot_cleanup"; | ||||
|             group = "filebot_cleanup"; | ||||
|             mode = "1770"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -41,12 +41,14 @@ | |||
| 
 | ||||
|   # installed opentabletdriver | ||||
|   hardware.opentabletdriver.enable = true; | ||||
|   hardware.keyboard.qmk.enable = true; | ||||
| 
 | ||||
|   # Enable the GNOME Desktop Environment. | ||||
|   services.displayManager.gdm.enable = true; | ||||
|   services.desktopManager.gnome.enable = true; | ||||
| 
 | ||||
|   host = { | ||||
|     ai.enable = true; | ||||
|     users = { | ||||
|       eve = { | ||||
|         isDesktopUser = true; | ||||
|  | @ -68,6 +70,9 @@ | |||
|   }; | ||||
| 
 | ||||
|   services.tailscale.enable = true; | ||||
|   # We were having weird build errors so this is disabled right now | ||||
|   # error: The option `devices.emergent.folders.eve_records.path' was accessed but has no value defined. Try setting the option | ||||
|   services.syncthing.enable = false; | ||||
| 
 | ||||
|   # Configure keymap in X11 | ||||
|   # services.xserver.xkb.layout = "us"; | ||||
|  |  | |||
							
								
								
									
										110
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										110
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							|  | @ -25,11 +25,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1758287904, | ||||
|         "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", | ||||
|         "lastModified": 1760701190, | ||||
|         "narHash": "sha256-y7UhnWlER8r776JsySqsbTUh2Txf7K30smfHlqdaIQw=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "disko", | ||||
|         "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", | ||||
|         "rev": "3a9450b26e69dcb6f8de6e2b07b3fc1c288d85f5", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -46,11 +46,11 @@ | |||
|       }, | ||||
|       "locked": { | ||||
|         "dir": "pkgs/firefox-addons", | ||||
|         "lastModified": 1759403080, | ||||
|         "narHash": "sha256-EteyL8KyG9R5xzqyOBzyag4n2cSemu61VFrl3opJSqE=", | ||||
|         "lastModified": 1761797037, | ||||
|         "narHash": "sha256-OqwAGit+3cdsG02K6+8WJniA2q0rqUVc6zbT5N9C1us=", | ||||
|         "owner": "rycee", | ||||
|         "repo": "nur-expressions", | ||||
|         "rev": "8af6dfcbcbf1115a4f5aeed77ff0db5d3c02caf0", | ||||
|         "rev": "3d9f4de0988bcfa57e45e16e1ef9326c56bdf891", | ||||
|         "type": "gitlab" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -62,11 +62,11 @@ | |||
|     }, | ||||
|     "flake-compat": { | ||||
|       "locked": { | ||||
|         "lastModified": 1747046372, | ||||
|         "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", | ||||
|         "lastModified": 1761588595, | ||||
|         "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", | ||||
|         "owner": "edolstra", | ||||
|         "repo": "flake-compat", | ||||
|         "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", | ||||
|         "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -111,24 +111,6 @@ | |||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_3": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_3" | ||||
|       }, | ||||
|       "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, | ||||
|  | @ -151,11 +133,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1759337100, | ||||
|         "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", | ||||
|         "lastModified": 1761845621, | ||||
|         "narHash": "sha256-d+R4MHsGmdebvSMsYUFWONsZSlUbOo8Zq/wjMdMiIac=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", | ||||
|         "rev": "97e3022a8d2c09313fa49847f6da4d76abcfc72d", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -182,11 +164,11 @@ | |||
|     "lix": { | ||||
|       "flake": false, | ||||
|       "locked": { | ||||
|         "lastModified": 1759624822, | ||||
|         "narHash": "sha256-cf40qfsfpxJU/BnQ9PEj027LdPINNSsJqm+C6Ug93BA=", | ||||
|         "rev": "57333a0e600c5e096a609410a2f1059b97194b1e", | ||||
|         "lastModified": 1755787066, | ||||
|         "narHash": "sha256-X2UwkUEban08GRSPXRr+kz8fckHqebr3P77qSvjoeOw=", | ||||
|         "rev": "ac9721a92e8138d29707824dbedb484c76948493", | ||||
|         "type": "tarball", | ||||
|         "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/57333a0e600c5e096a609410a2f1059b97194b1e.tar.gz" | ||||
|         "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/ac9721a92e8138d29707824dbedb484c76948493.tar.gz?rev=ac9721a92e8138d29707824dbedb484c76948493" | ||||
|       }, | ||||
|       "original": { | ||||
|         "type": "tarball", | ||||
|  | @ -203,11 +185,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1756511062, | ||||
|         "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", | ||||
|         "lastModified": 1759851320, | ||||
|         "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", | ||||
|         "ref": "refs/heads/main", | ||||
|         "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", | ||||
|         "revCount": 162, | ||||
|         "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", | ||||
|         "revCount": 163, | ||||
|         "type": "git", | ||||
|         "url": "https://git.lix.systems/lix-project/nixos-module.git" | ||||
|       }, | ||||
|  | @ -225,11 +207,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1759342933, | ||||
|         "narHash": "sha256-mdlUFcrOfvT0Pm+Hko/6aR3xf1ao5JA2iem4KsEVjP4=", | ||||
|         "lastModified": 1760821194, | ||||
|         "narHash": "sha256-UCsJ8eDuHL14u2GFIYEY/drtZ6jht5zN/G/6QNlEy2g=", | ||||
|         "owner": "utensils", | ||||
|         "repo": "mcp-nixos", | ||||
|         "rev": "50b02bcba32b941d2ec48fedef68641702ca5b0f", | ||||
|         "rev": "0ae453f38d0f088c31d4678da3a12b183165986f", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -245,11 +227,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1758805352, | ||||
|         "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=", | ||||
|         "lastModified": 1761339987, | ||||
|         "narHash": "sha256-IUaawVwItZKi64IA6kF6wQCLCzpXbk2R46dHn8sHkig=", | ||||
|         "owner": "LnL7", | ||||
|         "repo": "nix-darwin", | ||||
|         "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c", | ||||
|         "rev": "7cd9aac79ee2924a85c211d21fafd394b06a38de", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -281,17 +263,16 @@ | |||
|     }, | ||||
|     "nix-vscode-extensions": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_3", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1759369908, | ||||
|         "narHash": "sha256-IIhaE6jAge64z+fIyi/8Vtu0JdTtapbp4CvwiuIkZ1E=", | ||||
|         "lastModified": 1761789484, | ||||
|         "narHash": "sha256-17gDUWloFXQlavqHRey/urQe6sQ3yP5hsQyYmcNOZyU=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "nix-vscode-extensions", | ||||
|         "rev": "a66ad2141b1440a838ead278c6edfe8a4ce75e6c", | ||||
|         "rev": "c47e683d236fa6e4c27dbda2af3468cb9aceb813", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -302,11 +283,11 @@ | |||
|     }, | ||||
|     "nixos-hardware": { | ||||
|       "locked": { | ||||
|         "lastModified": 1759261527, | ||||
|         "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", | ||||
|         "lastModified": 1761827175, | ||||
|         "narHash": "sha256-XdPVSYyIBK4/ruoqujaQmmSGg3J2/EenexV9IEXhr6o=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixos-hardware", | ||||
|         "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", | ||||
|         "rev": "43ffe9ac82567512abb83187cb673de1091bdfa8", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -334,11 +315,11 @@ | |||
|     }, | ||||
|     "nixpkgs_2": { | ||||
|       "locked": { | ||||
|         "lastModified": 1759381078, | ||||
|         "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", | ||||
|         "lastModified": 1761672384, | ||||
|         "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", | ||||
|         "owner": "nixos", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", | ||||
|         "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -389,11 +370,11 @@ | |||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1759188042, | ||||
|         "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", | ||||
|         "lastModified": 1760998189, | ||||
|         "narHash": "sha256-ee2e1/AeGL5X8oy/HXsZQvZnae6XfEVdstGopKucYLY=", | ||||
|         "owner": "Mic92", | ||||
|         "repo": "sops-nix", | ||||
|         "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", | ||||
|         "rev": "5a7d18b5c55642df5c432aadb757140edfeb70b3", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|  | @ -431,21 +412,6 @@ | |||
|         "repo": "default", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "systems_3": { | ||||
|       "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", | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
|   src = fetchurl { | ||||
|     url = "http://tools.mapillary.com/uploader/download/linux/${version}"; | ||||
|     name = "mapillary-uploader.AppImage"; | ||||
|     sha256 = "sha256-Oyx7AIdA/2mwBaq7UzXOoyq/z2SU2sViMN40sY2RCQw="; | ||||
|     sha256 = "sha256-hpWdfeuhYylO+SFD3BsKI0s/xtObCDd5OcuJ6i/aEuI="; | ||||
|   }; | ||||
| 
 | ||||
|   appimageContents = appimageTools.extractType2 { | ||||
|  | @ -23,9 +23,6 @@ in | |||
|       # Install desktop file | ||||
|       install -Dm644 ${appimageContents}/mapillary-desktop-uploader.desktop $out/share/applications/mapillary-uploader.desktop | ||||
| 
 | ||||
|       # Install icon | ||||
|       install -Dm644 ${appimageContents}/usr/share/icons/hicolor/0x0/apps/mapillary-desktop-uploader.png $out/share/pixmaps/mapillary-uploader.png | ||||
| 
 | ||||
|       # Fix desktop file paths | ||||
|       substituteInPlace $out/share/applications/mapillary-uploader.desktop \ | ||||
|         --replace 'Exec=AppRun' 'Exec=${pname}' | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|   flutter332, | ||||
|   fetchFromGitLab, | ||||
|   pkg-config, | ||||
|   wrapGAppsHook, | ||||
|   wrapGAppsHook3, | ||||
|   gtk3, | ||||
|   glib, | ||||
|   glib-networking, | ||||
|  | @ -65,7 +65,7 @@ flutter332.buildFlutterApplication rec { | |||
| 
 | ||||
|   nativeBuildInputs = [ | ||||
|     pkg-config | ||||
|     wrapGAppsHook | ||||
|     wrapGAppsHook3 | ||||
|   ]; | ||||
| 
 | ||||
|   buildInputs = [ | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
|     ./user.nix | ||||
|     ./flipperzero.nix | ||||
|     ./i18n.nix | ||||
|     ./impermanence.nix | ||||
|     ./openssh.nix | ||||
|     ./gnome.nix | ||||
|     ./programs | ||||
|  |  | |||
|  | @ -1,8 +1,16 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: { | ||||
| }: let | ||||
|   enabledExtensions = | ||||
|     [] | ||||
|     ++ lib.optional config.gnome.extensions.dash-to-dock.enable pkgs.gnomeExtensions.dash-to-dock | ||||
|     ++ lib.optional config.gnome.extensions.dash-to-panel.enable pkgs.gnomeExtensions.dash-to-panel; | ||||
| 
 | ||||
|   extensions = config.gnome.extraExtensions ++ enabledExtensions; | ||||
| in { | ||||
|   options.gnome = { | ||||
|     extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; | ||||
|     clockFormat = lib.mkOption { | ||||
|  | @ -34,7 +42,7 @@ | |||
|       ]; | ||||
|       default = "blue"; | ||||
|     }; | ||||
|     extensions = lib.mkOption { | ||||
|     extraExtensions = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.package; | ||||
|       default = []; | ||||
|       description = "The set of extensions to install and enable in the user environment."; | ||||
|  | @ -60,16 +68,80 @@ | |||
|       })); | ||||
|       default = {}; | ||||
|     }; | ||||
|     displayScaling = lib.mkOption { | ||||
|       type = lib.types.nullOr (lib.types.enum [100 125 150 175 200]); | ||||
|       default = null; | ||||
|       description = "Display scaling percentage for GNOME"; | ||||
|     }; | ||||
|     experimentalFeatures = lib.mkOption { | ||||
|       type = lib.types.submodule { | ||||
|         options = { | ||||
|           scaleMonitorFramebuffer = lib.mkEnableOption "scale-monitor-framebuffer experimental feature"; | ||||
|         }; | ||||
|       }; | ||||
|       default = {}; | ||||
|       description = "GNOME experimental features to enable"; | ||||
|     }; | ||||
| 
 | ||||
|     nightLight = lib.mkOption { | ||||
|       type = lib.types.submodule { | ||||
|         options = { | ||||
|           enable = lib.mkEnableOption "night light (blue light filter)"; | ||||
|           automatic = lib.mkOption { | ||||
|             type = lib.types.bool; | ||||
|             default = true; | ||||
|             description = "Whether to automatically schedule night light based on sunset/sunrise"; | ||||
|           }; | ||||
|           fromTime = lib.mkOption { | ||||
|             type = lib.types.float; | ||||
|             default = 20.0; | ||||
|             description = "Start time for night light in 24-hour format (e.g., 20.0 for 8:00 PM)"; | ||||
|           }; | ||||
|           toTime = lib.mkOption { | ||||
|             type = lib.types.float; | ||||
|             default = 6.0; | ||||
|             description = "End time for night light in 24-hour format (e.g., 6.0 for 6:00 AM)"; | ||||
|           }; | ||||
|           temperature = lib.mkOption { | ||||
|             type = lib.types.int; | ||||
|             default = 4000; | ||||
|             description = "Color temperature for night light (1000-10000K, lower is warmer)"; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       default = {}; | ||||
|       description = "Night light configuration"; | ||||
|     }; | ||||
| 
 | ||||
|     extensions = { | ||||
|       dash-to-dock = { | ||||
|         enable = lib.mkEnableOption "Dash to Dock extension"; | ||||
|         options = lib.mkOption { | ||||
|           type = lib.types.nullOr lib.types.attrs; | ||||
|           default = null; | ||||
|           description = "Dash to Dock configuration options. If null, no custom configuration will be applied."; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|       dash-to-panel = { | ||||
|         enable = lib.mkEnableOption "Dash to Panel extension"; | ||||
|         options = lib.mkOption { | ||||
|           type = lib.types.nullOr lib.types.attrs; | ||||
|           default = null; | ||||
|           description = "Dash to Panel configuration options. If null, no custom configuration will be applied."; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = { | ||||
|     home.packages = config.gnome.extensions; | ||||
|     home.packages = 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; | ||||
|             enabled-extensions = builtins.map (extension: extension.extensionUuid) extensions; | ||||
|           }; | ||||
| 
 | ||||
|           "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; | ||||
|  | @ -77,7 +149,23 @@ | |||
|           "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; | ||||
|           "org/gnome/desktop/interface".text-scaling-factor = lib.mkIf (config.gnome.displayScaling != null) (config.gnome.displayScaling / 100.0); | ||||
| 
 | ||||
|           "org/gnome/mutter".experimental-features = lib.mkIf (builtins.any (x: x) (builtins.attrValues config.gnome.experimentalFeatures)) ( | ||||
|             lib.optional config.gnome.experimentalFeatures.scaleMonitorFramebuffer "scale-monitor-framebuffer" | ||||
|           ); | ||||
|         } | ||||
| 
 | ||||
|         # Night light configuration | ||||
|         (lib.mkIf config.gnome.nightLight.enable { | ||||
|           "org/gnome/settings-daemon/plugins/color" = { | ||||
|             night-light-enabled = true; | ||||
|             night-light-schedule-automatic = config.gnome.nightLight.automatic; | ||||
|             night-light-schedule-from = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.fromTime; | ||||
|             night-light-schedule-to = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.toTime; | ||||
|             night-light-temperature = config.gnome.nightLight.temperature; | ||||
|           }; | ||||
|         }) | ||||
|         ( | ||||
|           lib.mkMerge ( | ||||
|             builtins.map (value: let | ||||
|  | @ -100,6 +188,15 @@ | |||
|             ) | ||||
|           ) | ||||
|         ) | ||||
| 
 | ||||
|         # Extension configurations | ||||
|         (lib.mkIf (config.gnome.extensions.dash-to-dock.enable && config.gnome.extensions.dash-to-dock.options != null) { | ||||
|           "org/gnome/shell/extensions/dash-to-dock" = config.gnome.extensions.dash-to-dock.options; | ||||
|         }) | ||||
| 
 | ||||
|         (lib.mkIf (config.gnome.extensions.dash-to-panel.enable && config.gnome.extensions.dash-to-panel.options != null) { | ||||
|           "org/gnome/shell/extensions/dash-to-panel" = config.gnome.extensions.dash-to-panel.options; | ||||
|         }) | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
|  |  | |||
							
								
								
									
										35
									
								
								modules/home-manager-modules/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								modules/home-manager-modules/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.impermanence; | ||||
| in { | ||||
|   options.impermanence = { | ||||
|     enable = lib.mkEnableOption "impermanence for home directory"; | ||||
|     fallbackPersistence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = true; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkMerge [ | ||||
|     (lib.mkIf config.impermanence.enable { | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = osConfig.host.impermanence.enable; | ||||
|           message = "impermanence can not be enabled for a user when it is not enabled for the system"; | ||||
|         } | ||||
|       ]; | ||||
|     }) | ||||
|     # If impermanence is not enabled for this user but system impermanence is enabled, | ||||
|     # persist the entire home directory as fallback | ||||
|     (lib.mkIf (osConfig.host.impermanence.enable && !cfg.enable && cfg.fallbackPersistence.enable) { | ||||
|       home.persistence."/persist/home/${config.home.username}" = { | ||||
|         directories = ["."]; | ||||
|         allowOther = true; | ||||
|       }; | ||||
|     }) | ||||
|   ]; | ||||
| } | ||||
|  | @ -95,7 +95,7 @@ | |||
|           ); | ||||
|         } | ||||
|       ) | ||||
|       (lib.mkIf osConfig.host.impermanence.enable { | ||||
|       (lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           files = lib.lists.flatten ( | ||||
|             builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.bitwarden = { | ||||
|  | @ -12,11 +11,11 @@ | |||
|   config = lib.mkIf config.programs.bitwarden.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = with pkgs; [ | ||||
|         bitwarden | ||||
|         bitwarden-desktop | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/Bitwarden" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.bruno = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/bruno/" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.calibre = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/calibre" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.davinci-resolve = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.dataHome}/DaVinciResolve" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.dbeaver-bin = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.dataHome}/DBeaverData/" | ||||
|  |  | |||
|  | @ -12,11 +12,13 @@ | |||
|     ./obsidian.nix | ||||
|     ./prostudiomasters.nix | ||||
|     ./idea.nix | ||||
|     ./kdenlive.nix | ||||
|     ./krita.nix | ||||
|     ./protonvpn.nix | ||||
|     ./calibre.nix | ||||
|     ./bruno.nix | ||||
|     ./dbeaver.nix | ||||
|     ./dungeon-draft.nix | ||||
|     ./steam.nix | ||||
|     ./vscode | ||||
|     ./ungoogled-chromium.nix | ||||
|  | @ -24,6 +26,7 @@ | |||
|     ./mapillary-uploader.nix | ||||
|     ./inkscape.nix | ||||
|     ./gimp.nix | ||||
|     ./guild-wars-2.nix | ||||
|     ./proxmark3.nix | ||||
|     ./freecad.nix | ||||
|     ./onionshare.nix | ||||
|  | @ -33,11 +36,14 @@ | |||
|     ./qflipper.nix | ||||
|     ./openvpn.nix | ||||
|     ./noisetorch.nix | ||||
|     ./olympus.nix | ||||
|     ./openrgb.nix | ||||
|     ./via.nix | ||||
|     ./vortex.nix | ||||
|     ./davinci-resolve.nix | ||||
|     ./gdx-liftoff.nix | ||||
|     ./tor-browser.nix | ||||
|     ./polycule.nix | ||||
|     ./vmware-workstation.nix | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.discord = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/discord/" | ||||
|  |  | |||
							
								
								
									
										24
									
								
								modules/home-manager-modules/programs/dungeon-draft.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/home-manager-modules/programs/dungeon-draft.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.programs.dungeon-draft; | ||||
| in { | ||||
|   options.programs.dungeon-draft = { | ||||
|     enable = lib.mkEnableOption "Dungeon Draft"; | ||||
|   }; | ||||
| 
 | ||||
|   config = { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = !cfg.enable; | ||||
|         message = '' | ||||
|           Dungeon Draft module is not yet fully configured. | ||||
|           Please download the Dungeon Draft executable (.exe) from the official website, | ||||
|           then configure the Wine environment and executable path as needed. | ||||
|         ''; | ||||
|       } | ||||
|     ]; | ||||
|   }; | ||||
| } | ||||
|  | @ -1,7 +1,6 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: let | ||||
|   buildProfilePersistence = profile: { | ||||
|  | @ -26,7 +25,7 @@ | |||
|     allowOther = true; | ||||
|   }; | ||||
| in { | ||||
|   config = lib.mkIf (config.programs.firefox.enable && osConfig.host.impermanence.enable) { | ||||
|   config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) { | ||||
|     home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( | ||||
|       ( | ||||
|         lib.attrsets.mapAttrsToList | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.freecad = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/FreeCAD" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.gdx-liftoff = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.gimp = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/GIMP" | ||||
|  |  | |||
							
								
								
									
										24
									
								
								modules/home-manager-modules/programs/guild-wars-2.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/home-manager-modules/programs/guild-wars-2.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.programs.guild-wars-2; | ||||
| in { | ||||
|   options.programs.guild-wars-2 = { | ||||
|     enable = lib.mkEnableOption "Guild Wars 2"; | ||||
|   }; | ||||
| 
 | ||||
|   config = { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = !cfg.enable; | ||||
|         message = '' | ||||
|           Guild Wars 2 module is not yet fully configured. | ||||
|           Please install Guild Wars 2 manually via Steam or the official client, | ||||
|           then configure the Wine environment as needed. | ||||
|         ''; | ||||
|       } | ||||
|     ]; | ||||
|   }; | ||||
| } | ||||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.jetbrains.idea-community = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             # configuration | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.inkscape = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/inkscape" | ||||
|  |  | |||
							
								
								
									
										36
									
								
								modules/home-manager-modules/programs/kdenlive.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								modules/home-manager-modules/programs/kdenlive.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.programs.kdenlive; | ||||
| in { | ||||
|   options.programs.kdenlive = { | ||||
|     enable = lib.mkEnableOption "kdenlive"; | ||||
|     package = lib.mkOption { | ||||
|       type = lib.types.package; | ||||
|       default = pkgs.kdePackages.kdenlive; | ||||
|       description = "The kdenlive package to install."; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf cfg.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = [ | ||||
|         cfg.package | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/kdenliverc" | ||||
|             "${config.xdg.dataHome}/kdenlive" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
| } | ||||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.krita = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/kritarc" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.libreoffice = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/libreoffice" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.makemkv = { | ||||
|  | @ -30,7 +29,7 @@ | |||
|       home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             ".MakeMKV" | ||||
|  |  | |||
|  | @ -11,7 +11,20 @@ in { | |||
|     enable = mkEnableOption "Mapillary Desktop Uploader"; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|   config = mkIf cfg.enable (mkMerge [ | ||||
|     { | ||||
|       home.packages = [pkgs.mapillary-uploader]; | ||||
|     } | ||||
|     ( | ||||
|       mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/mapillary-uploader" | ||||
|             "${config.xdg.dataHome}/mapillary-uploader" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.mfoc = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.noisetorch = { | ||||
|  |  | |||
|  | @ -1,13 +1,17 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|         # TODO: map impermanence for obs | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/obs-studio" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [ | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/obsidian" | ||||
|  |  | |||
							
								
								
									
										36
									
								
								modules/home-manager-modules/programs/olympus.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								modules/home-manager-modules/programs/olympus.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   pkgs, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.programs.olympus; | ||||
| in { | ||||
|   options.programs.olympus = { | ||||
|     enable = lib.mkEnableOption "olympus"; | ||||
|     package = lib.mkOption { | ||||
|       type = lib.types.package; | ||||
|       default = pkgs.olympus; | ||||
|       description = "The olympus package to install."; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf cfg.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = [ | ||||
|         cfg.package | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/olympus" | ||||
|             "${config.xdg.dataHome}/olympus" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
| } | ||||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.onionshare = { | ||||
|  |  | |||
|  | @ -2,16 +2,27 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.openrgb = { | ||||
|     enable = lib.mkEnableOption "enable openrgb"; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.programs.openrgb.enable { | ||||
|   config = lib.mkIf config.programs.openrgb.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = with pkgs; [ | ||||
|         openrgb | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/OpenRGB" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.openvpn = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.pdfarranger = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.picard = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/MusicBrainz" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.piper = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.polycule = { | ||||
|  | @ -17,7 +16,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           # TODO: check that these are actually the correct folders | ||||
|           # directories = [ | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.prostudiomasters = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/ProStudioMasters" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.protonvpn-gui = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/protonvpn" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.proxmark3 = { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.qbittorrent = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/qBittorrent" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.qflipper = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/qFlipper" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.signal-desktop-bin = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/Signal" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.steam = { | ||||
|  | @ -18,7 +17,7 @@ | |||
|         ]; | ||||
|       } | ||||
|       ( | ||||
|         lib.mkIf osConfig.host.impermanence.enable { | ||||
|         lib.mkIf config.impermanence.enable { | ||||
|           home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|             directories = [ | ||||
|               { | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.tor-browser = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.dataHome}/torbrowser" | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.ungoogled-chromium = { | ||||
|  | @ -16,7 +15,7 @@ | |||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf osConfig.host.impermanence.enable { | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/chromium" | ||||
|  |  | |||
|  | @ -2,16 +2,28 @@ | |||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   osConfig, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.via = { | ||||
|     enable = lib.mkEnableOption "enable via"; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.programs.via.enable { | ||||
|   config = lib.mkIf config.programs.via.enable (lib.mkMerge [ | ||||
|     { | ||||
|       home.packages = with pkgs; [ | ||||
|         via | ||||
|       ]; | ||||
|     } | ||||
|     ( | ||||
|       lib.mkIf config.impermanence.enable { | ||||
|         home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|           directories = [ | ||||
|             "${config.xdg.configHome}/via" | ||||
|             "${config.xdg.dataHome}/via" | ||||
|           ]; | ||||
|           allowOther = true; | ||||
|         }; | ||||
|       } | ||||
|     ) | ||||
|   ]); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										37
									
								
								modules/home-manager-modules/programs/vmware-workstation.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								modules/home-manager-modules/programs/vmware-workstation.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.vmware-workstation = { | ||||
|     enable = lib.mkEnableOption "enable VMware Workstation"; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.programs.vmware-workstation.enable ( | ||||
|     lib.mkMerge [ | ||||
|       { | ||||
|         home.packages = with pkgs; [ | ||||
|           vmware-workstation | ||||
|         ]; | ||||
|       } | ||||
|       ( | ||||
|         lib.mkIf config.impermanence.enable { | ||||
|           home.persistence."/persist${config.home.homeDirectory}" = { | ||||
|             directories = [ | ||||
|               { | ||||
|                 directory = ".vmware"; | ||||
|                 method = "symlink"; | ||||
|               } | ||||
|               { | ||||
|                 directory = "vmware"; | ||||
|                 method = "symlink"; | ||||
|               } | ||||
|             ]; | ||||
|             allowOther = true; | ||||
|           }; | ||||
|         } | ||||
|       ) | ||||
|     ] | ||||
|   ); | ||||
| } | ||||
							
								
								
									
										24
									
								
								modules/home-manager-modules/programs/vortex.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/home-manager-modules/programs/vortex.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.programs.vortex; | ||||
| in { | ||||
|   options.programs.vortex = { | ||||
|     enable = lib.mkEnableOption "Vortex (Nexus Mods manager)"; | ||||
|   }; | ||||
| 
 | ||||
|   config = { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = !cfg.enable; | ||||
|         message = '' | ||||
|           Vortex module is not yet fully configured. | ||||
|           Please download and install Vortex manually from the Nexus Mods website, | ||||
|           then configure the Wine environment and dependencies as needed. | ||||
|         ''; | ||||
|       } | ||||
|     ]; | ||||
|   }; | ||||
| } | ||||
|  | @ -16,6 +16,7 @@ | |||
|     ./go.nix | ||||
|     ./evenBetterToml.nix | ||||
|     ./openRemoteSsh.nix | ||||
|     ./rustAnalyzer.nix | ||||
|     ./astroVscode.nix | ||||
|     ./vscodeMdx.nix | ||||
|     ./claudeDev.nix | ||||
|  | @ -23,5 +24,6 @@ | |||
|     ./vitest.nix | ||||
|     ./direnv.nix | ||||
|     ./conventionalCommits.nix | ||||
|     ./openDyslexicFont.nix | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,49 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.programs.vscode.profiles = lib.mkOption { | ||||
|     type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { | ||||
|       options = { | ||||
|         extraExtensions.openDyslexicFont = { | ||||
|           enable = lib.mkEnableOption "should OpenDyslexic font be set as the default font for VSCode"; | ||||
|           package = lib.mkPackageOption pkgs "nerd-fonts.open-dyslexic" { | ||||
|             default = ["nerd-fonts" "open-dyslexic"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.openDyslexicFont.enable { | ||||
|         userSettings = { | ||||
|           "editor.fontFamily" = "'OpenDyslexicM Nerd Font Mono', Droid Sans Mono, monospace"; | ||||
|           "editor.fontSize" = 14; | ||||
|           "editor.letterSpacing" = -0.3; | ||||
|         }; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| 
 | ||||
|   config = let | ||||
|     enabledProfiles = | ||||
|       lib.filter (profile: profile.extraExtensions.openDyslexicFont.enable or false) | ||||
|       (lib.attrValues config.programs.vscode.profiles); | ||||
| 
 | ||||
|     anyProfileUsesOpenDyslexicFont = enabledProfiles != []; | ||||
| 
 | ||||
|     fontPackages = lib.unique (map (profile: profile.extraExtensions.openDyslexicFont.package) enabledProfiles); | ||||
|   in { | ||||
|     # Ensure OpenDyslexic font packages are installed when any VSCode profile uses them | ||||
|     home.packages = fontPackages; | ||||
| 
 | ||||
|     fonts.fontconfig.enable = lib.mkIf anyProfileUsesOpenDyslexicFont true; | ||||
| 
 | ||||
|     # Add assertion to ensure the fonts are available | ||||
|     assertions = | ||||
|       map (fontPkg: { | ||||
|         assertion = lib.elem fontPkg config.home.packages; | ||||
|         message = "OpenDyslexic font package '${fontPkg.name or "unknown"}' must be installed when using openDyslexicFont extension for VSCode."; | ||||
|       }) | ||||
|       fontPackages; | ||||
|   }; | ||||
| } | ||||
|  | @ -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.rustAnalyzer = { | ||||
|           enable = lib.mkEnableOption "should the rust-analyzer extension for vscode be enabled"; | ||||
|           extension = lib.mkPackageOption pkgsRepository "rust-analyzer" { | ||||
|             default = ["rust-lang" "rust-analyzer"]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       config = lib.mkIf config.extraExtensions.rustAnalyzer.enable { | ||||
|         extensions = [ | ||||
|           config.extraExtensions.rustAnalyzer.extension | ||||
|         ]; | ||||
|       }; | ||||
|     })); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										24
									
								
								modules/nixos-modules/server/actual/actual.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/nixos-modules/server/actual/actual.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   const = import ./const.nix; | ||||
|   dataDirectory = const.dataDirectory; | ||||
| in { | ||||
|   options.services.actual = { | ||||
|     port = lib.mkOption { | ||||
|       type = lib.types.port; | ||||
|       description = "The port to listen on"; | ||||
|       default = 5006; | ||||
|     }; | ||||
|   }; | ||||
|   config = lib.mkIf config.services.actual.enable { | ||||
|     services.actual = { | ||||
|       settings = { | ||||
|         port = config.services.actual.port; | ||||
|         dataDir = dataDirectory; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -1,3 +1,3 @@ | |||
| { | ||||
|   dataDirectory = "/var/lib/actual/"; | ||||
|   dataDirectory = "/var/lib/private/actual"; | ||||
| } | ||||
|  |  | |||
|  | @ -1,26 +1,8 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   const = import ./const.nix; | ||||
|   dataDirectory = const.dataDirectory; | ||||
| in { | ||||
|   imports = [ | ||||
|     ./actual.nix | ||||
|     ./proxy.nix | ||||
|     ./fail2ban.nix | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.actual.enable { | ||||
|     systemd.tmpfiles.rules = [ | ||||
|       "d ${dataDirectory} 2770 actual actual" | ||||
|     ]; | ||||
| 
 | ||||
|     services.actual = { | ||||
|       settings = { | ||||
|         ACTUAL_DATA_DIR = dataDirectory; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -6,11 +6,22 @@ | |||
|   const = import ./const.nix; | ||||
|   dataDirectory = const.dataDirectory; | ||||
| in { | ||||
|   config = lib.mkIf (config.services.actual.enable && config.host.impermanence.enable) { | ||||
|   options.services.actual = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.actual.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.actual.impermanence.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.actual.settings.ACTUAL_DATA_DIR == dataDirectory; | ||||
|         message = "actual data location does not match persistence"; | ||||
|         assertion = config.services.actual.settings.dataDir == dataDirectory; | ||||
|         message = "actual data location does not match persistence\nconfig directory: ${config.services.actual.settings.dataDir}\npersistence directory: ${dataDirectory}"; | ||||
|       } | ||||
|       { | ||||
|         assertion = config.systemd.services.actual.serviceConfig.DynamicUser or false; | ||||
|         message = "actual systemd service must have DynamicUser enabled to use private directory"; | ||||
|       } | ||||
|     ]; | ||||
|     environment.persistence."/persist/system/root" = { | ||||
|  |  | |||
|  | @ -4,17 +4,30 @@ | |||
|   ... | ||||
| }: { | ||||
|   options.services.actual = { | ||||
|     subdomain = lib.mkOption { | ||||
|     domain = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "actual"; | ||||
|       description = "subdomain of base domain that actual will be hosted at"; | ||||
|       description = "domain that actual will be hosted at"; | ||||
|       default = "actual.arpa"; | ||||
|     }; | ||||
|     extraDomains = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.str; | ||||
|       description = "extra domains that should be configured for actual"; | ||||
|       default = []; | ||||
|     }; | ||||
|     reverseProxy.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.actual.enable && config.services.reverseProxy.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf (config.services.actual.enable && config.host.reverse_proxy.enable) { | ||||
|     host = { | ||||
|       reverse_proxy.subdomains.${config.services.actual.subdomain} = { | ||||
|   config = lib.mkIf config.services.actual.reverseProxy.enable { | ||||
|     services.reverseProxy.services.actual = { | ||||
|       target = "http://localhost:${toString config.services.actual.settings.port}"; | ||||
|       domain = config.services.actual.domain; | ||||
|       extraDomains = config.services.actual.extraDomains; | ||||
| 
 | ||||
|       settings = { | ||||
|         forwardHeaders.enable = true; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./proxy.nix | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,14 @@ | |||
| }: let | ||||
|   bazarr_data_directory = "/var/lib/bazarr"; | ||||
| in { | ||||
|   config = lib.mkIf (config.services.bazarr.enable && config.host.impermanence.enable) { | ||||
|   options.services.bazarr = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.bazarr.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.bazarr.impermanence.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.bazarr.dataDir == bazarr_data_directory; | ||||
|  |  | |||
|  | @ -1,28 +0,0 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.services.bazarr = { | ||||
|     subdomain = lib.mkOption { | ||||
|       type = lib.types.nullOr lib.types.str; | ||||
|       default = null; | ||||
|       description = "Subdomain for reverse proxy. If null, service will be local only."; | ||||
|     }; | ||||
|     extraSubdomains = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.str; | ||||
|       default = []; | ||||
|       description = "Extra subdomains for reverse proxy."; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf (config.services.bazarr.enable && config.services.bazarr.subdomain != null) { | ||||
|     host.reverse_proxy.subdomains.bazarr = { | ||||
|       subdomain = config.services.bazarr.subdomain; | ||||
|       extraSubdomains = config.services.bazarr.extraSubdomains; | ||||
|       target = "http://127.0.0.1:6767"; | ||||
|       websockets.enable = true; | ||||
|       forwardHeaders.enable = true; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										193
									
								
								modules/nixos-modules/server/crab-hole/crab-hole.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								modules/nixos-modules/server/crab-hole/crab-hole.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,193 @@ | |||
| { | ||||
|   config, | ||||
|   lib, | ||||
|   ... | ||||
| }: let | ||||
|   cfg = config.services.crab-hole; | ||||
| in { | ||||
|   options.services.crab-hole = { | ||||
|     port = lib.mkOption { | ||||
|       type = lib.types.port; | ||||
|       default = 8080; | ||||
|       description = "Port for the crab-hole API to listen on."; | ||||
|     }; | ||||
| 
 | ||||
|     openFirewall = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = false; | ||||
|       description = "Whether to open the firewall for the crab-hole API port."; | ||||
|     }; | ||||
| 
 | ||||
|     listen = lib.mkOption { | ||||
|       type = lib.types.str; | ||||
|       default = "0.0.0.0"; | ||||
|       description = "Address for the crab-hole API to listen on."; | ||||
|     }; | ||||
| 
 | ||||
|     show_doc = lib.mkEnableOption "OpenAPI documentation (loads content from third party websites)"; | ||||
| 
 | ||||
|     downstreams = { | ||||
|       host = { | ||||
|         enable = lib.mkEnableOption "host downstream DNS server accessible from network on all interfaces"; | ||||
|         port = lib.mkOption { | ||||
|           type = lib.types.port; | ||||
|           default = 53; | ||||
|           description = "Port for the host downstream DNS server to listen on."; | ||||
|         }; | ||||
|         openFirewall = lib.mkEnableOption "automatic port forwarding for the host downstream"; | ||||
|         disableSystemdResolved = lib.mkOption { | ||||
|           type = lib.types.bool; | ||||
|           default = true; | ||||
|           description = "Whether to automatically disable systemd-resolved when using port 53. Set to false if you want to handle the conflict manually."; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     extraDownstreams = lib.mkOption { | ||||
|       type = lib.types.listOf (lib.types.submodule { | ||||
|         options = { | ||||
|           protocol = lib.mkOption { | ||||
|             type = lib.types.enum ["udp" "tcp" "tls" "https" "quic"]; | ||||
|             description = "Protocol for the downstream server."; | ||||
|           }; | ||||
| 
 | ||||
|           listen = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|             description = "Address to listen on for downstream connections."; | ||||
|           }; | ||||
| 
 | ||||
|           port = lib.mkOption { | ||||
|             type = lib.types.port; | ||||
|             description = "Port to listen on for downstream connections."; | ||||
|           }; | ||||
|         }; | ||||
|       }); | ||||
|       default = []; | ||||
|       description = "List of additional downstream DNS server configurations."; | ||||
|     }; | ||||
| 
 | ||||
|     upstreams = { | ||||
|       cloudFlare = { | ||||
|         enable = lib.mkEnableOption "Cloudflare DNS over TLS upstream servers (1.1.1.1 and 1.0.0.1)"; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     extraUpstreams = lib.mkOption { | ||||
|       type = lib.types.listOf (lib.types.submodule { | ||||
|         options = { | ||||
|           socket_addr = lib.mkOption { | ||||
|             type = lib.types.str; | ||||
|             description = "Socket address of the upstream DNS server (e.g., \"1.1.1.1:853\" or \"[2606:4700:4700::1111]:853\")."; | ||||
|           }; | ||||
| 
 | ||||
|           protocol = lib.mkOption { | ||||
|             type = lib.types.enum ["udp" "tcp" "tls" "https" "quic"]; | ||||
|             description = "Protocol to use for upstream DNS queries."; | ||||
|           }; | ||||
|         }; | ||||
|       }); | ||||
|       default = []; | ||||
|       description = "List of additional upstream DNS server configurations."; | ||||
|     }; | ||||
| 
 | ||||
|     blocklists = { | ||||
|       ad_malware = { | ||||
|         enable = lib.mkEnableOption "Host file for blocking ads and malware"; | ||||
|         url = lib.mkOption { | ||||
|           type = lib.types.str; | ||||
|           default = "http://sbc.io/hosts/hosts"; | ||||
|           description = "URL of the ad and malware blocklist host file"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     extraBlocklists = lib.mkOption { | ||||
|       type = lib.types.listOf lib.types.str; | ||||
|       default = []; | ||||
|       description = "Additional blocklist URLs to be added to the configuration"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf cfg.enable { | ||||
|     # Assertions for proper configuration | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = !(cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && config.services.resolved.enable && cfg.downstreams.host.disableSystemdResolved); | ||||
|         message = "crab-hole host downstream cannot use port 53 while systemd-resolved is enabled. Either disable systemd-resolved or use a different port."; | ||||
|       } | ||||
|       { | ||||
|         assertion = !(cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && !cfg.downstreams.host.disableSystemdResolved && config.services.resolved.enable); | ||||
|         message = "crab-hole host downstream is configured to use port 53 but systemd-resolved is still enabled and disableSystemdResolved is false. Set disableSystemdResolved = true or manually disable systemd-resolved."; | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     # Automatically disable systemd-resolved if using port 53 | ||||
|     services.resolved.enable = lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && cfg.downstreams.host.disableSystemdResolved) (lib.mkForce false); | ||||
| 
 | ||||
|     # Configure DNS nameservers when disabling systemd-resolved | ||||
|     networking.nameservers = lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && cfg.downstreams.host.disableSystemdResolved) (lib.mkDefault ["127.0.0.1" "1.1.1.1" "8.8.8.8"]); | ||||
| 
 | ||||
|     services.crab-hole.settings = lib.mkMerge [ | ||||
|       { | ||||
|         api = { | ||||
|           port = cfg.port; | ||||
|           listen = cfg.listen; | ||||
|           show_doc = cfg.show_doc; | ||||
|         }; | ||||
|         downstream = cfg.extraDownstreams; | ||||
|         upstream.name_servers = cfg.extraUpstreams; | ||||
|         blocklist.lists = cfg.extraBlocklists; | ||||
|       } | ||||
|       (lib.mkIf cfg.blocklists.ad_malware.enable { | ||||
|         blocklist.lists = [cfg.blocklists.ad_malware.url]; | ||||
|       }) | ||||
|       (lib.mkIf cfg.downstreams.host.enable { | ||||
|         downstream = [ | ||||
|           { | ||||
|             protocol = "udp"; | ||||
|             listen = "0.0.0.0"; | ||||
|             port = cfg.downstreams.host.port; | ||||
|           } | ||||
|         ]; | ||||
|       }) | ||||
|       (lib.mkIf cfg.upstreams.cloudFlare.enable { | ||||
|         upstream.name_servers = [ | ||||
|           { | ||||
|             socket_addr = "1.1.1.1:853"; | ||||
|             protocol = "tls"; | ||||
|             tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; | ||||
|             trust_nx_responses = false; | ||||
|           } | ||||
|           { | ||||
|             socket_addr = "1.0.0.1:853"; | ||||
|             protocol = "tls"; | ||||
|             tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; | ||||
|             trust_nx_responses = false; | ||||
|           } | ||||
|           { | ||||
|             socket_addr = "[2606:4700:4700::1111]:853"; | ||||
|             protocol = "tls"; | ||||
|             tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; | ||||
|             trust_nx_responses = false; | ||||
|           } | ||||
|           { | ||||
|             socket_addr = "[2606:4700:4700::1001]:853"; | ||||
|             protocol = "tls"; | ||||
|             tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; | ||||
|             trust_nx_responses = false; | ||||
|           } | ||||
|         ]; | ||||
|       }) | ||||
|     ]; | ||||
| 
 | ||||
|     # Open firewall if requested | ||||
|     networking.firewall = lib.mkMerge [ | ||||
|       (lib.mkIf cfg.openFirewall { | ||||
|         allowedTCPPorts = [cfg.port]; | ||||
|       }) | ||||
|       (lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.openFirewall) { | ||||
|         allowedUDPPorts = [cfg.downstreams.host.port]; | ||||
|       }) | ||||
|     ]; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										6
									
								
								modules/nixos-modules/server/crab-hole/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								modules/nixos-modules/server/crab-hole/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./crab-hole.nix | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										33
									
								
								modules/nixos-modules/server/crab-hole/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								modules/nixos-modules/server/crab-hole/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   workingDirectory = "/var/lib/private/crab-hole"; | ||||
| in { | ||||
|   options.services.crab-hole = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.crab-hole.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.crab-hole.impermanence.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = | ||||
|           config.systemd.services.crab-hole.serviceConfig.WorkingDirectory == (builtins.replaceStrings ["/private"] [""] workingDirectory); | ||||
|         message = "crab-hole working directory does not match persistence"; | ||||
|       } | ||||
|     ]; | ||||
|     environment.persistence."/persist/system/root" = { | ||||
|       directories = [ | ||||
|         { | ||||
|           directory = workingDirectory; | ||||
|           user = "crab-hole"; | ||||
|           group = "crab-hole"; | ||||
|         } | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -1,20 +1,23 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./reverse_proxy.nix | ||||
|     ./fail2ban.nix | ||||
|     ./postgres.nix | ||||
|     ./reverseProxy | ||||
|     ./fail2ban | ||||
|     ./postgres | ||||
|     ./network_storage | ||||
|     ./podman.nix | ||||
| 
 | ||||
|     ./actual | ||||
|     ./bazarr | ||||
|     ./crab-hole | ||||
|     ./flaresolverr | ||||
|     ./forgejo | ||||
|     ./home-assistant | ||||
|     ./immich | ||||
|     ./jackett | ||||
|     ./jellyfin | ||||
|     ./lidarr | ||||
|     ./panoramax | ||||
|     ./paperless | ||||
|     ./qbittorent.nix | ||||
|     ./qbittorent | ||||
|     ./radarr | ||||
|     ./searx | ||||
|     ./sonarr | ||||
|  |  | |||
|  | @ -1,74 +0,0 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   dataFolder = "/var/lib/fail2ban"; | ||||
|   dataFile = "fail2ban.sqlite3"; | ||||
| in { | ||||
|   config = lib.mkIf config.services.fail2ban.enable (lib.mkMerge [ | ||||
|     { | ||||
|       environment.etc = { | ||||
|         "fail2ban/filter.d/nginx.local".text = lib.mkIf config.services.nginx.enable ( | ||||
|           pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|             [Definition] | ||||
|             failregex = "limiting requests, excess:.* by zone.*client: <HOST>" | ||||
|           '') | ||||
|         ); | ||||
|       }; | ||||
| 
 | ||||
|       services.fail2ban = { | ||||
|         maxretry = 5; | ||||
|         ignoreIP = [ | ||||
|           # Whitelist local networks | ||||
|           "10.0.0.0/8" | ||||
|           "172.16.0.0/12" | ||||
|           "192.168.0.0/16" | ||||
| 
 | ||||
|           # tail scale tailnet | ||||
|           "100.64.0.0/10" | ||||
|           "fd7a:115c:a1e0::/48" | ||||
|         ]; | ||||
|         bantime = "24h"; # Ban IPs for one day on the first ban | ||||
|         bantime-increment = { | ||||
|           enable = true; # Enable increment of bantime after each violation | ||||
|           formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)"; | ||||
|           maxtime = "168h"; # Do not ban for more than 1 week | ||||
|           overalljails = true; # Calculate the ban time based on all the violations | ||||
|         }; | ||||
|         jails = { | ||||
|           nginx-iptables.settings = lib.mkIf config.services.nginx.enable { | ||||
|             enabled = true; | ||||
|             filter = "nginx"; | ||||
|             action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|             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 {}; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|     (lib.mkIf config.host.impermanence.enable { | ||||
|       assertions = [ | ||||
|         { | ||||
|           assertion = config.services.fail2ban.daemonSettings.Definition.dbfile == "${dataFolder}/${dataFile}"; | ||||
|           message = "fail2ban data file does not match persistence"; | ||||
|         } | ||||
|       ]; | ||||
| 
 | ||||
|       environment.persistence."/persist/system/root" = { | ||||
|         directories = [ | ||||
|           { | ||||
|             directory = dataFolder; | ||||
|             user = "fail2ban"; | ||||
|             group = "fail2ban"; | ||||
|           } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]); | ||||
| } | ||||
							
								
								
									
										6
									
								
								modules/nixos-modules/server/fail2ban/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								modules/nixos-modules/server/fail2ban/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./fail2ban.nix | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										51
									
								
								modules/nixos-modules/server/fail2ban/fail2ban.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								modules/nixos-modules/server/fail2ban/fail2ban.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| { | ||||
|   lib, | ||||
|   pkgs, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf config.services.fail2ban.enable { | ||||
|     environment.etc = { | ||||
|       "fail2ban/filter.d/nginx.local".text = lib.mkIf config.services.nginx.enable ( | ||||
|         pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|           [Definition] | ||||
|           failregex = "limiting requests, excess:.* by zone.*client: <HOST>" | ||||
|         '') | ||||
|       ); | ||||
|     }; | ||||
| 
 | ||||
|     services.fail2ban = { | ||||
|       maxretry = 5; | ||||
|       ignoreIP = [ | ||||
|         # Whitelist local networks | ||||
|         "10.0.0.0/8" | ||||
|         "172.16.0.0/12" | ||||
|         "192.168.0.0/16" | ||||
| 
 | ||||
|         # tail scale tailnet | ||||
|         "100.64.0.0/10" | ||||
|         "fd7a:115c:a1e0::/48" | ||||
|       ]; | ||||
|       bantime = "24h"; # Ban IPs for one day on the first ban | ||||
|       bantime-increment = { | ||||
|         enable = true; # Enable increment of bantime after each violation | ||||
|         formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)"; | ||||
|         maxtime = "168h"; # Do not ban for more than 1 week | ||||
|         overalljails = true; # Calculate the ban time based on all the violations | ||||
|       }; | ||||
|       jails = { | ||||
|         nginx-iptables.settings = lib.mkIf config.services.nginx.enable { | ||||
|           enabled = true; | ||||
|           filter = "nginx"; | ||||
|           action = ''iptables-multiport[name=HTTP, port="http,https"]''; | ||||
|           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 {}; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										34
									
								
								modules/nixos-modules/server/fail2ban/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								modules/nixos-modules/server/fail2ban/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   dataFolder = "/var/lib/fail2ban"; | ||||
|   dataFile = "fail2ban.sqlite3"; | ||||
| in { | ||||
|   options.services.fail2ban = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.fail2ban.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.fail2ban.impermanence.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.fail2ban.daemonSettings.Definition.dbfile == "${dataFolder}/${dataFile}"; | ||||
|         message = "fail2ban data file does not match persistence"; | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     environment.persistence."/persist/system/root" = { | ||||
|       directories = [ | ||||
|         { | ||||
|           directory = dataFolder; | ||||
|           user = "fail2ban"; | ||||
|           group = "fail2ban"; | ||||
|         } | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										5
									
								
								modules/nixos-modules/server/flaresolverr/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								modules/nixos-modules/server/flaresolverr/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| {...}: { | ||||
|   imports = [ | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										26
									
								
								modules/nixos-modules/server/flaresolverr/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								modules/nixos-modules/server/flaresolverr/impermanence.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   options.services.flaresolverr = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.flaresolverr.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.flaresolverr.impermanence.enable { | ||||
|     # FlareSolverr typically doesn't need persistent storage as it's a proxy service | ||||
|     # but we'll add basic structure in case it's needed for logs or configuration | ||||
|     environment.persistence."/persist/system/root" = { | ||||
|       directories = [ | ||||
|         { | ||||
|           directory = "/var/lib/flaresolverr"; | ||||
|           user = "flaresolverr"; | ||||
|           group = "flaresolverr"; | ||||
|         } | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -2,40 +2,31 @@ | |||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf config.services.forgejo.enable ( | ||||
|     lib.mkMerge [ | ||||
|       { | ||||
|         host = { | ||||
|           postgres = { | ||||
|             enable = true; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
| }: let | ||||
|   usingPostgres = config.services.forgejo.database.type == "postgres"; | ||||
| in { | ||||
|   config = lib.mkIf config.services.forgejo.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|             assertion = config.services.forgejo.settings.database.DB_TYPE == "postgres"; | ||||
|             message = "Forgejo database type must be postgres"; | ||||
|         assertion = !usingPostgres || config.services.postgresql.enable; | ||||
|         message = "PostgreSQL must be enabled when Forgejo database type is postgres"; | ||||
|       } | ||||
|       { | ||||
|         assertion = !(usingPostgres && config.services.forgejo.database.createDatabase) || (builtins.any (db: db == "forgejo") config.services.postgresql.ensureDatabases); | ||||
|         message = "Forgejo built-in database creation failed - expected 'forgejo' in ensureDatabases but got: ${builtins.toString config.services.postgresql.ensureDatabases}"; | ||||
|       } | ||||
|       { | ||||
|         assertion = !(usingPostgres && config.services.forgejo.database.createDatabase) || (builtins.any (user: user.name == "forgejo") config.services.postgresql.ensureUsers); | ||||
|         message = "Forgejo built-in user creation failed - expected user 'forgejo' in ensureUsers but got: ${builtins.toString (builtins.map (u: u.name) config.services.postgresql.ensureUsers)}"; | ||||
|       } | ||||
|     ]; | ||||
|       } | ||||
|       (lib.mkIf config.host.postgres.enable { | ||||
|         host = { | ||||
|           postgres = { | ||||
|             extraUsers = { | ||||
|               forgejo = { | ||||
|                 isClient = true; | ||||
|                 createUser = true; | ||||
| 
 | ||||
|     services.forgejo.database.createDatabase = lib.mkDefault usingPostgres; | ||||
| 
 | ||||
|     systemd.services.forgejo = lib.mkIf usingPostgres { | ||||
|       requires = [ | ||||
|         config.systemd.services.postgresql.name | ||||
|       ]; | ||||
|     }; | ||||
|   }; | ||||
|             extraDatabases = { | ||||
|               forgejo = { | ||||
|                 name = "forgejo"; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       }) | ||||
|     ] | ||||
|   ); | ||||
| } | ||||
|  |  | |||
|  | @ -1,53 +1,9 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   const = import ./const.nix; | ||||
|   httpPort = const.httpPort; | ||||
|   sshPort = const.sshPort; | ||||
|   db_user = "forgejo"; | ||||
| in { | ||||
|   imports = [ | ||||
|     ./forgejo.nix | ||||
|     ./proxy.nix | ||||
|     ./database.nix | ||||
|     ./fail2ban.nix | ||||
|     ./impermanence.nix | ||||
|   ]; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.forgejo.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER == config.users.users.git.name; | ||||
|         message = "Forgejo BUILTIN_SSH_SERVER_USER hardcoded value does not match expected git user name"; | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     services.forgejo = { | ||||
|       database = { | ||||
|         type = "postgres"; | ||||
|         socket = "/run/postgresql"; | ||||
|       }; | ||||
|       lfs.enable = true; | ||||
|       settings = { | ||||
|         server = { | ||||
|           DOMAIN = "${config.services.forgejo.subdomain}.${config.host.reverse_proxy.hostname}"; | ||||
|           HTTP_PORT = httpPort; | ||||
|           START_SSH_SERVER = true; | ||||
|           SSH_LISTEN_PORT = sshPort; | ||||
|           SSH_PORT = 22; | ||||
|           BUILTIN_SSH_SERVER_USER = "git"; | ||||
|           ROOT_URL = "https://git.jan-leila.com"; | ||||
|         }; | ||||
|         service = { | ||||
|           DISABLE_REGISTRATION = true; | ||||
|         }; | ||||
|         database = { | ||||
|           DB_TYPE = "postgres"; | ||||
|           NAME = db_user; | ||||
|           USER = db_user; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,16 @@ | |||
|   pkgs, | ||||
|   ... | ||||
| }: { | ||||
|   config = lib.mkIf (config.services.forgejo.enable && config.services.fail2ban.enable) { | ||||
|   options.services.forgejo = { | ||||
|     fail2ban = { | ||||
|       enable = lib.mkOption { | ||||
|         type = lib.types.bool; | ||||
|         default = config.services.forgejo.enable && config.services.fail2ban.enable; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.forgejo.fail2ban.enable { | ||||
|     environment.etc = { | ||||
|       "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( | ||||
|         pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||
|  |  | |||
							
								
								
									
										46
									
								
								modules/nixos-modules/server/forgejo/forgejo.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								modules/nixos-modules/server/forgejo/forgejo.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| { | ||||
|   lib, | ||||
|   config, | ||||
|   ... | ||||
| }: let | ||||
|   const = import ./const.nix; | ||||
|   httpPort = const.httpPort; | ||||
|   sshPort = const.sshPort; | ||||
|   db_user = "forgejo"; | ||||
| in { | ||||
|   config = lib.mkIf config.services.forgejo.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER == config.users.users.git.name; | ||||
|         message = "Forgejo BUILTIN_SSH_SERVER_USER hardcoded value does not match expected git user name"; | ||||
|       } | ||||
|     ]; | ||||
| 
 | ||||
|     services.forgejo = { | ||||
|       database = { | ||||
|         type = "postgres"; | ||||
|         socket = "/run/postgresql"; | ||||
|       }; | ||||
|       lfs.enable = true; | ||||
|       settings = { | ||||
|         server = { | ||||
|           DOMAIN = config.services.forgejo.reverseProxy.domain; | ||||
|           HTTP_PORT = httpPort; | ||||
|           START_SSH_SERVER = true; | ||||
|           SSH_LISTEN_PORT = sshPort; | ||||
|           SSH_PORT = 22; | ||||
|           BUILTIN_SSH_SERVER_USER = "git"; | ||||
|           ROOT_URL = "https://git.jan-leila.com"; | ||||
|         }; | ||||
|         service = { | ||||
|           DISABLE_REGISTRATION = true; | ||||
|         }; | ||||
|         database = { | ||||
|           DB_TYPE = "postgres"; | ||||
|           NAME = db_user; | ||||
|           USER = db_user; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | @ -5,7 +5,14 @@ | |||
| }: let | ||||
|   stateDir = "/var/lib/forgejo"; | ||||
| in { | ||||
|   config = lib.mkIf (config.services.forgejo.enable && config.host.impermanence.enable) { | ||||
|   options.services.forgejo = { | ||||
|     impermanence.enable = lib.mkOption { | ||||
|       type = lib.types.bool; | ||||
|       default = config.services.forgejo.enable && config.host.impermanence.enable; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = lib.mkIf config.services.forgejo.impermanence.enable { | ||||
|     assertions = [ | ||||
|       { | ||||
|         assertion = config.services.forgejo.stateDir == stateDir; | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue