diff --git a/.hooks/post-merge b/.hooks/post-merge new file mode 100755 index 0000000..11fb20c --- /dev/null +++ b/.hooks/post-merge @@ -0,0 +1,18 @@ +#!/usr/bin/env nix-shell +#! nix-shell -i bash ../shell.nix + +# Get current branch name +current_branch=$(git branch --show-current) + +# Only restore stash if we're on main branch and a merge just completed +if [ "$current_branch" = "main" ]; then + # Check if there are any stashes to restore + if git stash list | grep -q "stash@"; then + echo "Post-merge: restoring stashed changes on main branch" + git stash pop -q + else + echo "Post-merge: no stash to restore on main branch" + fi +else + echo "Post-merge: no action needed on branch '$current_branch'" +fi diff --git a/.hooks/pre-merge-commit b/.hooks/pre-merge-commit new file mode 100755 index 0000000..9edaf92 --- /dev/null +++ b/.hooks/pre-merge-commit @@ -0,0 +1,37 @@ +#!/usr/bin/env nix-shell +#! nix-shell -i bash ../shell.nix + +# Get the target branch (the branch being merged into) +target_branch="" + +# Check if we're in the middle of a merge +if [ -f .git/MERGE_HEAD ]; then + # We're in a merge, check if the current branch is main + current_branch=$(git branch --show-current) + if [ "$current_branch" = "main" ]; then + target_branch="main" + fi +fi + +# If we're merging into main, run nix flake check +if [ "$target_branch" = "main" ]; then + echo "Merging into main branch - running nix flake check..." + + echo "stashing all uncommitted changes" + git stash -q --keep-index + + 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 diff --git a/README.md b/README.md index acaa6e7..f8c7ecf 100644 --- a/README.md +++ b/README.md @@ -46,36 +46,56 @@ nix multi user, multi system, configuration with `sops` secret management, `home # Tasks: +## Chores: +- [ ] test out crab hole service +- [ ] learn how to use actual + ## Tech Debt -- monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) -- nfs export should be backed by the same values for server and client -## New Features -- crab-hole -- figure out why syncthing and jellyfins permissions don't propagate downwards -- figure out steam vr things? -- auto turn off on power loss - nut -- zfs email after scrubbing # TODO: test this -- SMART test with email results -- samba mounts -- offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) -- Create Tor guard/relay server -- migrate away from flakes and move to npins -- whisper -- zfs encryption FIDO2 2fa (look into shavee) -- Secure Boot - https://github.com/nix-community/lanzaboote -- rotate sops encryption keys periodically (and somehow sync between devices?) -- wake on LAN for updates -- remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html -- ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix -- panoramax instance -- mastodon instance -- rework the reverse_proxy.nix file so that it is a normally named service. Then also change it so that we can hook into it with both a base domain and a subdomain to make migrating to vpn accessible services easier -- move searx, home-assistant, actual, jellyfin, paperless, and immich to only be accessible via vpn -- make radarr, sonarr, and bazarr accessible over vpn -- create some sort of service that allows uploading files to jellyfin - - auto sort files into where they should go with some combination of filebot cli and picard cli -- graphana accessible though tailscale -- fix panoramax package -- actual instance -- intergrade radarr, sonarr, and bazarr -- claude code MCP servers should bundle node with them so they work in all environments +- [ ] monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) +- [ ] migrate away from flakes and move to npins +- [ ] 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 + +## Broken things +- [ ] figure out steam vr things? +- [ ] whisper was having issues + +## Data Integrity +- [ ] zfs email after scrubbing # TODO: test this +- [ ] SMART test with email results +- [ ] zfs encryption FIDO2 2fa (look into shavee) +- [ ] rotate sops encryption keys periodically (and somehow sync between devices?) +- [ ] Secure Boot - https://github.com/nix-community/lanzaboote +- [ ] auto turn off on power loss - nut + +## Data Access +- [ ] nfs export should be backed by the same values for server and client +- [ ] samba mounts +- [ ] offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) +- [ ] figure out why syncthing and jellyfins permissions don't propagate downwards +- [ ] make radarr, sonarr, and bazarr accessible over vpn +- [ ] move searx, home-assistant, actual, jellyfin, paperless, and immich to only be accessible via vpn + +## Services +- [ ] vikunja service for project management +- [ ] Create Tor guard/relay server +- [ ] mastodon instance + +## 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 \ No newline at end of file diff --git a/configurations/home-manager/eve/gnomeconf.nix b/configurations/home-manager/eve/gnomeconf.nix index fbad391..7cd3863 100644 --- a/configurations/home-manager/eve/gnomeconf.nix +++ b/configurations/home-manager/eve/gnomeconf.nix @@ -1,12 +1,39 @@ -{pkgs, ...}: { +{ + osConfig, + lib, + ... +}: { config = { + gnome = lib.mkMerge [ + { + colorScheme = "prefer-dark"; + accentColor = "slate"; + clockFormat = "24h"; + nightLight = { + enable = true; + automatic = false; + fromTime = 12.0; + toTime = 11.999999999999; + temperature = 2700; + }; + extraWindowControls = true; + extensions = { + dash-to-panel = { + enable = true; + }; + }; + } + + (lib.mkIf (osConfig.networking.hostName == "horizon") { + displayScaling = 125; + experimentalFeatures = { + scaleMonitorFramebuffer = true; + }; + }) + ]; + dconf = { enable = true; - settings = { - "org/gnome/shell".enabled-extensions = [ - pkgs.gnomeExtensions.dash-to-panel.extensionUuid - ]; - }; }; }; } diff --git a/configurations/home-manager/eve/packages.nix b/configurations/home-manager/eve/packages.nix index f738fe2..73195c4 100644 --- a/configurations/home-manager/eve/packages.nix +++ b/configurations/home-manager/eve/packages.nix @@ -18,6 +18,7 @@ in { home.packages = lib.lists.optionals userConfig.isDesktopUser ( with pkgs; [ gnomeExtensions.dash-to-panel + claude-code ] ); @@ -61,6 +62,22 @@ in { piper.enable = hardware.piperMouse.enable; krita.enable = true; ungoogled-chromium.enable = true; + + inkscape.enable = true; + obsidian.enable = true; + obs-studio.enable = true; + kdenlive.enable = true; + tor-browser.enable = true; + olympus.enable = true; + libreoffice.enable = true; + + claude-code.enable = osConfig.host.ai.enable; + + # Windows applications that we need to figure out how to install + guild-wars-2.enable = false; + vortex.enable = false; + dungeon-draft.enable = false; + vmware-workstation.enable = true; }) ]; }; diff --git a/configurations/home-manager/leyla/dconf.nix b/configurations/home-manager/leyla/dconf.nix index ef75db6..9aa61f7 100644 --- a/configurations/home-manager/leyla/dconf.nix +++ b/configurations/home-manager/leyla/dconf.nix @@ -1,31 +1,43 @@ -{pkgs, ...}: { +{...}: { config = { gnome = { extraWindowControls = true; colorScheme = "prefer-dark"; clockFormat = "24h"; - extensions = [ - pkgs.gnomeExtensions.dash-to-dock - ]; + nightLight = { + enable = true; + automatic = false; + fromTime = 12.0; + toTime = 11.999999999999; + temperature = 2700; + }; + extensions = { + dash-to-dock = { + enable = true; + options = { + "dock-position" = "LEFT"; + "intellihide-mode" = "ALL_WINDOWS"; + "show-trash" = false; + "require-pressure-to-show" = false; + "show-mounts" = false; + }; + }; + }; hotkeys = { "Open Terminal" = { binding = "t"; command = "kgx"; }; + "Open Firefox" = { + binding = "f"; + command = "firefox"; + }; }; }; dconf = { enable = true; settings = { - "org/gnome/shell/extensions/dash-to-dock" = { - "dock-position" = "LEFT"; - "intellihide-mode" = "ALL_WINDOWS"; - "show-trash" = false; - "require-pressure-to-show" = false; - "show-mounts" = false; - }; - "org/gnome/shell" = { favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; # app-picker-layout = diff --git a/configurations/home-manager/leyla/default.nix b/configurations/home-manager/leyla/default.nix index 6d759c5..eba7f7b 100644 --- a/configurations/home-manager/leyla/default.nix +++ b/configurations/home-manager/leyla/default.nix @@ -87,7 +87,6 @@ # TODO: move this into a fonts module home.packages = with pkgs; [ aileron - nerd-fonts.open-dyslexic ]; fonts.fontconfig.enable = true; }; diff --git a/configurations/home-manager/leyla/impermanence.nix b/configurations/home-manager/leyla/impermanence.nix index 041bff8..ce81c81 100644 --- a/configurations/home-manager/leyla/impermanence.nix +++ b/configurations/home-manager/leyla/impermanence.nix @@ -1,10 +1,9 @@ { lib, config, - osConfig, ... }: { - config = lib.mkIf osConfig.host.impermanence.enable { + config = lib.mkIf (config.impermanence.enable) { home.persistence."/persist/home/leyla" = { directories = [ "desktop" diff --git a/configurations/home-manager/leyla/packages/vscode/default.nix b/configurations/home-manager/leyla/packages/vscode/default.nix index ba9e48a..fd72006 100644 --- a/configurations/home-manager/leyla/packages/vscode/default.nix +++ b/configurations/home-manager/leyla/packages/vscode/default.nix @@ -32,6 +32,7 @@ in { "javascript.updateImportsOnFileMove.enabled" = "always"; "editor.tabSize" = 2; "editor.insertSpaces" = false; + # "terminal.integrated.fontFamily" = "'Droid Sans Mono', 'monospace', monospace"; } ]; @@ -40,6 +41,7 @@ in { oneDark.enable = true; atomKeybindings.enable = true; openRemoteSsh.enable = true; + # openDyslexicFont.enable = false; # html development autoRenameTag.enable = true; diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index 9fbdee6..c2b8fc5 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -57,7 +57,6 @@ "ata-ST18000NT001-3NF101_ZVTEF27J" "ata-ST18000NE000-3G6101_ZVTJ7359" ] - # TODO: this needs to be configured manually [ "ata-ST4000NE001-2MA101_WS2275P3" "ata-ST4000NE001-2MA101_WS227B9F" @@ -343,6 +342,20 @@ openFirewall = true; }; + crab-hole = { + enable = true; + port = 8085; + openFirewall = true; + show_doc = true; + downstreams = { + loopback = { + enable = true; + openFirewall = true; + }; + }; + upstreams.cloudFlare.enable = true; + }; + qbittorrent = { enable = true; mediaDir = "/srv/qbittorent"; @@ -350,21 +363,28 @@ webuiPort = 8084; }; - filebot-cleanup = { - enable = true; - licenseFile = "/srv/jellyfin/filebot_license.psm"; - }; - sonarr = { - enable = false; + enable = true; openFirewall = true; }; radarr = { - enable = false; + enable = true; openFirewall = true; }; bazarr = { - enable = false; + enable = true; + openFirewall = true; + }; + lidarr = { + enable = true; + openFirewall = true; + }; + jackett = { + enable = true; + openFirewall = true; + }; + flaresolverr = { + enable = true; openFirewall = true; }; }; diff --git a/configurations/nixos/defiant/default.nix b/configurations/nixos/defiant/default.nix index 05975a1..3013946 100644 --- a/configurations/nixos/defiant/default.nix +++ b/configurations/nixos/defiant/default.nix @@ -4,6 +4,5 @@ ./hardware-configuration.nix ./configuration.nix ./packages.nix - ./filebot.nix ]; } diff --git a/configurations/nixos/defiant/filebot.nix b/configurations/nixos/defiant/filebot.nix deleted file mode 100644 index aaf247d..0000000 --- a/configurations/nixos/defiant/filebot.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -with lib; let - cfg = config.services.filebot-cleanup; -in { - options.services.filebot-cleanup = { - enable = mkEnableOption "Filebot cleanup service"; - - licenseFile = mkOption { - type = types.nullOr types.path; - default = null; - description = "Path to the Filebot license file"; - }; - - cleanupDirectory = mkOption { - type = types.str; - default = "/srv/jellyfin/filebot_cleanup"; - description = "Directory where cleaned up media files are stored"; - }; - }; - - config = mkIf cfg.enable { - users.groups.filebot_cleanup = {}; - users.users.filebot_cleanup = { - isSystemUser = true; - group = "filebot_cleanup"; - extraGroups = ["jellyfin_media"]; - home = cfg.cleanupDirectory; - createHome = true; - }; - - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "filebot" - ]; - - environment.systemPackages = with pkgs; [ - filebot - ]; - - systemd.services.filebot-cleanup = { - description = "Filebot media cleanup service"; - serviceConfig = { - Type = "simple"; - User = "filebot_cleanup"; - Group = "filebot_cleanup"; - ExecStart = pkgs.writeShellScript "filebot-cleanup" '' - ${optionalString (cfg.licenseFile != null) '' - ${pkgs.filebot}/bin/filebot --license "${cfg.licenseFile}" - ''} - ${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Movies/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate - ${pkgs.filebot}/bin/filebot -rename -r "/srv/jellyfin/media/Shows/" --output "${cfg.cleanupDirectory}/" --format "{jellyfin}" -non-strict --action duplicate - ''; - StandardOutput = "journal"; - StandardError = "journal"; - }; - wantedBy = ["multi-user.target"]; - }; - - environment.persistence = lib.mkIf config.host.impermanence.enable { - "/persist/system/jellyfin" = { - enable = true; - hideMounts = true; - files = [ - cfg.licenseFile - ]; - directories = [ - { - directory = cfg.cleanupDirectory; - user = "filebot_cleanup"; - group = "filebot_cleanup"; - mode = "1770"; - } - ]; - }; - }; - }; -} diff --git a/configurations/nixos/emergent/configuration.nix b/configurations/nixos/emergent/configuration.nix index bb671f7..fd27374 100644 --- a/configurations/nixos/emergent/configuration.nix +++ b/configurations/nixos/emergent/configuration.nix @@ -40,13 +40,15 @@ services.xserver.wacom.enable = true; # installed opentabletdriver - hardware.opentabletdriver.enable = true; + # hardware.opentabletdriver.enable = true; + hardware.keyboard.qmk.enable = true; # Enable the GNOME Desktop Environment. services.displayManager.gdm.enable = true; services.desktopManager.gnome.enable = true; host = { + ai.enable = true; users = { eve = { isDesktopUser = true; @@ -68,6 +70,9 @@ }; services.tailscale.enable = true; + # We were having weird build errors so this is disabled right now + # error: The option `devices.emergent.folders.eve_records.path' was accessed but has no value defined. Try setting the option + services.syncthing.enable = false; # Configure keymap in X11 # services.xserver.xkb.layout = "us"; diff --git a/configurations/nixos/emergent/hardware-configuration.nix b/configurations/nixos/emergent/hardware-configuration.nix index 4e13149..67149df 100644 --- a/configurations/nixos/emergent/hardware-configuration.nix +++ b/configurations/nixos/emergent/hardware-configuration.nix @@ -12,7 +12,7 @@ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod"]; + boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "wacom"]; boot.initrd.kernelModules = []; boot.kernelModules = []; boot.extraModulePackages = []; diff --git a/configurations/nixos/twilight/hardware-configuration.nix b/configurations/nixos/twilight/hardware-configuration.nix index 1389caf..94c83d6 100644 --- a/configurations/nixos/twilight/hardware-configuration.nix +++ b/configurations/nixos/twilight/hardware-configuration.nix @@ -18,12 +18,12 @@ fileSystems = { "/" = { - device = "/dev/disk/by-uuid/8be49c65-2b57-48f1-b74d-244d26061adb"; + device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part2"; fsType = "ext4"; }; "/boot" = { - device = "/dev/disk/by-uuid/3006-3867"; + device = "/dev/disk/by-id/ata-TOSHIBA_DT01ACA100_77D21HVNS-part1"; fsType = "vfat"; options = ["fmask=0022" "dmask=0022"]; }; diff --git a/flake.lock b/flake.lock index 9309105..bb7e3a6 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ ] }, "locked": { - "lastModified": 1758287904, - "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", + "lastModified": 1760701190, + "narHash": "sha256-y7UhnWlER8r776JsySqsbTUh2Txf7K30smfHlqdaIQw=", "owner": "nix-community", "repo": "disko", - "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", + "rev": "3a9450b26e69dcb6f8de6e2b07b3fc1c288d85f5", "type": "github" }, "original": { @@ -46,11 +46,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1759403080, - "narHash": "sha256-EteyL8KyG9R5xzqyOBzyag4n2cSemu61VFrl3opJSqE=", + "lastModified": 1760673822, + "narHash": "sha256-h+liPhhMw1yYvkDGLHzQJQShQs+yLjNgjfAyZX+sRrM=", "owner": "rycee", "repo": "nur-expressions", - "rev": "8af6dfcbcbf1115a4f5aeed77ff0db5d3c02caf0", + "rev": "5cca27f1bb30a26140d0cf60ab34daa45b4fa11f", "type": "gitlab" }, "original": { @@ -111,24 +111,6 @@ "type": "github" } }, - "flake-utils_3": { - "inputs": { - "systems": "systems_3" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "flakey-profile": { "locked": { "lastModified": 1712898590, @@ -151,11 +133,11 @@ ] }, "locked": { - "lastModified": 1759337100, - "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", + "lastModified": 1760662441, + "narHash": "sha256-mlDqR1Ntgs9uYYEAUR1IhamKBO0lxoNS4zGLzEZaY0A=", "owner": "nix-community", "repo": "home-manager", - "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", + "rev": "722792af097dff5790f1a66d271a47759f477755", "type": "github" }, "original": { @@ -182,11 +164,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1759624822, - "narHash": "sha256-cf40qfsfpxJU/BnQ9PEj027LdPINNSsJqm+C6Ug93BA=", - "rev": "57333a0e600c5e096a609410a2f1059b97194b1e", + "lastModified": 1755787066, + "narHash": "sha256-X2UwkUEban08GRSPXRr+kz8fckHqebr3P77qSvjoeOw=", + "rev": "ac9721a92e8138d29707824dbedb484c76948493", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/57333a0e600c5e096a609410a2f1059b97194b1e.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/ac9721a92e8138d29707824dbedb484c76948493.tar.gz?rev=ac9721a92e8138d29707824dbedb484c76948493" }, "original": { "type": "tarball", @@ -203,11 +185,11 @@ ] }, "locked": { - "lastModified": 1756511062, - "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", + "lastModified": 1759851320, + "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", "ref": "refs/heads/main", - "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", - "revCount": 162, + "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", + "revCount": 163, "type": "git", "url": "https://git.lix.systems/lix-project/nixos-module.git" }, @@ -245,11 +227,11 @@ ] }, "locked": { - "lastModified": 1758805352, - "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=", + "lastModified": 1760721282, + "narHash": "sha256-aAHphQbU9t/b2RRy2Eb8oMv+I08isXv2KUGFAFn7nCo=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c", + "rev": "c3211fcd0c56c11ff110d346d4487b18f7365168", "type": "github" }, "original": { @@ -281,17 +263,16 @@ }, "nix-vscode-extensions": { "inputs": { - "flake-utils": "flake-utils_3", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1759369908, - "narHash": "sha256-IIhaE6jAge64z+fIyi/8Vtu0JdTtapbp4CvwiuIkZ1E=", + "lastModified": 1760720017, + "narHash": "sha256-ALb+L8zaP6IJ3BigQJ+ih7NqmaptzL/CbkNkLbhmsGE=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "a66ad2141b1440a838ead278c6edfe8a4ce75e6c", + "rev": "b0897a5d1d5829eb67ca7168680873ee7a0d52b8", "type": "github" }, "original": { @@ -302,11 +283,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1759261527, - "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", + "lastModified": 1760106635, + "narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", + "rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", "type": "github" }, "original": { @@ -334,11 +315,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1759381078, - "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", + "lastModified": 1760524057, + "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", + "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", "type": "github" }, "original": { @@ -389,11 +370,11 @@ ] }, "locked": { - "lastModified": 1759188042, - "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", + "lastModified": 1760393368, + "narHash": "sha256-8mN3kqyqa2PKY0wwZ2UmMEYMcxvNTwLaOrrDsw6Qi4E=", "owner": "Mic92", "repo": "sops-nix", - "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", + "rev": "ab8d56e85b8be14cff9d93735951e30c3e86a437", "type": "github" }, "original": { @@ -431,21 +412,6 @@ "repo": "default", "type": "github" } - }, - "systems_3": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/modules/common-modules/pkgs/mapillary-uploader.nix b/modules/common-modules/pkgs/mapillary-uploader.nix index 7ce24f2..9ae2ea7 100644 --- a/modules/common-modules/pkgs/mapillary-uploader.nix +++ b/modules/common-modules/pkgs/mapillary-uploader.nix @@ -9,7 +9,7 @@ src = fetchurl { url = "http://tools.mapillary.com/uploader/download/linux/${version}"; name = "mapillary-uploader.AppImage"; - sha256 = "sha256-Oyx7AIdA/2mwBaq7UzXOoyq/z2SU2sViMN40sY2RCQw="; + sha256 = "sha256-OY3SiMHUyjwPDrPWfa+mFg2BHZrz6GG/9/D5sCP2Da8="; }; appimageContents = appimageTools.extractType2 { @@ -23,9 +23,6 @@ in # Install desktop file install -Dm644 ${appimageContents}/mapillary-desktop-uploader.desktop $out/share/applications/mapillary-uploader.desktop - # Install icon - install -Dm644 ${appimageContents}/usr/share/icons/hicolor/0x0/apps/mapillary-desktop-uploader.png $out/share/pixmaps/mapillary-uploader.png - # Fix desktop file paths substituteInPlace $out/share/applications/mapillary-uploader.desktop \ --replace 'Exec=AppRun' 'Exec=${pname}' diff --git a/modules/home-manager-modules/default.nix b/modules/home-manager-modules/default.nix index 4c085a5..29d3414 100644 --- a/modules/home-manager-modules/default.nix +++ b/modules/home-manager-modules/default.nix @@ -5,6 +5,7 @@ ./user.nix ./flipperzero.nix ./i18n.nix + ./impermanence.nix ./openssh.nix ./gnome.nix ./programs diff --git a/modules/home-manager-modules/gnome.nix b/modules/home-manager-modules/gnome.nix index 8c70cf6..ab56189 100644 --- a/modules/home-manager-modules/gnome.nix +++ b/modules/home-manager-modules/gnome.nix @@ -1,8 +1,16 @@ { lib, config, + pkgs, ... -}: { +}: let + enabledExtensions = + [] + ++ lib.optional config.gnome.extensions.dash-to-dock.enable pkgs.gnomeExtensions.dash-to-dock + ++ lib.optional config.gnome.extensions.dash-to-panel.enable pkgs.gnomeExtensions.dash-to-panel; + + extensions = config.gnome.extraExtensions ++ enabledExtensions; +in { options.gnome = { extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; clockFormat = lib.mkOption { @@ -34,7 +42,7 @@ ]; default = "blue"; }; - extensions = lib.mkOption { + extraExtensions = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; description = "The set of extensions to install and enable in the user environment."; @@ -60,16 +68,80 @@ })); default = {}; }; + displayScaling = lib.mkOption { + type = lib.types.nullOr (lib.types.enum [100 125 150 175 200]); + default = null; + description = "Display scaling percentage for GNOME"; + }; + experimentalFeatures = lib.mkOption { + type = lib.types.submodule { + options = { + scaleMonitorFramebuffer = lib.mkEnableOption "scale-monitor-framebuffer experimental feature"; + }; + }; + default = {}; + description = "GNOME experimental features to enable"; + }; + + nightLight = lib.mkOption { + type = lib.types.submodule { + options = { + enable = lib.mkEnableOption "night light (blue light filter)"; + automatic = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to automatically schedule night light based on sunset/sunrise"; + }; + fromTime = lib.mkOption { + type = lib.types.float; + default = 20.0; + description = "Start time for night light in 24-hour format (e.g., 20.0 for 8:00 PM)"; + }; + toTime = lib.mkOption { + type = lib.types.float; + default = 6.0; + description = "End time for night light in 24-hour format (e.g., 6.0 for 6:00 AM)"; + }; + temperature = lib.mkOption { + type = lib.types.int; + default = 4000; + description = "Color temperature for night light (1000-10000K, lower is warmer)"; + }; + }; + }; + default = {}; + description = "Night light configuration"; + }; + + extensions = { + dash-to-dock = { + enable = lib.mkEnableOption "Dash to Dock extension"; + options = lib.mkOption { + type = lib.types.nullOr lib.types.attrs; + default = null; + description = "Dash to Dock configuration options. If null, no custom configuration will be applied."; + }; + }; + + dash-to-panel = { + enable = lib.mkEnableOption "Dash to Panel extension"; + options = lib.mkOption { + type = lib.types.nullOr lib.types.attrs; + default = null; + description = "Dash to Panel configuration options. If null, no custom configuration will be applied."; + }; + }; + }; }; config = { - home.packages = config.gnome.extensions; + home.packages = extensions; dconf = { settings = lib.mkMerge [ { "org/gnome/shell" = { disable-user-extensions = false; # enables user extensions - enabled-extensions = builtins.map (extension: extension.extensionUuid) config.gnome.extensions; + enabled-extensions = builtins.map (extension: extension.extensionUuid) extensions; }; "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; @@ -77,7 +149,23 @@ "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; "org/gnome/desktop/interface".accent-color = config.gnome.accentColor; "org/gnome/desktop/interface".clock-format = config.gnome.clockFormat; + "org/gnome/desktop/interface".text-scaling-factor = lib.mkIf (config.gnome.displayScaling != null) (config.gnome.displayScaling / 100.0); + + "org/gnome/mutter".experimental-features = lib.mkIf (builtins.any (x: x) (builtins.attrValues config.gnome.experimentalFeatures)) ( + lib.optional config.gnome.experimentalFeatures.scaleMonitorFramebuffer "scale-monitor-framebuffer" + ); } + + # Night light configuration + (lib.mkIf config.gnome.nightLight.enable { + "org/gnome/settings-daemon/plugins/color" = { + night-light-enabled = true; + night-light-schedule-automatic = config.gnome.nightLight.automatic; + night-light-schedule-from = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.fromTime; + night-light-schedule-to = lib.mkIf (!config.gnome.nightLight.automatic) config.gnome.nightLight.toTime; + night-light-temperature = config.gnome.nightLight.temperature; + }; + }) ( lib.mkMerge ( builtins.map (value: let @@ -100,6 +188,15 @@ ) ) ) + + # Extension configurations + (lib.mkIf (config.gnome.extensions.dash-to-dock.enable && config.gnome.extensions.dash-to-dock.options != null) { + "org/gnome/shell/extensions/dash-to-dock" = config.gnome.extensions.dash-to-dock.options; + }) + + (lib.mkIf (config.gnome.extensions.dash-to-panel.enable && config.gnome.extensions.dash-to-panel.options != null) { + "org/gnome/shell/extensions/dash-to-panel" = config.gnome.extensions.dash-to-panel.options; + }) ]; }; }; diff --git a/modules/home-manager-modules/impermanence.nix b/modules/home-manager-modules/impermanence.nix new file mode 100644 index 0000000..dc9eae9 --- /dev/null +++ b/modules/home-manager-modules/impermanence.nix @@ -0,0 +1,31 @@ +{ + config, + lib, + osConfig, + ... +}: let + cfg = config.impermanence; +in { + options.impermanence = { + enable = lib.mkEnableOption "impermanence for home directory"; + }; + + config = lib.mkMerge [ + (lib.mkIf config.impermanence.enable { + assertions = [ + { + assertion = osConfig.impermanence.enable; + message = "impermanence can not be enabled for a user when it is not enabled for a configuration"; + } + ]; + }) + (lib.mkIf osConfig.host.impermanence.enable { + # If impermanence is not enabled for this user but system impermanence is enabled, + # persist the entire home directory as fallback + home.persistence."/persist/home/${config.home.username}" = lib.mkIf (!cfg.enable) { + directories = ["."]; + allowOther = true; + }; + }) + ]; +} diff --git a/modules/home-manager-modules/openssh.nix b/modules/home-manager-modules/openssh.nix index 9d77d10..afc98dd 100644 --- a/modules/home-manager-modules/openssh.nix +++ b/modules/home-manager-modules/openssh.nix @@ -95,7 +95,7 @@ ); } ) - (lib.mkIf osConfig.host.impermanence.enable { + (lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { files = lib.lists.flatten ( builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys diff --git a/modules/home-manager-modules/programs/bitwarden.nix b/modules/home-manager-modules/programs/bitwarden.nix index b9b91c4..5c14068 100644 --- a/modules/home-manager-modules/programs/bitwarden.nix +++ b/modules/home-manager-modules/programs/bitwarden.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.bitwarden = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/Bitwarden" diff --git a/modules/home-manager-modules/programs/bruno.nix b/modules/home-manager-modules/programs/bruno.nix index 00b248f..8ad5e63 100644 --- a/modules/home-manager-modules/programs/bruno.nix +++ b/modules/home-manager-modules/programs/bruno.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.bruno = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/bruno/" diff --git a/modules/home-manager-modules/programs/calibre.nix b/modules/home-manager-modules/programs/calibre.nix index 9e5f34e..dbe6e2b 100644 --- a/modules/home-manager-modules/programs/calibre.nix +++ b/modules/home-manager-modules/programs/calibre.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.calibre = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/calibre" diff --git a/modules/home-manager-modules/programs/davinci-resolve.nix b/modules/home-manager-modules/programs/davinci-resolve.nix index 00ba525..6c4526f 100644 --- a/modules/home-manager-modules/programs/davinci-resolve.nix +++ b/modules/home-manager-modules/programs/davinci-resolve.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.davinci-resolve = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.dataHome}/DaVinciResolve" diff --git a/modules/home-manager-modules/programs/dbeaver.nix b/modules/home-manager-modules/programs/dbeaver.nix index a962459..8b6c41a 100644 --- a/modules/home-manager-modules/programs/dbeaver.nix +++ b/modules/home-manager-modules/programs/dbeaver.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.dbeaver-bin = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.dataHome}/DBeaverData/" diff --git a/modules/home-manager-modules/programs/default.nix b/modules/home-manager-modules/programs/default.nix index 68e5c71..3fff489 100644 --- a/modules/home-manager-modules/programs/default.nix +++ b/modules/home-manager-modules/programs/default.nix @@ -12,11 +12,13 @@ ./obsidian.nix ./prostudiomasters.nix ./idea.nix + ./kdenlive.nix ./krita.nix ./protonvpn.nix ./calibre.nix ./bruno.nix ./dbeaver.nix + ./dungeon-draft.nix ./steam.nix ./vscode ./ungoogled-chromium.nix @@ -24,6 +26,7 @@ ./mapillary-uploader.nix ./inkscape.nix ./gimp.nix + ./guild-wars-2.nix ./proxmark3.nix ./freecad.nix ./onionshare.nix @@ -33,11 +36,14 @@ ./qflipper.nix ./openvpn.nix ./noisetorch.nix + ./olympus.nix ./openrgb.nix ./via.nix + ./vortex.nix ./davinci-resolve.nix ./gdx-liftoff.nix ./tor-browser.nix ./polycule.nix + ./vmware-workstation.nix ]; } diff --git a/modules/home-manager-modules/programs/discord.nix b/modules/home-manager-modules/programs/discord.nix index e8605a5..d5d7192 100644 --- a/modules/home-manager-modules/programs/discord.nix +++ b/modules/home-manager-modules/programs/discord.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.discord = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/discord/" diff --git a/modules/home-manager-modules/programs/dungeon-draft.nix b/modules/home-manager-modules/programs/dungeon-draft.nix new file mode 100644 index 0000000..faa69c6 --- /dev/null +++ b/modules/home-manager-modules/programs/dungeon-draft.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.dungeon-draft; +in { + options.programs.dungeon-draft = { + enable = lib.mkEnableOption "Dungeon Draft"; + }; + + config = { + assertions = [ + { + assertion = !cfg.enable; + message = '' + Dungeon Draft module is not yet fully configured. + Please download the Dungeon Draft executable (.exe) from the official website, + then configure the Wine environment and executable path as needed. + ''; + } + ]; + }; +} diff --git a/modules/home-manager-modules/programs/firefox.nix b/modules/home-manager-modules/programs/firefox.nix index 907b619..8841887 100644 --- a/modules/home-manager-modules/programs/firefox.nix +++ b/modules/home-manager-modules/programs/firefox.nix @@ -1,7 +1,6 @@ { lib, config, - osConfig, ... }: let buildProfilePersistence = profile: { @@ -26,7 +25,7 @@ allowOther = true; }; in { - config = lib.mkIf (config.programs.firefox.enable && osConfig.host.impermanence.enable) { + config = lib.mkIf (config.programs.firefox.enable && config.impermanence.enable) { home.persistence."/persist${config.home.homeDirectory}" = lib.mkMerge ( ( lib.attrsets.mapAttrsToList diff --git a/modules/home-manager-modules/programs/freecad.nix b/modules/home-manager-modules/programs/freecad.nix index ec17205..89668de 100644 --- a/modules/home-manager-modules/programs/freecad.nix +++ b/modules/home-manager-modules/programs/freecad.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.freecad = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/FreeCAD" diff --git a/modules/home-manager-modules/programs/gdx-liftoff.nix b/modules/home-manager-modules/programs/gdx-liftoff.nix index b29230d..4440831 100644 --- a/modules/home-manager-modules/programs/gdx-liftoff.nix +++ b/modules/home-manager-modules/programs/gdx-liftoff.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.gdx-liftoff = { diff --git a/modules/home-manager-modules/programs/gimp.nix b/modules/home-manager-modules/programs/gimp.nix index 428068e..925a2d9 100644 --- a/modules/home-manager-modules/programs/gimp.nix +++ b/modules/home-manager-modules/programs/gimp.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.gimp = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/GIMP" diff --git a/modules/home-manager-modules/programs/guild-wars-2.nix b/modules/home-manager-modules/programs/guild-wars-2.nix new file mode 100644 index 0000000..3f68ec6 --- /dev/null +++ b/modules/home-manager-modules/programs/guild-wars-2.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.guild-wars-2; +in { + options.programs.guild-wars-2 = { + enable = lib.mkEnableOption "Guild Wars 2"; + }; + + config = { + assertions = [ + { + assertion = !cfg.enable; + message = '' + Guild Wars 2 module is not yet fully configured. + Please install Guild Wars 2 manually via Steam or the official client, + then configure the Wine environment as needed. + ''; + } + ]; + }; +} diff --git a/modules/home-manager-modules/programs/idea.nix b/modules/home-manager-modules/programs/idea.nix index f0a928c..e59e7b2 100644 --- a/modules/home-manager-modules/programs/idea.nix +++ b/modules/home-manager-modules/programs/idea.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.jetbrains.idea-community = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ # configuration diff --git a/modules/home-manager-modules/programs/inkscape.nix b/modules/home-manager-modules/programs/inkscape.nix index facb08f..a26ddec 100644 --- a/modules/home-manager-modules/programs/inkscape.nix +++ b/modules/home-manager-modules/programs/inkscape.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.inkscape = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/inkscape" diff --git a/modules/home-manager-modules/programs/kdenlive.nix b/modules/home-manager-modules/programs/kdenlive.nix new file mode 100644 index 0000000..05327d1 --- /dev/null +++ b/modules/home-manager-modules/programs/kdenlive.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.kdenlive; +in { + options.programs.kdenlive = { + enable = lib.mkEnableOption "kdenlive"; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.kdePackages.kdenlive; + description = "The kdenlive package to install."; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + home.packages = [ + cfg.package + ]; + } + ( + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/kdenliverc" + "${config.xdg.dataHome}/kdenlive" + ]; + allowOther = true; + }; + } + ) + ]); +} diff --git a/modules/home-manager-modules/programs/krita.nix b/modules/home-manager-modules/programs/krita.nix index d662251..3ba5560 100644 --- a/modules/home-manager-modules/programs/krita.nix +++ b/modules/home-manager-modules/programs/krita.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.krita = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/kritarc" diff --git a/modules/home-manager-modules/programs/libreoffice.nix b/modules/home-manager-modules/programs/libreoffice.nix index b61ea58..93163e7 100644 --- a/modules/home-manager-modules/programs/libreoffice.nix +++ b/modules/home-manager-modules/programs/libreoffice.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.libreoffice = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/libreoffice" diff --git a/modules/home-manager-modules/programs/makemkv.nix b/modules/home-manager-modules/programs/makemkv.nix index eca059d..e92c3d3 100644 --- a/modules/home-manager-modules/programs/makemkv.nix +++ b/modules/home-manager-modules/programs/makemkv.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.makemkv = { @@ -30,7 +29,7 @@ home.file.".MakeMKV/settings.conf".source = config.lib.file.mkOutOfStoreSymlink config.sops.templates."MakeMKV.settings.conf".path; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ ".MakeMKV" diff --git a/modules/home-manager-modules/programs/mapillary-uploader.nix b/modules/home-manager-modules/programs/mapillary-uploader.nix index 38c1144..df1f093 100644 --- a/modules/home-manager-modules/programs/mapillary-uploader.nix +++ b/modules/home-manager-modules/programs/mapillary-uploader.nix @@ -11,7 +11,20 @@ in { enable = mkEnableOption "Mapillary Desktop Uploader"; }; - config = mkIf cfg.enable { - home.packages = [pkgs.mapillary-uploader]; - }; + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [pkgs.mapillary-uploader]; + } + ( + mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/mapillary-uploader" + "${config.xdg.dataHome}/mapillary-uploader" + ]; + allowOther = true; + }; + } + ) + ]); } diff --git a/modules/home-manager-modules/programs/mfoc.nix b/modules/home-manager-modules/programs/mfoc.nix index 7b92007..6006c9b 100644 --- a/modules/home-manager-modules/programs/mfoc.nix +++ b/modules/home-manager-modules/programs/mfoc.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.mfoc = { diff --git a/modules/home-manager-modules/programs/noisetorch.nix b/modules/home-manager-modules/programs/noisetorch.nix index c53e3a9..4b42638 100644 --- a/modules/home-manager-modules/programs/noisetorch.nix +++ b/modules/home-manager-modules/programs/noisetorch.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.noisetorch = { diff --git a/modules/home-manager-modules/programs/obs.nix b/modules/home-manager-modules/programs/obs.nix index 98c4fea..bfdba90 100644 --- a/modules/home-manager-modules/programs/obs.nix +++ b/modules/home-manager-modules/programs/obs.nix @@ -1,13 +1,17 @@ { lib, config, - osConfig, ... }: { config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ ( - lib.mkIf osConfig.host.impermanence.enable { - # TODO: map impermanence for obs + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/obs-studio" + ]; + allowOther = true; + }; } ) ]); diff --git a/modules/home-manager-modules/programs/obsidian.nix b/modules/home-manager-modules/programs/obsidian.nix index 4d28b3e..824563d 100644 --- a/modules/home-manager-modules/programs/obsidian.nix +++ b/modules/home-manager-modules/programs/obsidian.nix @@ -1,12 +1,11 @@ { lib, config, - osConfig, ... }: { config = lib.mkIf config.programs.obsidian.enable (lib.mkMerge [ ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/obsidian" diff --git a/modules/home-manager-modules/programs/olympus.nix b/modules/home-manager-modules/programs/olympus.nix new file mode 100644 index 0000000..0e38eec --- /dev/null +++ b/modules/home-manager-modules/programs/olympus.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.olympus; +in { + options.programs.olympus = { + enable = lib.mkEnableOption "olympus"; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.olympus; + description = "The olympus package to install."; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + home.packages = [ + cfg.package + ]; + } + ( + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/olympus" + "${config.xdg.dataHome}/olympus" + ]; + allowOther = true; + }; + } + ) + ]); +} diff --git a/modules/home-manager-modules/programs/onionshare.nix b/modules/home-manager-modules/programs/onionshare.nix index ed1903d..475f993 100644 --- a/modules/home-manager-modules/programs/onionshare.nix +++ b/modules/home-manager-modules/programs/onionshare.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.onionshare = { diff --git a/modules/home-manager-modules/programs/openrgb.nix b/modules/home-manager-modules/programs/openrgb.nix index 0260c91..c9d5e14 100644 --- a/modules/home-manager-modules/programs/openrgb.nix +++ b/modules/home-manager-modules/programs/openrgb.nix @@ -2,16 +2,27 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.openrgb = { enable = lib.mkEnableOption "enable openrgb"; }; - config = lib.mkIf config.programs.openrgb.enable { - home.packages = with pkgs; [ - openrgb - ]; - }; + config = lib.mkIf config.programs.openrgb.enable (lib.mkMerge [ + { + home.packages = with pkgs; [ + openrgb + ]; + } + ( + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/OpenRGB" + ]; + allowOther = true; + }; + } + ) + ]); } diff --git a/modules/home-manager-modules/programs/openvpn.nix b/modules/home-manager-modules/programs/openvpn.nix index 814c16d..dcd499c 100644 --- a/modules/home-manager-modules/programs/openvpn.nix +++ b/modules/home-manager-modules/programs/openvpn.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.openvpn = { diff --git a/modules/home-manager-modules/programs/pdfarranger.nix b/modules/home-manager-modules/programs/pdfarranger.nix index d4e33b5..9246efd 100644 --- a/modules/home-manager-modules/programs/pdfarranger.nix +++ b/modules/home-manager-modules/programs/pdfarranger.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.pdfarranger = { diff --git a/modules/home-manager-modules/programs/picard.nix b/modules/home-manager-modules/programs/picard.nix index d2c1fe2..bc37b86 100644 --- a/modules/home-manager-modules/programs/picard.nix +++ b/modules/home-manager-modules/programs/picard.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.picard = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/MusicBrainz" diff --git a/modules/home-manager-modules/programs/piper.nix b/modules/home-manager-modules/programs/piper.nix index ec0d887..3ed25fd 100644 --- a/modules/home-manager-modules/programs/piper.nix +++ b/modules/home-manager-modules/programs/piper.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.piper = { diff --git a/modules/home-manager-modules/programs/polycule.nix b/modules/home-manager-modules/programs/polycule.nix index a7004bd..d0aea2a 100644 --- a/modules/home-manager-modules/programs/polycule.nix +++ b/modules/home-manager-modules/programs/polycule.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.polycule = { @@ -17,7 +16,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { # TODO: check that these are actually the correct folders # directories = [ diff --git a/modules/home-manager-modules/programs/prostudiomasters.nix b/modules/home-manager-modules/programs/prostudiomasters.nix index 9e6088f..5345169 100644 --- a/modules/home-manager-modules/programs/prostudiomasters.nix +++ b/modules/home-manager-modules/programs/prostudiomasters.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.prostudiomasters = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/ProStudioMasters" diff --git a/modules/home-manager-modules/programs/protonvpn.nix b/modules/home-manager-modules/programs/protonvpn.nix index dd11aae..513a610 100644 --- a/modules/home-manager-modules/programs/protonvpn.nix +++ b/modules/home-manager-modules/programs/protonvpn.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.protonvpn-gui = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/protonvpn" diff --git a/modules/home-manager-modules/programs/proxmark3.nix b/modules/home-manager-modules/programs/proxmark3.nix index ad1e298..656be19 100644 --- a/modules/home-manager-modules/programs/proxmark3.nix +++ b/modules/home-manager-modules/programs/proxmark3.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.proxmark3 = { diff --git a/modules/home-manager-modules/programs/qbittorrent.nix b/modules/home-manager-modules/programs/qbittorrent.nix index 02e23df..61d13c0 100644 --- a/modules/home-manager-modules/programs/qbittorrent.nix +++ b/modules/home-manager-modules/programs/qbittorrent.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.qbittorrent = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/qBittorrent" diff --git a/modules/home-manager-modules/programs/qflipper.nix b/modules/home-manager-modules/programs/qflipper.nix index abc2442..8b42766 100644 --- a/modules/home-manager-modules/programs/qflipper.nix +++ b/modules/home-manager-modules/programs/qflipper.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.qflipper = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/qFlipper" diff --git a/modules/home-manager-modules/programs/signal.nix b/modules/home-manager-modules/programs/signal.nix index fdf0af9..7db23a7 100644 --- a/modules/home-manager-modules/programs/signal.nix +++ b/modules/home-manager-modules/programs/signal.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.signal-desktop-bin = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/Signal" diff --git a/modules/home-manager-modules/programs/steam.nix b/modules/home-manager-modules/programs/steam.nix index 4661151..fd98cb6 100644 --- a/modules/home-manager-modules/programs/steam.nix +++ b/modules/home-manager-modules/programs/steam.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.steam = { @@ -18,7 +17,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ { diff --git a/modules/home-manager-modules/programs/tor-browser.nix b/modules/home-manager-modules/programs/tor-browser.nix index 2c58578..c3b085d 100644 --- a/modules/home-manager-modules/programs/tor-browser.nix +++ b/modules/home-manager-modules/programs/tor-browser.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.tor-browser = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.dataHome}/torbrowser" diff --git a/modules/home-manager-modules/programs/ungoogled-chromium.nix b/modules/home-manager-modules/programs/ungoogled-chromium.nix index 5b52cd6..ef6a881 100644 --- a/modules/home-manager-modules/programs/ungoogled-chromium.nix +++ b/modules/home-manager-modules/programs/ungoogled-chromium.nix @@ -2,7 +2,6 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.ungoogled-chromium = { @@ -16,7 +15,7 @@ ]; } ( - lib.mkIf osConfig.host.impermanence.enable { + lib.mkIf config.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { directories = [ "${config.xdg.configHome}/chromium" diff --git a/modules/home-manager-modules/programs/via.nix b/modules/home-manager-modules/programs/via.nix index 0b79452..0aa58e4 100644 --- a/modules/home-manager-modules/programs/via.nix +++ b/modules/home-manager-modules/programs/via.nix @@ -2,16 +2,28 @@ lib, pkgs, config, - osConfig, ... }: { options.programs.via = { enable = lib.mkEnableOption "enable via"; }; - config = lib.mkIf config.programs.via.enable { - home.packages = with pkgs; [ - via - ]; - }; + config = lib.mkIf config.programs.via.enable (lib.mkMerge [ + { + home.packages = with pkgs; [ + via + ]; + } + ( + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.configHome}/via" + "${config.xdg.dataHome}/via" + ]; + allowOther = true; + }; + } + ) + ]); } diff --git a/modules/home-manager-modules/programs/vmware-workstation.nix b/modules/home-manager-modules/programs/vmware-workstation.nix new file mode 100644 index 0000000..8e9d406 --- /dev/null +++ b/modules/home-manager-modules/programs/vmware-workstation.nix @@ -0,0 +1,37 @@ +{ + lib, + pkgs, + config, + ... +}: { + options.programs.vmware-workstation = { + enable = lib.mkEnableOption "enable VMware Workstation"; + }; + + config = lib.mkIf config.programs.vmware-workstation.enable ( + lib.mkMerge [ + { + home.packages = with pkgs; [ + vmware-workstation + ]; + } + ( + lib.mkIf config.impermanence.enable { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + { + directory = ".vmware"; + method = "symlink"; + } + { + directory = "vmware"; + method = "symlink"; + } + ]; + allowOther = true; + }; + } + ) + ] + ); +} diff --git a/modules/home-manager-modules/programs/vortex.nix b/modules/home-manager-modules/programs/vortex.nix new file mode 100644 index 0000000..cb86526 --- /dev/null +++ b/modules/home-manager-modules/programs/vortex.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.vortex; +in { + options.programs.vortex = { + enable = lib.mkEnableOption "Vortex (Nexus Mods manager)"; + }; + + config = { + assertions = [ + { + assertion = !cfg.enable; + message = '' + Vortex module is not yet fully configured. + Please download and install Vortex manually from the Nexus Mods website, + then configure the Wine environment and dependencies as needed. + ''; + } + ]; + }; +} diff --git a/modules/home-manager-modules/programs/vscode/default.nix b/modules/home-manager-modules/programs/vscode/default.nix index 85f4a62..8f366fe 100644 --- a/modules/home-manager-modules/programs/vscode/default.nix +++ b/modules/home-manager-modules/programs/vscode/default.nix @@ -23,5 +23,6 @@ ./vitest.nix ./direnv.nix ./conventionalCommits.nix + ./openDyslexicFont.nix ]; } diff --git a/modules/home-manager-modules/programs/vscode/openDyslexicFont.nix b/modules/home-manager-modules/programs/vscode/openDyslexicFont.nix new file mode 100644 index 0000000..f1f6215 --- /dev/null +++ b/modules/home-manager-modules/programs/vscode/openDyslexicFont.nix @@ -0,0 +1,49 @@ +{ + lib, + pkgs, + config, + ... +}: { + options.programs.vscode.profiles = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { + options = { + extraExtensions.openDyslexicFont = { + enable = lib.mkEnableOption "should OpenDyslexic font be set as the default font for VSCode"; + package = lib.mkPackageOption pkgs "nerd-fonts.open-dyslexic" { + default = ["nerd-fonts" "open-dyslexic"]; + }; + }; + }; + config = lib.mkIf config.extraExtensions.openDyslexicFont.enable { + userSettings = { + "editor.fontFamily" = "'OpenDyslexicM Nerd Font Mono', Droid Sans Mono, monospace"; + "editor.fontSize" = 14; + "editor.letterSpacing" = -0.3; + }; + }; + })); + }; + + config = let + enabledProfiles = + lib.filter (profile: profile.extraExtensions.openDyslexicFont.enable or false) + (lib.attrValues config.programs.vscode.profiles); + + anyProfileUsesOpenDyslexicFont = enabledProfiles != []; + + fontPackages = lib.unique (map (profile: profile.extraExtensions.openDyslexicFont.package) enabledProfiles); + in { + # Ensure OpenDyslexic font packages are installed when any VSCode profile uses them + home.packages = fontPackages; + + fonts.fontconfig.enable = lib.mkIf anyProfileUsesOpenDyslexicFont true; + + # Add assertion to ensure the fonts are available + assertions = + map (fontPkg: { + assertion = lib.elem fontPkg config.home.packages; + message = "OpenDyslexic font package '${fontPkg.name or "unknown"}' must be installed when using openDyslexicFont extension for VSCode."; + }) + fontPackages; + }; +} diff --git a/modules/nixos-modules/server/crab-hole/crab-hole.nix b/modules/nixos-modules/server/crab-hole/crab-hole.nix new file mode 100644 index 0000000..58ff660 --- /dev/null +++ b/modules/nixos-modules/server/crab-hole/crab-hole.nix @@ -0,0 +1,144 @@ +{ + 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 = { + loopback = { + enable = lib.mkEnableOption "loopback downstream DNS server on localhost:53"; + openFirewall = lib.mkEnableOption "automatic port forwarding for the loopback downstream"; + }; + }; + + 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."; + }; + }; + + config = lib.mkIf cfg.enable { + 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; + } + (lib.mkIf cfg.downstreams.loopback.enable { + downstream = [ + { + protocol = "udp"; + listen = "localhost"; + port = 53; + } + ]; + }) + (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.loopback.enable && cfg.downstreams.loopback.openFirewall) { + allowedUDPPorts = [53]; + }) + ]; + }; +} diff --git a/modules/nixos-modules/server/crab-hole/default.nix b/modules/nixos-modules/server/crab-hole/default.nix new file mode 100644 index 0000000..158a851 --- /dev/null +++ b/modules/nixos-modules/server/crab-hole/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + ./crab-hole.nix + ./impermanence.nix + ]; +} diff --git a/modules/nixos-modules/server/crab-hole/impermanence.nix b/modules/nixos-modules/server/crab-hole/impermanence.nix new file mode 100644 index 0000000..455e593 --- /dev/null +++ b/modules/nixos-modules/server/crab-hole/impermanence.nix @@ -0,0 +1,26 @@ +{ + lib, + config, + ... +}: let + workingDirectory = "/var/lib/private/crab-hole"; +in { + config = lib.mkIf (config.services.immich.enable && config.host.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"; + } + ]; + }; + }; +} diff --git a/modules/nixos-modules/server/default.nix b/modules/nixos-modules/server/default.nix index e550123..57874d5 100644 --- a/modules/nixos-modules/server/default.nix +++ b/modules/nixos-modules/server/default.nix @@ -8,10 +8,14 @@ ./actual ./bazarr + ./crab-hole + ./flaresolverr ./forgejo ./home-assistant ./immich + ./jackett ./jellyfin + ./lidarr ./panoramax ./paperless ./qbittorent.nix diff --git a/modules/nixos-modules/server/flaresolverr/default.nix b/modules/nixos-modules/server/flaresolverr/default.nix new file mode 100644 index 0000000..f39d940 --- /dev/null +++ b/modules/nixos-modules/server/flaresolverr/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + ./proxy.nix + ./impermanence.nix + ]; +} diff --git a/modules/nixos-modules/server/flaresolverr/impermanence.nix b/modules/nixos-modules/server/flaresolverr/impermanence.nix new file mode 100644 index 0000000..b568a56 --- /dev/null +++ b/modules/nixos-modules/server/flaresolverr/impermanence.nix @@ -0,0 +1,19 @@ +{ + lib, + config, + ... +}: { + config = lib.mkIf (config.services.flaresolverr.enable && config.host.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"; + } + ]; + }; + }; +} diff --git a/modules/nixos-modules/server/flaresolverr/proxy.nix b/modules/nixos-modules/server/flaresolverr/proxy.nix new file mode 100644 index 0000000..5b8dd4c --- /dev/null +++ b/modules/nixos-modules/server/flaresolverr/proxy.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + ... +}: { + options.services.flaresolverr = { + 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.flaresolverr.enable && config.services.flaresolverr.subdomain != null) { + host.reverse_proxy.subdomains.flaresolverr = { + subdomain = config.services.flaresolverr.subdomain; + extraSubdomains = config.services.flaresolverr.extraSubdomains; + target = "http://127.0.0.1:${toString config.services.flaresolverr.port}"; + websockets.enable = true; + forwardHeaders.enable = true; + }; + }; +} diff --git a/modules/nixos-modules/server/jackett/default.nix b/modules/nixos-modules/server/jackett/default.nix new file mode 100644 index 0000000..f39d940 --- /dev/null +++ b/modules/nixos-modules/server/jackett/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + ./proxy.nix + ./impermanence.nix + ]; +} diff --git a/modules/nixos-modules/server/jackett/impermanence.nix b/modules/nixos-modules/server/jackett/impermanence.nix new file mode 100644 index 0000000..5826a54 --- /dev/null +++ b/modules/nixos-modules/server/jackett/impermanence.nix @@ -0,0 +1,26 @@ +{ + lib, + config, + ... +}: let + jackett_data_directory = "/var/lib/jackett/.config/Jackett"; +in { + config = lib.mkIf (config.services.jackett.enable && config.host.impermanence.enable) { + assertions = [ + { + assertion = config.services.jackett.dataDir == jackett_data_directory; + message = "jackett data directory does not match persistence"; + } + ]; + + environment.persistence."/persist/system/root" = { + directories = [ + { + directory = jackett_data_directory; + user = "jackett"; + group = "jackett"; + } + ]; + }; + }; +} diff --git a/modules/nixos-modules/server/jackett/proxy.nix b/modules/nixos-modules/server/jackett/proxy.nix new file mode 100644 index 0000000..af5fa79 --- /dev/null +++ b/modules/nixos-modules/server/jackett/proxy.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + ... +}: { + options.services.jackett = { + 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.jackett.enable && config.services.jackett.subdomain != null) { + host.reverse_proxy.subdomains.jackett = { + subdomain = config.services.jackett.subdomain; + extraSubdomains = config.services.jackett.extraSubdomains; + target = "http://127.0.0.1:9117"; + websockets.enable = true; + forwardHeaders.enable = true; + }; + }; +} diff --git a/modules/nixos-modules/server/lidarr/default.nix b/modules/nixos-modules/server/lidarr/default.nix new file mode 100644 index 0000000..f39d940 --- /dev/null +++ b/modules/nixos-modules/server/lidarr/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + ./proxy.nix + ./impermanence.nix + ]; +} diff --git a/modules/nixos-modules/server/lidarr/impermanence.nix b/modules/nixos-modules/server/lidarr/impermanence.nix new file mode 100644 index 0000000..689b924 --- /dev/null +++ b/modules/nixos-modules/server/lidarr/impermanence.nix @@ -0,0 +1,26 @@ +{ + lib, + config, + ... +}: let + lidarr_data_directory = "/var/lib/lidarr/.config/Lidarr"; +in { + config = lib.mkIf (config.services.lidarr.enable && config.host.impermanence.enable) { + assertions = [ + { + assertion = config.services.lidarr.dataDir == lidarr_data_directory; + message = "lidarr data directory does not match persistence"; + } + ]; + + environment.persistence."/persist/system/root" = { + directories = [ + { + directory = lidarr_data_directory; + user = "lidarr"; + group = "lidarr"; + } + ]; + }; + }; +} diff --git a/modules/nixos-modules/server/lidarr/proxy.nix b/modules/nixos-modules/server/lidarr/proxy.nix new file mode 100644 index 0000000..0146ccf --- /dev/null +++ b/modules/nixos-modules/server/lidarr/proxy.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + ... +}: { + options.services.lidarr = { + 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.lidarr.enable && config.services.lidarr.subdomain != null) { + host.reverse_proxy.subdomains.lidarr = { + subdomain = config.services.lidarr.subdomain; + extraSubdomains = config.services.lidarr.extraSubdomains; + target = "http://127.0.0.1:8686"; + websockets.enable = true; + forwardHeaders.enable = true; + }; + }; +} diff --git a/modules/nixos-modules/server/panoramax/impermanence.nix b/modules/nixos-modules/server/panoramax/impermanence.nix index 011c322..41b1401 100644 --- a/modules/nixos-modules/server/panoramax/impermanence.nix +++ b/modules/nixos-modules/server/panoramax/impermanence.nix @@ -1,10 +1,9 @@ { lib, config, - osConfig, ... }: { - config = lib.mkIf (config.services.panoramax.enable && osConfig.host.impermanence.enable) { + config = lib.mkIf (config.services.panoramax.enable && config.host.impermanence.enable) { # TODO: configure impermanence for panoramax data # This would typically include directories like: # - /var/lib/panoramax diff --git a/modules/nixos-modules/users.nix b/modules/nixos-modules/users.nix index 137ae4b..987e080 100644 --- a/modules/nixos-modules/users.nix +++ b/modules/nixos-modules/users.nix @@ -29,6 +29,8 @@ radarr = 2014; sonarr = 2015; bazarr = 2016; + lidarr = 2017; + crab-hole = 2018; }; gids = { @@ -50,6 +52,8 @@ radarr = 2014; sonarr = 2015; bazarr = 2016; + lidarr = 2017; + crab-hole = 2018; }; users = config.users.users; @@ -221,6 +225,18 @@ in { isSystemUser = true; group = config.users.users.bazarr.name; }; + + lidarr = { + uid = lib.mkForce uids.lidarr; + isSystemUser = true; + group = config.users.users.lidarr.name; + }; + + crab-hole = { + uid = lib.mkForce uids.crab-hole; + isSystemUser = true; + group = config.users.users.crab-hole.name; + }; }; groups = { @@ -261,6 +277,7 @@ in { users.radarr.name users.sonarr.name users.bazarr.name + users.lidarr.name leyla eve ivy @@ -365,6 +382,20 @@ in { users.bazarr.name ]; }; + + lidarr = { + gid = lib.mkForce gids.lidarr; + members = [ + users.lidarr.name + ]; + }; + + crab-hole = { + gid = lib.mkForce gids.crab-hole; + members = [ + users.crab-hole.name + ]; + }; }; }; } diff --git a/rebuild.sh b/rebuild.sh index 36a1201..6750450 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -1,5 +1,15 @@ #!/usr/bin/env bash +# Get current branch and git status for branch-aware behavior +current_branch=$(git branch --show-current 2>/dev/null || echo "unknown") +git_status=$(git status --porcelain 2>/dev/null || echo "") + +# Default values +default_target=$(hostname) +default_user="$USER" +default_host=$(hostname) +default_mode=$(if [[ "$current_branch" != "main" ]]; then echo "test"; else echo "switch"; fi) + if [ -d "result" ]; then preserve_result=true @@ -42,14 +52,29 @@ while [ $# -gt 0 ]; do ;; --help|-h) echo "--help -h: print this message" - echo "--target -t: set the target system to rebuild on" - echo "--flake -f: set the flake to rebuild on the target system" - echo "--mode -m: set the mode to rebuild flake as on the target system" - echo "--user -u: set the user to rebuild flake as on the target system" - echo "--host: set the host that the flake will be rebuilt on (unset for current machine)" + echo "--target -t: defaults to the current system" + echo " currently: $default_target" + echo "--flake -f: defaults to same as target" + echo " currently: ${target:-$default_target}" + echo "--mode -m: defaults to 'switch', but 'test' on non-main branches" + echo " currently would be: $default_mode" + echo "--user -u: defaults to the current user" + echo " currently: $default_user" + echo "--host: defaults to building on the current machine" + echo " currently: $default_host" echo "--preserve-result: do not remove the generated result folder after building" echo "--no-preserve-result: remove any result folder after building" echo "--show-trace: show trace on builds" + echo "" + echo "Branch-aware behavior:" + echo " - On non-main branches: defaults to test mode with warning" + echo " - On main with uncommitted changes: shows warning about creating a branch" + echo " - Current branch: $current_branch" + if [[ -n "$git_status" ]]; then + echo " - Git status: uncommitted changes detected" + else + echo " - Git status: clean working tree" + fi exit 0 ;; *) @@ -60,10 +85,21 @@ while [ $# -gt 0 ]; do shift done -target=${target:-$(hostname)} +target=${target:-$default_target} flake=${flake:-$target} -mode=${mode:-switch} -user=${user:-$USER} +mode=${mode:-$default_mode} +user=${user:-$default_user} + +# Branch-aware warnings and behavior +if [[ "$current_branch" != "main" ]] && [[ "$mode" == "test" ]]; then + echo "⚠️ WARNING: You are on branch '$current_branch' (not main)" + echo " Defaulting to test mode to prevent accidental system changes" + echo " Specify --mode=switch explicitly if you want to apply changes" +elif [[ "$current_branch" == "main" ]] && [[ -n "$git_status" ]] && [[ "$mode" != "test" ]]; then + echo "⚠️ WARNING: You are on main branch with uncommitted changes" + echo " Consider creating a feature branch for development:" + echo " git checkout -b feature/your-feature-name" +fi command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake" @@ -91,4 +127,4 @@ then then rm -r result fi -fi \ No newline at end of file +fi