Compare commits
	
		
			No commits in common. "main" and "main" have entirely different histories.
		
	
	
		
	
		
					 153 changed files with 1922 additions and 3088 deletions
				
			
		|  | @ -3,12 +3,4 @@ | ||||||
| 
 | 
 | ||||||
| echo "restoring stashed changes" | echo "restoring stashed changes" | ||||||
| 
 | 
 | ||||||
| # Find the most recent pre-commit stash and restore it | git stash pop -q | ||||||
| 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 |  | ||||||
|  |  | ||||||
|  | @ -1,32 +0,0 @@ | ||||||
| #!/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,24 +1,14 @@ | ||||||
| #!/usr/bin/env nix-shell | #!/usr/bin/env nix-shell | ||||||
| #! nix-shell -i bash ../shell.nix | #! nix-shell -i bash ../shell.nix | ||||||
| 
 | 
 | ||||||
| # Get current branch name | echo "stashing all uncommitted changes" | ||||||
| current_branch=$(git branch --show-current) | git stash -q --keep-index | ||||||
| 
 | 
 | ||||||
| echo "stashing all uncommitted changes with named stash (excluding hooks)" | echo "checking flakes all compile" | ||||||
| git stash push -q --keep-index -m "pre-commit-stash-$(date +%s)" -- ':!.hooks/' | nix flake check | ||||||
| 
 | 
 | ||||||
| # Only run nix flake check if we're on main branch | if [ ! $? -eq 0 ]; then | ||||||
| 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 |     exit 1 | ||||||
|     fi |  | ||||||
|     echo "nix flake check passed" |  | ||||||
| else |  | ||||||
|     echo "Not on main branch - skipping nix flake check" |  | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| echo "running linter" | echo "running linter" | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| #!/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 |  | ||||||
							
								
								
									
										90
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										90
									
								
								README.md
									
										
									
									
									
								
							|  | @ -43,65 +43,39 @@ 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 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/ | - Look into this for npins https://jade.fyi/blog/pinning-nixos-with-npins/ | ||||||
| - https://nixos-and-flakes.thiscute.world/ | - 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: | # Tasks: | ||||||
| 
 | 
 | ||||||
| ## Chores: |  | ||||||
| - [ ] test out crab hole service |  | ||||||
| 
 |  | ||||||
| ## Tech Debt | ## 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/) | - 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 | - nfs export should be backed by the same values for server and client | ||||||
| 
 | ## New Features | ||||||
| ## Broken things | - crab-hole | ||||||
| - [ ] figure out steam vr things? | - figure out why syncthing and jellyfins permissions don't propagate downwards | ||||||
| - [ ] whisper was having issues | - figure out steam vr things? | ||||||
| 
 | - auto turn off on power loss - nut | ||||||
| ## Data Integrity | - zfs email after scrubbing # TODO: test this | ||||||
| - [ ] zfs email after scrubbing # TODO: test this | - SMART test with email results | ||||||
| - [ ] SMART test with email results | - samba mounts | ||||||
| - [ ] zfs encryption FIDO2 2fa (look into shavee) | - 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) | ||||||
| - [ ] rotate sops encryption keys periodically (and somehow sync between devices?) | - Create Tor guard/relay server | ||||||
| - [ ] Secure Boot - https://github.com/nix-community/lanzaboote | - migrate away from flakes and move to npins | ||||||
| - [ ] auto turn off on power loss - nut | - whisper | ||||||
| - [ ] 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 | - zfs encryption FIDO2 2fa (look into shavee) | ||||||
| 
 | - Secure Boot - https://github.com/nix-community/lanzaboote | ||||||
| ## Data Access | - rotate sops encryption keys periodically (and somehow sync between devices?) | ||||||
| - [ ] nfs export should be backed by the same values for server and client | - wake on LAN for updates | ||||||
| - [ ] samba mounts | - remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html | ||||||
| - [ ] 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) | - ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix | ||||||
| - [ ] figure out why syncthing and jellyfins permissions don't propagate downwards | - panoramax instance | ||||||
| - [ ] make radarr, sonarr, and bazarr accessible over vpn | - mastodon instance | ||||||
| - [ ] move searx, home-assistant, actual, vikunja, jellyfin, paperless, and immich to only be accessible via vpn | - 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 | ||||||
| ## Services | - make radarr, sonarr, and bazarr accessible over vpn | ||||||
| - [ ] vikunja service for project management | - create some sort of service that allows uploading files to jellyfin | ||||||
| - [ ] Penpot services (need to make this custom) | 	- auto sort files into where they should go with some combination of filebot cli and picard cli | ||||||
| - [ ] minecraft server with old world file | - graphana accessible though tailscale | ||||||
| - [ ] Create Tor guard/relay server | - fix panoramax package | ||||||
| - [ ] mastodon instance | - actual instance | ||||||
| - [ ] screeps server | - intergrade radarr, sonarr, and bazarr | ||||||
| 
 | - claude code MCP servers should bundle node with them so they work in all environments | ||||||
| ## 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,39 +1,12 @@ | ||||||
| { | {pkgs, ...}: { | ||||||
|   osConfig, |  | ||||||
|   lib, |  | ||||||
|   ... |  | ||||||
| }: { |  | ||||||
|   config = { |   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 = { |     dconf = { | ||||||
|       enable = true; |       enable = true; | ||||||
|  |       settings = { | ||||||
|  |         "org/gnome/shell".enabled-extensions = [ | ||||||
|  |           pkgs.gnomeExtensions.dash-to-panel.extensionUuid | ||||||
|  |         ]; | ||||||
|  |       }; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,7 +18,6 @@ in { | ||||||
|     home.packages = lib.lists.optionals userConfig.isDesktopUser ( |     home.packages = lib.lists.optionals userConfig.isDesktopUser ( | ||||||
|       with pkgs; [ |       with pkgs; [ | ||||||
|         gnomeExtensions.dash-to-panel |         gnomeExtensions.dash-to-panel | ||||||
|         claude-code |  | ||||||
|       ] |       ] | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | @ -32,11 +31,9 @@ in { | ||||||
|       (lib.mkIf (config.user.isDesktopUser || config.user.isTerminalUser) { |       (lib.mkIf (config.user.isDesktopUser || config.user.isTerminalUser) { | ||||||
|         git = { |         git = { | ||||||
|           enable = true; |           enable = true; | ||||||
|           settings = { |           userName = "Eve"; | ||||||
|             user.name = "Eve"; |           userEmail = "evesnrobins@gmail.com"; | ||||||
|             user.email = "evesnrobins@gmail.com"; |           extraConfig.init.defaultBranch = "main"; | ||||||
|             init.defaultBranch = "main"; |  | ||||||
|           }; |  | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         openssh = { |         openssh = { | ||||||
|  | @ -64,22 +61,6 @@ in { | ||||||
|         piper.enable = hardware.piperMouse.enable; |         piper.enable = hardware.piperMouse.enable; | ||||||
|         krita.enable = true; |         krita.enable = true; | ||||||
|         ungoogled-chromium.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,6 +1,4 @@ | ||||||
| {osConfig, ...}: { | {osConfig, ...}: { | ||||||
|   impermanence.fallbackPersistence.enable = false; |  | ||||||
| 
 |  | ||||||
|   home = { |   home = { | ||||||
|     username = osConfig.users.users.git.name; |     username = osConfig.users.users.git.name; | ||||||
|     homeDirectory = osConfig.users.users.git.home; |     homeDirectory = osConfig.users.users.git.home; | ||||||
|  |  | ||||||
|  | @ -1,43 +1,31 @@ | ||||||
| {...}: { | {pkgs, ...}: { | ||||||
|   config = { |   config = { | ||||||
|     gnome = { |     gnome = { | ||||||
|       extraWindowControls = true; |       extraWindowControls = true; | ||||||
|       colorScheme = "prefer-dark"; |       colorScheme = "prefer-dark"; | ||||||
|       clockFormat = "24h"; |       clockFormat = "24h"; | ||||||
|       nightLight = { |       extensions = [ | ||||||
|         enable = true; |         pkgs.gnomeExtensions.dash-to-dock | ||||||
|         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 = { |       hotkeys = { | ||||||
|         "Open Terminal" = { |         "Open Terminal" = { | ||||||
|           binding = "<Super>t"; |           binding = "<Super>t"; | ||||||
|           command = "kgx"; |           command = "kgx"; | ||||||
|         }; |         }; | ||||||
|         "Open Firefox" = { |  | ||||||
|           binding = "<Super>f"; |  | ||||||
|           command = "firefox"; |  | ||||||
|         }; |  | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     dconf = { |     dconf = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       settings = { |       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" = { |         "org/gnome/shell" = { | ||||||
|           favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; |           favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; | ||||||
|           # app-picker-layout = |           # app-picker-layout = | ||||||
|  |  | ||||||
|  | @ -12,8 +12,6 @@ | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   config = { |   config = { | ||||||
|     impermanence.enable = osConfig.host.impermanence.enable; |  | ||||||
| 
 |  | ||||||
|     # Home Manager needs a bit of information about you and the paths it should |     # Home Manager needs a bit of information about you and the paths it should | ||||||
|     # manage. |     # manage. | ||||||
|     home = { |     home = { | ||||||
|  | @ -89,6 +87,7 @@ | ||||||
|     # TODO: move this into a fonts module |     # TODO: move this into a fonts module | ||||||
|     home.packages = with pkgs; [ |     home.packages = with pkgs; [ | ||||||
|       aileron |       aileron | ||||||
|  |       nerd-fonts.open-dyslexic | ||||||
|     ]; |     ]; | ||||||
|     fonts.fontconfig.enable = true; |     fonts.fontconfig.enable = true; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | @ -1,9 +1,10 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   config = lib.mkIf (config.impermanence.enable) { |   config = lib.mkIf osConfig.host.impermanence.enable { | ||||||
|     home.persistence."/persist/home/leyla" = { |     home.persistence."/persist/home/leyla" = { | ||||||
|       directories = [ |       directories = [ | ||||||
|         "desktop" |         "desktop" | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| in { | in { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./vscode |     ./vscode | ||||||
|     ./firefox |     ./firefox.nix | ||||||
|     ./direnv.nix |     ./direnv.nix | ||||||
|     ./openssh.nix |     ./openssh.nix | ||||||
|     ./git.nix |     ./git.nix | ||||||
|  |  | ||||||
							
								
								
									
										344
									
								
								configurations/home-manager/leyla/packages/firefox.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								configurations/home-manager/leyla/packages/firefox.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,344 @@ | ||||||
|  | { | ||||||
|  |   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 = [""]; | ||||||
|  |             # } | ||||||
|  |           ]; | ||||||
|  |         }; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | @ -1,149 +0,0 @@ | ||||||
| {...}: { |  | ||||||
|   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 = [""]; |  | ||||||
|           # } |  | ||||||
|         ]; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| { |  | ||||||
|   lib, |  | ||||||
|   pkgs, |  | ||||||
|   inputs, |  | ||||||
|   ... |  | ||||||
| }: { |  | ||||||
|   imports = [ |  | ||||||
|     ./firefox.nix |  | ||||||
|     ./bookmarks.nix |  | ||||||
|     ./harden.nix |  | ||||||
|   ]; |  | ||||||
| 
 |  | ||||||
|   config = { |  | ||||||
|     programs.firefox = { |  | ||||||
|       enable = true; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,221 +0,0 @@ | ||||||
| { |  | ||||||
|   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; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| {...}: { |  | ||||||
|   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,11 +2,9 @@ | ||||||
|   config = { |   config = { | ||||||
|     programs = { |     programs = { | ||||||
|       git = { |       git = { | ||||||
|         settings = { |         userName = "Leyla Becker"; | ||||||
|           user.name = "Leyla Becker"; |         userEmail = "git@jan-leila.com"; | ||||||
|           user.email = "git@jan-leila.com"; |         extraConfig.init.defaultBranch = "main"; | ||||||
|           init.defaultBranch = "main"; |  | ||||||
|         }; |  | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | @ -32,7 +32,6 @@ in { | ||||||
|               "javascript.updateImportsOnFileMove.enabled" = "always"; |               "javascript.updateImportsOnFileMove.enabled" = "always"; | ||||||
|               "editor.tabSize" = 2; |               "editor.tabSize" = 2; | ||||||
|               "editor.insertSpaces" = false; |               "editor.insertSpaces" = false; | ||||||
|               # "terminal.integrated.fontFamily" = "'Droid Sans Mono', 'monospace', monospace"; |  | ||||||
|             } |             } | ||||||
|           ]; |           ]; | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +40,6 @@ in { | ||||||
|             oneDark.enable = true; |             oneDark.enable = true; | ||||||
|             atomKeybindings.enable = true; |             atomKeybindings.enable = true; | ||||||
|             openRemoteSsh.enable = true; |             openRemoteSsh.enable = true; | ||||||
|             # openDyslexicFont.enable = false; |  | ||||||
| 
 | 
 | ||||||
|             # html development |             # html development | ||||||
|             autoRenameTag.enable = true; |             autoRenameTag.enable = true; | ||||||
|  | @ -69,9 +67,6 @@ in { | ||||||
|             # go development |             # go development | ||||||
|             go.enable = true; |             go.enable = true; | ||||||
| 
 | 
 | ||||||
|             # rust development |  | ||||||
|             rustAnalyzer.enable = true; |  | ||||||
| 
 |  | ||||||
|             # claude development |             # claude development | ||||||
|             claudeDev = lib.mkIf ai-tooling-enabled { |             claudeDev = lib.mkIf ai-tooling-enabled { | ||||||
|               enable = true; |               enable = true; | ||||||
|  |  | ||||||
|  | @ -57,6 +57,7 @@ | ||||||
|             "ata-ST18000NT001-3NF101_ZVTEF27J" |             "ata-ST18000NT001-3NF101_ZVTEF27J" | ||||||
|             "ata-ST18000NE000-3G6101_ZVTJ7359" |             "ata-ST18000NE000-3G6101_ZVTJ7359" | ||||||
|           ] |           ] | ||||||
|  |           # TODO: this needs to be configured manually | ||||||
|           [ |           [ | ||||||
|             "ata-ST4000NE001-2MA101_WS2275P3" |             "ata-ST4000NE001-2MA101_WS2275P3" | ||||||
|             "ata-ST4000NE001-2MA101_WS227B9F" |             "ata-ST4000NE001-2MA101_WS227B9F" | ||||||
|  | @ -102,6 +103,18 @@ | ||||||
|         directories = ["leyla_documents" "eve_documents" "users_documents" "media"]; |         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 = { |   systemd.network = { | ||||||
|  | @ -213,12 +226,6 @@ | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   services = { |   services = { | ||||||
|     # PostgreSQL database server |  | ||||||
|     postgresql = { |  | ||||||
|       enable = true; |  | ||||||
|       adminUsers = ["leyla"]; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     # temp enable desktop environment for setup |     # temp enable desktop environment for setup | ||||||
|     # Enable the X11 windowing system. |     # Enable the X11 windowing system. | ||||||
|     xserver.enable = true; |     xserver.enable = true; | ||||||
|  | @ -231,16 +238,6 @@ | ||||||
|       gnome.enable = true; |       gnome.enable = true; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     # Enable new reverse proxy system |  | ||||||
|     reverseProxy = { |  | ||||||
|       enable = true; |  | ||||||
|       openFirewall = true; |  | ||||||
|       acme = { |  | ||||||
|         enable = true; |  | ||||||
|         email = "jan-leila@protonmail.com"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     ollama = { |     ollama = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       exposePort = true; |       exposePort = true; | ||||||
|  | @ -298,35 +295,35 @@ | ||||||
| 
 | 
 | ||||||
|     jellyfin = { |     jellyfin = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       domain = "media.jan-leila.com"; |       subdomain = "media"; | ||||||
|       extraDomains = ["jellyfin.jan-leila.com"]; |       extraSubdomains = ["jellyfin"]; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     immich = { |     immich = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       domain = "photos.jan-leila.com"; |       subdomain = "photos"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     forgejo = { |     forgejo = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       reverseProxy.domain = "git.jan-leila.com"; |       subdomain = "git"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     searx = { |     searx = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       domain = "search.jan-leila.com"; |       subdomain = "search"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     actual = { |     actual = { | ||||||
|       enable = true; |       enable = false; | ||||||
|       domain = "budget.jan-leila.com"; |       subdomain = "budget"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     home-assistant = { |     home-assistant = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       domain = "home.jan-leila.com"; |       subdomain = "home"; | ||||||
|       openFirewall = true; |       openFirewall = true; | ||||||
|       postgres.enable = true; |       database = "postgres"; | ||||||
| 
 | 
 | ||||||
|       extensions = { |       extensions = { | ||||||
|         sonos.enable = true; |         sonos.enable = true; | ||||||
|  | @ -337,7 +334,7 @@ | ||||||
| 
 | 
 | ||||||
|     paperless = { |     paperless = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       domain = "documents.jan-leila.com"; |       subdomain = "documents"; | ||||||
|       passwordFile = config.sops.secrets."services/paperless_password".path; |       passwordFile = config.sops.secrets."services/paperless_password".path; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -346,21 +343,6 @@ | ||||||
|       openFirewall = true; |       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 = { |     qbittorrent = { | ||||||
|       enable = true; |       enable = true; | ||||||
|       mediaDir = "/srv/qbittorent"; |       mediaDir = "/srv/qbittorent"; | ||||||
|  | @ -368,28 +350,21 @@ | ||||||
|       webuiPort = 8084; |       webuiPort = 8084; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     sonarr = { |     filebot-cleanup = { | ||||||
|       enable = true; |       enable = true; | ||||||
|  |       licenseFile = "/srv/jellyfin/filebot_license.psm"; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     sonarr = { | ||||||
|  |       enable = false; | ||||||
|       openFirewall = true; |       openFirewall = true; | ||||||
|     }; |     }; | ||||||
|     radarr = { |     radarr = { | ||||||
|       enable = true; |       enable = false; | ||||||
|       openFirewall = true; |       openFirewall = true; | ||||||
|     }; |     }; | ||||||
|     bazarr = { |     bazarr = { | ||||||
|       enable = true; |       enable = false; | ||||||
|       openFirewall = true; |  | ||||||
|     }; |  | ||||||
|     lidarr = { |  | ||||||
|       enable = true; |  | ||||||
|       openFirewall = true; |  | ||||||
|     }; |  | ||||||
|     jackett = { |  | ||||||
|       enable = true; |  | ||||||
|       openFirewall = true; |  | ||||||
|     }; |  | ||||||
|     flaresolverr = { |  | ||||||
|       enable = true; |  | ||||||
|       openFirewall = true; |       openFirewall = true; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | @ -4,5 +4,6 @@ | ||||||
|     ./hardware-configuration.nix |     ./hardware-configuration.nix | ||||||
|     ./configuration.nix |     ./configuration.nix | ||||||
|     ./packages.nix |     ./packages.nix | ||||||
|  |     ./filebot.nix | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										82
									
								
								configurations/nixos/defiant/filebot.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								configurations/nixos/defiant/filebot.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | ||||||
|  | { | ||||||
|  |   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,14 +41,12 @@ | ||||||
| 
 | 
 | ||||||
|   # installed opentabletdriver |   # installed opentabletdriver | ||||||
|   hardware.opentabletdriver.enable = true; |   hardware.opentabletdriver.enable = true; | ||||||
|   hardware.keyboard.qmk.enable = true; |  | ||||||
| 
 | 
 | ||||||
|   # Enable the GNOME Desktop Environment. |   # Enable the GNOME Desktop Environment. | ||||||
|   services.displayManager.gdm.enable = true; |   services.displayManager.gdm.enable = true; | ||||||
|   services.desktopManager.gnome.enable = true; |   services.desktopManager.gnome.enable = true; | ||||||
| 
 | 
 | ||||||
|   host = { |   host = { | ||||||
|     ai.enable = true; |  | ||||||
|     users = { |     users = { | ||||||
|       eve = { |       eve = { | ||||||
|         isDesktopUser = true; |         isDesktopUser = true; | ||||||
|  | @ -70,9 +68,6 @@ | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   services.tailscale.enable = true; |   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 |   # Configure keymap in X11 | ||||||
|   # services.xserver.xkb.layout = "us"; |   # services.xserver.xkb.layout = "us"; | ||||||
|  |  | ||||||
							
								
								
									
										110
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										110
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							|  | @ -25,11 +25,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1760701190, |         "lastModified": 1758287904, | ||||||
|         "narHash": "sha256-y7UhnWlER8r776JsySqsbTUh2Txf7K30smfHlqdaIQw=", |         "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", | ||||||
|         "owner": "nix-community", |         "owner": "nix-community", | ||||||
|         "repo": "disko", |         "repo": "disko", | ||||||
|         "rev": "3a9450b26e69dcb6f8de6e2b07b3fc1c288d85f5", |         "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -46,11 +46,11 @@ | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "dir": "pkgs/firefox-addons", |         "dir": "pkgs/firefox-addons", | ||||||
|         "lastModified": 1761797037, |         "lastModified": 1759403080, | ||||||
|         "narHash": "sha256-OqwAGit+3cdsG02K6+8WJniA2q0rqUVc6zbT5N9C1us=", |         "narHash": "sha256-EteyL8KyG9R5xzqyOBzyag4n2cSemu61VFrl3opJSqE=", | ||||||
|         "owner": "rycee", |         "owner": "rycee", | ||||||
|         "repo": "nur-expressions", |         "repo": "nur-expressions", | ||||||
|         "rev": "3d9f4de0988bcfa57e45e16e1ef9326c56bdf891", |         "rev": "8af6dfcbcbf1115a4f5aeed77ff0db5d3c02caf0", | ||||||
|         "type": "gitlab" |         "type": "gitlab" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -62,11 +62,11 @@ | ||||||
|     }, |     }, | ||||||
|     "flake-compat": { |     "flake-compat": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761588595, |         "lastModified": 1747046372, | ||||||
|         "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", |         "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", | ||||||
|         "owner": "edolstra", |         "owner": "edolstra", | ||||||
|         "repo": "flake-compat", |         "repo": "flake-compat", | ||||||
|         "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", |         "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -111,6 +111,24 @@ | ||||||
|         "type": "github" |         "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": { |     "flakey-profile": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1712898590, |         "lastModified": 1712898590, | ||||||
|  | @ -133,11 +151,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761845621, |         "lastModified": 1759337100, | ||||||
|         "narHash": "sha256-d+R4MHsGmdebvSMsYUFWONsZSlUbOo8Zq/wjMdMiIac=", |         "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", | ||||||
|         "owner": "nix-community", |         "owner": "nix-community", | ||||||
|         "repo": "home-manager", |         "repo": "home-manager", | ||||||
|         "rev": "97e3022a8d2c09313fa49847f6da4d76abcfc72d", |         "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -164,11 +182,11 @@ | ||||||
|     "lix": { |     "lix": { | ||||||
|       "flake": false, |       "flake": false, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1755787066, |         "lastModified": 1759624822, | ||||||
|         "narHash": "sha256-X2UwkUEban08GRSPXRr+kz8fckHqebr3P77qSvjoeOw=", |         "narHash": "sha256-cf40qfsfpxJU/BnQ9PEj027LdPINNSsJqm+C6Ug93BA=", | ||||||
|         "rev": "ac9721a92e8138d29707824dbedb484c76948493", |         "rev": "57333a0e600c5e096a609410a2f1059b97194b1e", | ||||||
|         "type": "tarball", |         "type": "tarball", | ||||||
|         "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/ac9721a92e8138d29707824dbedb484c76948493.tar.gz?rev=ac9721a92e8138d29707824dbedb484c76948493" |         "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/57333a0e600c5e096a609410a2f1059b97194b1e.tar.gz" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|         "type": "tarball", |         "type": "tarball", | ||||||
|  | @ -185,11 +203,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1759851320, |         "lastModified": 1756511062, | ||||||
|         "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", |         "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", | ||||||
|         "ref": "refs/heads/main", |         "ref": "refs/heads/main", | ||||||
|         "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", |         "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", | ||||||
|         "revCount": 163, |         "revCount": 162, | ||||||
|         "type": "git", |         "type": "git", | ||||||
|         "url": "https://git.lix.systems/lix-project/nixos-module.git" |         "url": "https://git.lix.systems/lix-project/nixos-module.git" | ||||||
|       }, |       }, | ||||||
|  | @ -207,11 +225,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1760821194, |         "lastModified": 1759342933, | ||||||
|         "narHash": "sha256-UCsJ8eDuHL14u2GFIYEY/drtZ6jht5zN/G/6QNlEy2g=", |         "narHash": "sha256-mdlUFcrOfvT0Pm+Hko/6aR3xf1ao5JA2iem4KsEVjP4=", | ||||||
|         "owner": "utensils", |         "owner": "utensils", | ||||||
|         "repo": "mcp-nixos", |         "repo": "mcp-nixos", | ||||||
|         "rev": "0ae453f38d0f088c31d4678da3a12b183165986f", |         "rev": "50b02bcba32b941d2ec48fedef68641702ca5b0f", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -227,11 +245,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761339987, |         "lastModified": 1758805352, | ||||||
|         "narHash": "sha256-IUaawVwItZKi64IA6kF6wQCLCzpXbk2R46dHn8sHkig=", |         "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=", | ||||||
|         "owner": "LnL7", |         "owner": "LnL7", | ||||||
|         "repo": "nix-darwin", |         "repo": "nix-darwin", | ||||||
|         "rev": "7cd9aac79ee2924a85c211d21fafd394b06a38de", |         "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -263,16 +281,17 @@ | ||||||
|     }, |     }, | ||||||
|     "nix-vscode-extensions": { |     "nix-vscode-extensions": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|  |         "flake-utils": "flake-utils_3", | ||||||
|         "nixpkgs": [ |         "nixpkgs": [ | ||||||
|           "nixpkgs" |           "nixpkgs" | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761789484, |         "lastModified": 1759369908, | ||||||
|         "narHash": "sha256-17gDUWloFXQlavqHRey/urQe6sQ3yP5hsQyYmcNOZyU=", |         "narHash": "sha256-IIhaE6jAge64z+fIyi/8Vtu0JdTtapbp4CvwiuIkZ1E=", | ||||||
|         "owner": "nix-community", |         "owner": "nix-community", | ||||||
|         "repo": "nix-vscode-extensions", |         "repo": "nix-vscode-extensions", | ||||||
|         "rev": "c47e683d236fa6e4c27dbda2af3468cb9aceb813", |         "rev": "a66ad2141b1440a838ead278c6edfe8a4ce75e6c", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -283,11 +302,11 @@ | ||||||
|     }, |     }, | ||||||
|     "nixos-hardware": { |     "nixos-hardware": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761827175, |         "lastModified": 1759261527, | ||||||
|         "narHash": "sha256-XdPVSYyIBK4/ruoqujaQmmSGg3J2/EenexV9IEXhr6o=", |         "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", | ||||||
|         "owner": "NixOS", |         "owner": "NixOS", | ||||||
|         "repo": "nixos-hardware", |         "repo": "nixos-hardware", | ||||||
|         "rev": "43ffe9ac82567512abb83187cb673de1091bdfa8", |         "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -315,11 +334,11 @@ | ||||||
|     }, |     }, | ||||||
|     "nixpkgs_2": { |     "nixpkgs_2": { | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1761672384, |         "lastModified": 1759381078, | ||||||
|         "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", |         "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", | ||||||
|         "owner": "nixos", |         "owner": "nixos", | ||||||
|         "repo": "nixpkgs", |         "repo": "nixpkgs", | ||||||
|         "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", |         "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -370,11 +389,11 @@ | ||||||
|         ] |         ] | ||||||
|       }, |       }, | ||||||
|       "locked": { |       "locked": { | ||||||
|         "lastModified": 1760998189, |         "lastModified": 1759188042, | ||||||
|         "narHash": "sha256-ee2e1/AeGL5X8oy/HXsZQvZnae6XfEVdstGopKucYLY=", |         "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", | ||||||
|         "owner": "Mic92", |         "owner": "Mic92", | ||||||
|         "repo": "sops-nix", |         "repo": "sops-nix", | ||||||
|         "rev": "5a7d18b5c55642df5c432aadb757140edfeb70b3", |         "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", | ||||||
|         "type": "github" |         "type": "github" | ||||||
|       }, |       }, | ||||||
|       "original": { |       "original": { | ||||||
|  | @ -412,6 +431,21 @@ | ||||||
|         "repo": "default", |         "repo": "default", | ||||||
|         "type": "github" |         "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", |   "root": "root", | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
|   src = fetchurl { |   src = fetchurl { | ||||||
|     url = "http://tools.mapillary.com/uploader/download/linux/${version}"; |     url = "http://tools.mapillary.com/uploader/download/linux/${version}"; | ||||||
|     name = "mapillary-uploader.AppImage"; |     name = "mapillary-uploader.AppImage"; | ||||||
|     sha256 = "sha256-hpWdfeuhYylO+SFD3BsKI0s/xtObCDd5OcuJ6i/aEuI="; |     sha256 = "sha256-Oyx7AIdA/2mwBaq7UzXOoyq/z2SU2sViMN40sY2RCQw="; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   appimageContents = appimageTools.extractType2 { |   appimageContents = appimageTools.extractType2 { | ||||||
|  | @ -23,6 +23,9 @@ in | ||||||
|       # Install desktop file |       # Install desktop file | ||||||
|       install -Dm644 ${appimageContents}/mapillary-desktop-uploader.desktop $out/share/applications/mapillary-uploader.desktop |       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 |       # Fix desktop file paths | ||||||
|       substituteInPlace $out/share/applications/mapillary-uploader.desktop \ |       substituteInPlace $out/share/applications/mapillary-uploader.desktop \ | ||||||
|         --replace 'Exec=AppRun' 'Exec=${pname}' |         --replace 'Exec=AppRun' 'Exec=${pname}' | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
|   flutter332, |   flutter332, | ||||||
|   fetchFromGitLab, |   fetchFromGitLab, | ||||||
|   pkg-config, |   pkg-config, | ||||||
|   wrapGAppsHook3, |   wrapGAppsHook, | ||||||
|   gtk3, |   gtk3, | ||||||
|   glib, |   glib, | ||||||
|   glib-networking, |   glib-networking, | ||||||
|  | @ -65,7 +65,7 @@ flutter332.buildFlutterApplication rec { | ||||||
| 
 | 
 | ||||||
|   nativeBuildInputs = [ |   nativeBuildInputs = [ | ||||||
|     pkg-config |     pkg-config | ||||||
|     wrapGAppsHook3 |     wrapGAppsHook | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   buildInputs = [ |   buildInputs = [ | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
|     ./user.nix |     ./user.nix | ||||||
|     ./flipperzero.nix |     ./flipperzero.nix | ||||||
|     ./i18n.nix |     ./i18n.nix | ||||||
|     ./impermanence.nix |  | ||||||
|     ./openssh.nix |     ./openssh.nix | ||||||
|     ./gnome.nix |     ./gnome.nix | ||||||
|     ./programs |     ./programs | ||||||
|  |  | ||||||
|  | @ -1,16 +1,8 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   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 = { |   options.gnome = { | ||||||
|     extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; |     extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; | ||||||
|     clockFormat = lib.mkOption { |     clockFormat = lib.mkOption { | ||||||
|  | @ -42,7 +34,7 @@ in { | ||||||
|       ]; |       ]; | ||||||
|       default = "blue"; |       default = "blue"; | ||||||
|     }; |     }; | ||||||
|     extraExtensions = lib.mkOption { |     extensions = lib.mkOption { | ||||||
|       type = lib.types.listOf lib.types.package; |       type = lib.types.listOf lib.types.package; | ||||||
|       default = []; |       default = []; | ||||||
|       description = "The set of extensions to install and enable in the user environment."; |       description = "The set of extensions to install and enable in the user environment."; | ||||||
|  | @ -68,80 +60,16 @@ in { | ||||||
|       })); |       })); | ||||||
|       default = {}; |       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 = { |   config = { | ||||||
|     home.packages = extensions; |     home.packages = config.gnome.extensions; | ||||||
|     dconf = { |     dconf = { | ||||||
|       settings = lib.mkMerge [ |       settings = lib.mkMerge [ | ||||||
|         { |         { | ||||||
|           "org/gnome/shell" = { |           "org/gnome/shell" = { | ||||||
|             disable-user-extensions = false; # enables user extensions |             disable-user-extensions = false; # enables user extensions | ||||||
|             enabled-extensions = builtins.map (extension: extension.extensionUuid) extensions; |             enabled-extensions = builtins.map (extension: extension.extensionUuid) config.gnome.extensions; | ||||||
|           }; |           }; | ||||||
| 
 | 
 | ||||||
|           "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; |           "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; | ||||||
|  | @ -149,23 +77,7 @@ in { | ||||||
|           "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; |           "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; | ||||||
|           "org/gnome/desktop/interface".accent-color = config.gnome.accentColor; |           "org/gnome/desktop/interface".accent-color = config.gnome.accentColor; | ||||||
|           "org/gnome/desktop/interface".clock-format = config.gnome.clockFormat; |           "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 ( |           lib.mkMerge ( | ||||||
|             builtins.map (value: let |             builtins.map (value: let | ||||||
|  | @ -188,15 +100,6 @@ in { | ||||||
|             ) |             ) | ||||||
|           ) |           ) | ||||||
|         ) |         ) | ||||||
| 
 |  | ||||||
|         # 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; |  | ||||||
|         }) |  | ||||||
|       ]; |       ]; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | @ -1,35 +0,0 @@ | ||||||
| { |  | ||||||
|   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 config.impermanence.enable { |       (lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           files = lib.lists.flatten ( |           files = lib.lists.flatten ( | ||||||
|             builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys |             builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.bitwarden = { |   options.programs.bitwarden = { | ||||||
|  | @ -11,11 +12,11 @@ | ||||||
|   config = lib.mkIf config.programs.bitwarden.enable (lib.mkMerge [ |   config = lib.mkIf config.programs.bitwarden.enable (lib.mkMerge [ | ||||||
|     { |     { | ||||||
|       home.packages = with pkgs; [ |       home.packages = with pkgs; [ | ||||||
|         bitwarden-desktop |         bitwarden | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/Bitwarden" |             "${config.xdg.configHome}/Bitwarden" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.bruno = { |   options.programs.bruno = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/bruno/" |             "${config.xdg.configHome}/bruno/" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.calibre = { |   options.programs.calibre = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/calibre" |             "${config.xdg.configHome}/calibre" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.davinci-resolve = { |   options.programs.davinci-resolve = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.dataHome}/DaVinciResolve" |             "${config.xdg.dataHome}/DaVinciResolve" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.dbeaver-bin = { |   options.programs.dbeaver-bin = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.dataHome}/DBeaverData/" |             "${config.xdg.dataHome}/DBeaverData/" | ||||||
|  |  | ||||||
|  | @ -12,13 +12,11 @@ | ||||||
|     ./obsidian.nix |     ./obsidian.nix | ||||||
|     ./prostudiomasters.nix |     ./prostudiomasters.nix | ||||||
|     ./idea.nix |     ./idea.nix | ||||||
|     ./kdenlive.nix |  | ||||||
|     ./krita.nix |     ./krita.nix | ||||||
|     ./protonvpn.nix |     ./protonvpn.nix | ||||||
|     ./calibre.nix |     ./calibre.nix | ||||||
|     ./bruno.nix |     ./bruno.nix | ||||||
|     ./dbeaver.nix |     ./dbeaver.nix | ||||||
|     ./dungeon-draft.nix |  | ||||||
|     ./steam.nix |     ./steam.nix | ||||||
|     ./vscode |     ./vscode | ||||||
|     ./ungoogled-chromium.nix |     ./ungoogled-chromium.nix | ||||||
|  | @ -26,7 +24,6 @@ | ||||||
|     ./mapillary-uploader.nix |     ./mapillary-uploader.nix | ||||||
|     ./inkscape.nix |     ./inkscape.nix | ||||||
|     ./gimp.nix |     ./gimp.nix | ||||||
|     ./guild-wars-2.nix |  | ||||||
|     ./proxmark3.nix |     ./proxmark3.nix | ||||||
|     ./freecad.nix |     ./freecad.nix | ||||||
|     ./onionshare.nix |     ./onionshare.nix | ||||||
|  | @ -36,14 +33,11 @@ | ||||||
|     ./qflipper.nix |     ./qflipper.nix | ||||||
|     ./openvpn.nix |     ./openvpn.nix | ||||||
|     ./noisetorch.nix |     ./noisetorch.nix | ||||||
|     ./olympus.nix |  | ||||||
|     ./openrgb.nix |     ./openrgb.nix | ||||||
|     ./via.nix |     ./via.nix | ||||||
|     ./vortex.nix |  | ||||||
|     ./davinci-resolve.nix |     ./davinci-resolve.nix | ||||||
|     ./gdx-liftoff.nix |     ./gdx-liftoff.nix | ||||||
|     ./tor-browser.nix |     ./tor-browser.nix | ||||||
|     ./polycule.nix |     ./polycule.nix | ||||||
|     ./vmware-workstation.nix |  | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.discord = { |   options.programs.discord = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/discord/" |             "${config.xdg.configHome}/discord/" | ||||||
|  |  | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| { |  | ||||||
|   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,6 +1,7 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: let | }: let | ||||||
|   buildProfilePersistence = profile: { |   buildProfilePersistence = profile: { | ||||||
|  | @ -25,7 +26,7 @@ | ||||||
|     allowOther = true; |     allowOther = true; | ||||||
|   }; |   }; | ||||||
| in { | in { | ||||||
|   config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) { |   config = lib.mkIf (config.programs.firefox.enable && osConfig.host.impermanence.enable) { | ||||||
|     home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( |     home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( | ||||||
|       ( |       ( | ||||||
|         lib.attrsets.mapAttrsToList |         lib.attrsets.mapAttrsToList | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.freecad = { |   options.programs.freecad = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/FreeCAD" |             "${config.xdg.configHome}/FreeCAD" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.gdx-liftoff = { |   options.programs.gdx-liftoff = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.gimp = { |   options.programs.gimp = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/GIMP" |             "${config.xdg.configHome}/GIMP" | ||||||
|  |  | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| { |  | ||||||
|   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,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.jetbrains.idea-community = { |   options.programs.jetbrains.idea-community = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             # configuration |             # configuration | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.inkscape = { |   options.programs.inkscape = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/inkscape" |             "${config.xdg.configHome}/inkscape" | ||||||
|  |  | ||||||
|  | @ -1,36 +0,0 @@ | ||||||
| { |  | ||||||
|   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,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.krita = { |   options.programs.krita = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/kritarc" |             "${config.xdg.configHome}/kritarc" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.libreoffice = { |   options.programs.libreoffice = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/libreoffice" |             "${config.xdg.configHome}/libreoffice" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.makemkv = { |   options.programs.makemkv = { | ||||||
|  | @ -29,7 +30,7 @@ | ||||||
|       home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path; |       home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             ".MakeMKV" |             ".MakeMKV" | ||||||
|  |  | ||||||
|  | @ -11,20 +11,7 @@ in { | ||||||
|     enable = mkEnableOption "Mapillary Desktop Uploader"; |     enable = mkEnableOption "Mapillary Desktop Uploader"; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = mkIf cfg.enable (mkMerge [ |   config = mkIf cfg.enable { | ||||||
|     { |  | ||||||
|     home.packages = [pkgs.mapillary-uploader]; |     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,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.mfoc = { |   options.programs.mfoc = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.noisetorch = { |   options.programs.noisetorch = { | ||||||
|  |  | ||||||
|  | @ -1,17 +1,13 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ |   config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         # TODO: map impermanence for obs | ||||||
|           directories = [ |  | ||||||
|             "${config.xdg.configHome}/obs-studio" |  | ||||||
|           ]; |  | ||||||
|           allowOther = true; |  | ||||||
|         }; |  | ||||||
|       } |       } | ||||||
|     ) |     ) | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|  | @ -1,11 +1,12 @@ | ||||||
| { | { | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [ |   config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [ | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/obsidian" |             "${config.xdg.configHome}/obsidian" | ||||||
|  |  | ||||||
|  | @ -1,36 +0,0 @@ | ||||||
| { |  | ||||||
|   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,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.onionshare = { |   options.programs.onionshare = { | ||||||
|  |  | ||||||
|  | @ -2,27 +2,16 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.openrgb = { |   options.programs.openrgb = { | ||||||
|     enable = lib.mkEnableOption "enable openrgb"; |     enable = lib.mkEnableOption "enable openrgb"; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = lib.mkIf config.programs.openrgb.enable (lib.mkMerge [ |   config = lib.mkIf config.programs.openrgb.enable { | ||||||
|     { |  | ||||||
|     home.packages = with pkgs; [ |     home.packages = with pkgs; [ | ||||||
|       openrgb |       openrgb | ||||||
|     ]; |     ]; | ||||||
|     } |  | ||||||
|     ( |  | ||||||
|       lib.mkIf config.impermanence.enable { |  | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |  | ||||||
|           directories = [ |  | ||||||
|             "${config.xdg.configHome}/OpenRGB" |  | ||||||
|           ]; |  | ||||||
|           allowOther = true; |  | ||||||
|   }; |   }; | ||||||
|       } |  | ||||||
|     ) |  | ||||||
|   ]); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.openvpn = { |   options.programs.openvpn = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.pdfarranger = { |   options.programs.pdfarranger = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.picard = { |   options.programs.picard = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/MusicBrainz" |             "${config.xdg.configHome}/MusicBrainz" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.piper = { |   options.programs.piper = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.polycule = { |   options.programs.polycule = { | ||||||
|  | @ -16,7 +17,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           # TODO: check that these are actually the correct folders |           # TODO: check that these are actually the correct folders | ||||||
|           # directories = [ |           # directories = [ | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.prostudiomasters = { |   options.programs.prostudiomasters = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/ProStudioMasters" |             "${config.xdg.configHome}/ProStudioMasters" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.protonvpn-gui = { |   options.programs.protonvpn-gui = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/protonvpn" |             "${config.xdg.configHome}/protonvpn" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.proxmark3 = { |   options.programs.proxmark3 = { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.qbittorrent = { |   options.programs.qbittorrent = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/qBittorrent" |             "${config.xdg.configHome}/qBittorrent" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.qflipper = { |   options.programs.qflipper = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/qFlipper" |             "${config.xdg.configHome}/qFlipper" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.signal-desktop-bin = { |   options.programs.signal-desktop-bin = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/Signal" |             "${config.xdg.configHome}/Signal" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.steam = { |   options.programs.steam = { | ||||||
|  | @ -17,7 +18,7 @@ | ||||||
|         ]; |         ]; | ||||||
|       } |       } | ||||||
|       ( |       ( | ||||||
|         lib.mkIf config.impermanence.enable { |         lib.mkIf osConfig.host.impermanence.enable { | ||||||
|           home.persistence."/persist${config.home.homeDirectory}" = { |           home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|             directories = [ |             directories = [ | ||||||
|               { |               { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.tor-browser = { |   options.programs.tor-browser = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.dataHome}/torbrowser" |             "${config.xdg.dataHome}/torbrowser" | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.ungoogled-chromium = { |   options.programs.ungoogled-chromium = { | ||||||
|  | @ -15,7 +16,7 @@ | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|     ( |     ( | ||||||
|       lib.mkIf config.impermanence.enable { |       lib.mkIf osConfig.host.impermanence.enable { | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |         home.persistence."/persist${config.home.homeDirectory}" = { | ||||||
|           directories = [ |           directories = [ | ||||||
|             "${config.xdg.configHome}/chromium" |             "${config.xdg.configHome}/chromium" | ||||||
|  |  | ||||||
|  | @ -2,28 +2,16 @@ | ||||||
|   lib, |   lib, | ||||||
|   pkgs, |   pkgs, | ||||||
|   config, |   config, | ||||||
|  |   osConfig, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.programs.via = { |   options.programs.via = { | ||||||
|     enable = lib.mkEnableOption "enable via"; |     enable = lib.mkEnableOption "enable via"; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   config = lib.mkIf config.programs.via.enable (lib.mkMerge [ |   config = lib.mkIf config.programs.via.enable { | ||||||
|     { |  | ||||||
|     home.packages = with pkgs; [ |     home.packages = with pkgs; [ | ||||||
|       via |       via | ||||||
|     ]; |     ]; | ||||||
|     } |  | ||||||
|     ( |  | ||||||
|       lib.mkIf config.impermanence.enable { |  | ||||||
|         home.persistence."/persist${config.home.homeDirectory}" = { |  | ||||||
|           directories = [ |  | ||||||
|             "${config.xdg.configHome}/via" |  | ||||||
|             "${config.xdg.dataHome}/via" |  | ||||||
|           ]; |  | ||||||
|           allowOther = true; |  | ||||||
|   }; |   }; | ||||||
|       } |  | ||||||
|     ) |  | ||||||
|   ]); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| { |  | ||||||
|   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; |  | ||||||
|           }; |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     ] |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| { |  | ||||||
|   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,7 +16,6 @@ | ||||||
|     ./go.nix |     ./go.nix | ||||||
|     ./evenBetterToml.nix |     ./evenBetterToml.nix | ||||||
|     ./openRemoteSsh.nix |     ./openRemoteSsh.nix | ||||||
|     ./rustAnalyzer.nix |  | ||||||
|     ./astroVscode.nix |     ./astroVscode.nix | ||||||
|     ./vscodeMdx.nix |     ./vscodeMdx.nix | ||||||
|     ./claudeDev.nix |     ./claudeDev.nix | ||||||
|  | @ -24,6 +23,5 @@ | ||||||
|     ./vitest.nix |     ./vitest.nix | ||||||
|     ./direnv.nix |     ./direnv.nix | ||||||
|     ./conventionalCommits.nix |     ./conventionalCommits.nix | ||||||
|     ./openDyslexicFont.nix |  | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,49 +0,0 @@ | ||||||
| { |  | ||||||
|   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; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| { |  | ||||||
|   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 |  | ||||||
|         ]; |  | ||||||
|       }; |  | ||||||
|     })); |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,24 +0,0 @@ | ||||||
| { |  | ||||||
|   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/private/actual"; |   dataDirectory = "/var/lib/actual/"; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,8 +1,26 @@ | ||||||
| { | { | ||||||
|  |   lib, | ||||||
|  |   config, | ||||||
|  |   ... | ||||||
|  | }: let | ||||||
|  |   const = import ./const.nix; | ||||||
|  |   dataDirectory = const.dataDirectory; | ||||||
|  | in { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./actual.nix |  | ||||||
|     ./proxy.nix |     ./proxy.nix | ||||||
|     ./fail2ban.nix |     ./fail2ban.nix | ||||||
|     ./impermanence.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,22 +6,11 @@ | ||||||
|   const = import ./const.nix; |   const = import ./const.nix; | ||||||
|   dataDirectory = const.dataDirectory; |   dataDirectory = const.dataDirectory; | ||||||
| in { | in { | ||||||
|   options.services.actual = { |   config = lib.mkIf (config.services.actual.enable && config.host.impermanence.enable) { | ||||||
|     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 = [ |     assertions = [ | ||||||
|       { |       { | ||||||
|         assertion = config.services.actual.settings.dataDir == dataDirectory; |         assertion = config.services.actual.settings.ACTUAL_DATA_DIR == dataDirectory; | ||||||
|         message = "actual data location does not match persistence\nconfig directory: ${config.services.actual.settings.dataDir}\npersistence directory: ${dataDirectory}"; |         message = "actual data location does not match persistence"; | ||||||
|       } |  | ||||||
|       { |  | ||||||
|         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" = { |     environment.persistence."/persist/system/root" = { | ||||||
|  |  | ||||||
|  | @ -4,30 +4,17 @@ | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.services.actual = { |   options.services.actual = { | ||||||
|     domain = lib.mkOption { |     subdomain = lib.mkOption { | ||||||
|       type = lib.types.str; |       type = lib.types.str; | ||||||
|       description = "domain that actual will be hosted at"; |       default = "actual"; | ||||||
|       default = "actual.arpa"; |       description = "subdomain of base domain that actual will be hosted at"; | ||||||
|     }; |  | ||||||
|     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.reverseProxy.enable { |   config = lib.mkIf (config.services.actual.enable && config.host.reverse_proxy.enable) { | ||||||
|     services.reverseProxy.services.actual = { |     host = { | ||||||
|  |       reverse_proxy.subdomains.${config.services.actual.subdomain} = { | ||||||
|         target = "http://localhost:${toString config.services.actual.settings.port}"; |         target = "http://localhost:${toString config.services.actual.settings.port}"; | ||||||
|       domain = config.services.actual.domain; |  | ||||||
|       extraDomains = config.services.actual.extraDomains; |  | ||||||
| 
 |  | ||||||
|       settings = { |  | ||||||
|         forwardHeaders.enable = true; |  | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| {...}: { | {...}: { | ||||||
|   imports = [ |   imports = [ | ||||||
|  |     ./proxy.nix | ||||||
|     ./impermanence.nix |     ./impermanence.nix | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,14 +5,7 @@ | ||||||
| }: let | }: let | ||||||
|   bazarr_data_directory = "/var/lib/bazarr"; |   bazarr_data_directory = "/var/lib/bazarr"; | ||||||
| in { | in { | ||||||
|   options.services.bazarr = { |   config = lib.mkIf (config.services.bazarr.enable && config.host.impermanence.enable) { | ||||||
|     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 = [ |     assertions = [ | ||||||
|       { |       { | ||||||
|         assertion = config.services.bazarr.dataDir == bazarr_data_directory; |         assertion = config.services.bazarr.dataDir == bazarr_data_directory; | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								modules/nixos-modules/server/bazarr/proxy.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								modules/nixos-modules/server/bazarr/proxy.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | { | ||||||
|  |   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; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | @ -1,193 +0,0 @@ | ||||||
| { |  | ||||||
|   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]; |  | ||||||
|       }) |  | ||||||
|     ]; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| {...}: { |  | ||||||
|   imports = [ |  | ||||||
|     ./crab-hole.nix |  | ||||||
|     ./impermanence.nix |  | ||||||
|   ]; |  | ||||||
| } |  | ||||||
|  | @ -1,33 +0,0 @@ | ||||||
| { |  | ||||||
|   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,23 +1,20 @@ | ||||||
| {...}: { | {...}: { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./reverseProxy |     ./reverse_proxy.nix | ||||||
|     ./fail2ban |     ./fail2ban.nix | ||||||
|     ./postgres |     ./postgres.nix | ||||||
|     ./network_storage |     ./network_storage | ||||||
|  |     ./podman.nix | ||||||
| 
 | 
 | ||||||
|     ./actual |     ./actual | ||||||
|     ./bazarr |     ./bazarr | ||||||
|     ./crab-hole |  | ||||||
|     ./flaresolverr |  | ||||||
|     ./forgejo |     ./forgejo | ||||||
|     ./home-assistant |     ./home-assistant | ||||||
|     ./immich |     ./immich | ||||||
|     ./jackett |  | ||||||
|     ./jellyfin |     ./jellyfin | ||||||
|     ./lidarr |  | ||||||
|     ./panoramax |     ./panoramax | ||||||
|     ./paperless |     ./paperless | ||||||
|     ./qbittorent |     ./qbittorent.nix | ||||||
|     ./radarr |     ./radarr | ||||||
|     ./searx |     ./searx | ||||||
|     ./sonarr |     ./sonarr | ||||||
|  |  | ||||||
							
								
								
									
										74
									
								
								modules/nixos-modules/server/fail2ban.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								modules/nixos-modules/server/fail2ban.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | { | ||||||
|  |   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"; | ||||||
|  |           } | ||||||
|  |         ]; | ||||||
|  |       }; | ||||||
|  |     }) | ||||||
|  |   ]); | ||||||
|  | } | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| {...}: { |  | ||||||
|   imports = [ |  | ||||||
|     ./fail2ban.nix |  | ||||||
|     ./impermanence.nix |  | ||||||
|   ]; |  | ||||||
| } |  | ||||||
|  | @ -1,51 +0,0 @@ | ||||||
| { |  | ||||||
|   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 {}; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,34 +0,0 @@ | ||||||
| { |  | ||||||
|   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"; |  | ||||||
|         } |  | ||||||
|       ]; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| {...}: { |  | ||||||
|   imports = [ |  | ||||||
|     ./impermanence.nix |  | ||||||
|   ]; |  | ||||||
| } |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| { |  | ||||||
|   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,31 +2,40 @@ | ||||||
|   lib, |   lib, | ||||||
|   config, |   config, | ||||||
|   ... |   ... | ||||||
| }: let | }: { | ||||||
|   usingPostgres = config.services.forgejo.database.type == "postgres"; |   config = lib.mkIf config.services.forgejo.enable ( | ||||||
| in { |     lib.mkMerge [ | ||||||
|   config = lib.mkIf config.services.forgejo.enable { |       { | ||||||
|  |         host = { | ||||||
|  |           postgres = { | ||||||
|  |             enable = true; | ||||||
|  |           }; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|         assertions = [ |         assertions = [ | ||||||
|           { |           { | ||||||
|         assertion = !usingPostgres || config.services.postgresql.enable; |             assertion = config.services.forgejo.settings.database.DB_TYPE == "postgres"; | ||||||
|         message = "PostgreSQL must be enabled when Forgejo database type is postgres"; |             message = "Forgejo database type must be 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)}"; |  | ||||||
|           } |           } | ||||||
|         ]; |         ]; | ||||||
| 
 |       } | ||||||
|     services.forgejo.database.createDatabase = lib.mkDefault usingPostgres; |       (lib.mkIf config.host.postgres.enable { | ||||||
| 
 |         host = { | ||||||
|     systemd.services.forgejo = lib.mkIf usingPostgres { |           postgres = { | ||||||
|       requires = [ |             extraUsers = { | ||||||
|         config.systemd.services.postgresql.name |               forgejo = { | ||||||
|       ]; |                 isClient = true; | ||||||
|  |                 createUser = true; | ||||||
|               }; |               }; | ||||||
|             }; |             }; | ||||||
|  |             extraDatabases = { | ||||||
|  |               forgejo = { | ||||||
|  |                 name = "forgejo"; | ||||||
|  |               }; | ||||||
|  |             }; | ||||||
|  |           }; | ||||||
|  |         }; | ||||||
|  |       }) | ||||||
|  |     ] | ||||||
|  |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,53 @@ | ||||||
| { | { | ||||||
|  |   lib, | ||||||
|  |   config, | ||||||
|  |   ... | ||||||
|  | }: let | ||||||
|  |   const = import ./const.nix; | ||||||
|  |   httpPort = const.httpPort; | ||||||
|  |   sshPort = const.sshPort; | ||||||
|  |   db_user = "forgejo"; | ||||||
|  | in { | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./forgejo.nix |  | ||||||
|     ./proxy.nix |     ./proxy.nix | ||||||
|     ./database.nix |     ./database.nix | ||||||
|     ./fail2ban.nix |     ./fail2ban.nix | ||||||
|     ./impermanence.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,16 +4,7 @@ | ||||||
|   pkgs, |   pkgs, | ||||||
|   ... |   ... | ||||||
| }: { | }: { | ||||||
|   options.services.forgejo = { |   config = lib.mkIf (config.services.forgejo.enable && config.services.fail2ban.enable) { | ||||||
|     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 = { |     environment.etc = { | ||||||
|       "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( |       "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( | ||||||
|         pkgs.lib.mkDefault (pkgs.lib.mkAfter '' |         pkgs.lib.mkDefault (pkgs.lib.mkAfter '' | ||||||
|  |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| { |  | ||||||
|   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,14 +5,7 @@ | ||||||
| }: let | }: let | ||||||
|   stateDir = "/var/lib/forgejo"; |   stateDir = "/var/lib/forgejo"; | ||||||
| in { | in { | ||||||
|   options.services.forgejo = { |   config = lib.mkIf (config.services.forgejo.enable && config.host.impermanence.enable) { | ||||||
|     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 = [ |     assertions = [ | ||||||
|       { |       { | ||||||
|         assertion = config.services.forgejo.stateDir == stateDir; |         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