diff --git a/.hooks/post-commit b/.hooks/post-commit index 03a160d..56c439d 100755 --- a/.hooks/post-commit +++ b/.hooks/post-commit @@ -3,12 +3,4 @@ echo "restoring stashed changes" -# Find the most recent pre-commit stash and restore it -recent_stash=$(git stash list | grep "pre-commit-stash-" | head -n 1 | cut -d: -f1) - -if [ -n "$recent_stash" ]; then - echo "Found recent pre-commit stash: $recent_stash" - git stash pop -q "$recent_stash" -else - echo "No pre-commit stash found to restore" -fi +git stash pop -q diff --git a/.hooks/post-merge b/.hooks/post-merge deleted file mode 100755 index 06fabc3..0000000 --- a/.hooks/post-merge +++ /dev/null @@ -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 diff --git a/.hooks/pre-commit b/.hooks/pre-commit index 74cbc64..f98c64f 100755 --- a/.hooks/pre-commit +++ b/.hooks/pre-commit @@ -1,24 +1,14 @@ #!/usr/bin/env nix-shell #! nix-shell -i bash ../shell.nix -# Get current branch name -current_branch=$(git branch --show-current) +echo "stashing all uncommitted changes" +git stash -q --keep-index -echo "stashing all uncommitted changes with named stash (excluding hooks)" -git stash push -q --keep-index -m "pre-commit-stash-$(date +%s)" -- ':!.hooks/' +echo "checking flakes all compile" +nix flake check -# Only run nix flake check if we're on main branch -if [ "$current_branch" = "main" ]; then - echo "On main branch - checking flakes all compile" - nix flake check - - if [ ! $? -eq 0 ]; then - echo "Error: nix flake check failed on main branch" - exit 1 - fi - echo "nix flake check passed" -else - echo "Not on main branch - skipping nix flake check" +if [ ! $? -eq 0 ]; then + exit 1 fi echo "running linter" @@ -29,4 +19,4 @@ RESULT=$? echo "adding lint changes to commit" git add -u -exit $RESULT +exit $RESULT \ No newline at end of file diff --git a/.hooks/pre-merge-commit b/.hooks/pre-merge-commit deleted file mode 100755 index 9b7b41d..0000000 --- a/.hooks/pre-merge-commit +++ /dev/null @@ -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 diff --git a/README.md b/README.md index 883e143..acaa6e7 100644 --- a/README.md +++ b/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 npins https://jade.fyi/blog/pinning-nixos-with-npins/ - https://nixos-and-flakes.thiscute.world/ -- proton mail now has an smtp server we could use that for our zfs and SMART test emails # Tasks: -## Chores: -- [ ] test out crab hole service - ## Tech Debt -- [ ] monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) -- [ ] migrate away from flakes and move to npins - -## Broken things -- [ ] figure out steam vr things? -- [ ] whisper was having issues - -## Data Integrity -- [ ] zfs email after scrubbing # TODO: test this -- [ ] SMART test with email results -- [ ] zfs encryption FIDO2 2fa (look into shavee) -- [ ] rotate sops encryption keys periodically (and somehow sync between devices?) -- [ ] Secure Boot - https://github.com/nix-community/lanzaboote -- [ ] auto turn off on power loss - nut -- [ ] secondary server with data sync. Maybe a Pi with a usb hdd enclosure and use rtcwake to only turn on once a week to sync data over tailscale with connection initiated from pi's side. We could probably put this at LZ. Hoping for it to draw only like $1 of power a month. Initial sync should probably be done here before we move it over because that will take a while. Data should be encrypted so that devices doesn't have access to it. Project will prob cost like $1800 - -## Data Access -- [ ] nfs export should be backed by the same values for server and client -- [ ] samba mounts -- [ ] offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) -- [ ] figure out why syncthing and jellyfins permissions don't propagate downwards -- [ ] make radarr, sonarr, and bazarr accessible over vpn -- [ ] move searx, home-assistant, actual, vikunja, jellyfin, paperless, and immich to only be accessible via vpn - -## Services -- [ ] vikunja service for project management -- [ ] Penpot services (need to make this custom) -- [ ] minecraft server with old world file -- [ ] Create Tor guard/relay server -- [ ] mastodon instance -- [ ] screeps server - -## 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 \ No newline at end of file +- 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 diff --git a/configurations/home-manager/eve/gnomeconf.nix b/configurations/home-manager/eve/gnomeconf.nix index 7cd3863..fbad391 100644 --- a/configurations/home-manager/eve/gnomeconf.nix +++ b/configurations/home-manager/eve/gnomeconf.nix @@ -1,39 +1,12 @@ -{ - osConfig, - lib, - ... -}: { +{pkgs, ...}: { 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 fb8d8a4..f738fe2 100644 --- a/configurations/home-manager/eve/packages.nix +++ b/configurations/home-manager/eve/packages.nix @@ -18,7 +18,6 @@ in { home.packages = lib.lists.optionals userConfig.isDesktopUser ( with pkgs; [ gnomeExtensions.dash-to-panel - claude-code ] ); @@ -32,11 +31,9 @@ in { (lib.mkIf (config.user.isDesktopUser || config.user.isTerminalUser) { git = { enable = true; - settings = { - user.name = "Eve"; - user.email = "evesnrobins@gmail.com"; - init.defaultBranch = "main"; - }; + userName = "Eve"; + userEmail = "evesnrobins@gmail.com"; + extraConfig.init.defaultBranch = "main"; }; openssh = { @@ -64,22 +61,6 @@ 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/git/default.nix b/configurations/home-manager/git/default.nix index 1ea29cc..2276e7a 100644 --- a/configurations/home-manager/git/default.nix +++ b/configurations/home-manager/git/default.nix @@ -1,6 +1,4 @@ {osConfig, ...}: { - impermanence.fallbackPersistence.enable = false; - home = { username = osConfig.users.users.git.name; homeDirectory = osConfig.users.users.git.home; diff --git a/configurations/home-manager/leyla/dconf.nix b/configurations/home-manager/leyla/dconf.nix index 9aa61f7..ef75db6 100644 --- a/configurations/home-manager/leyla/dconf.nix +++ b/configurations/home-manager/leyla/dconf.nix @@ -1,43 +1,31 @@ -{...}: { +{pkgs, ...}: { config = { gnome = { extraWindowControls = true; colorScheme = "prefer-dark"; clockFormat = "24h"; - 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; - }; - }; - }; + extensions = [ + pkgs.gnomeExtensions.dash-to-dock + ]; 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 8a37754..6d759c5 100644 --- a/configurations/home-manager/leyla/default.nix +++ b/configurations/home-manager/leyla/default.nix @@ -12,8 +12,6 @@ ]; config = { - impermanence.enable = osConfig.host.impermanence.enable; - # Home Manager needs a bit of information about you and the paths it should # manage. home = { @@ -89,6 +87,7 @@ # 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 ce81c81..041bff8 100644 --- a/configurations/home-manager/leyla/impermanence.nix +++ b/configurations/home-manager/leyla/impermanence.nix @@ -1,9 +1,10 @@ { lib, config, + osConfig, ... }: { - config = lib.mkIf (config.impermanence.enable) { + config = lib.mkIf osConfig.host.impermanence.enable { home.persistence."/persist/home/leyla" = { directories = [ "desktop" diff --git a/configurations/home-manager/leyla/packages/default.nix b/configurations/home-manager/leyla/packages/default.nix index 50cc175..5bccad3 100644 --- a/configurations/home-manager/leyla/packages/default.nix +++ b/configurations/home-manager/leyla/packages/default.nix @@ -9,7 +9,7 @@ in { imports = [ ./vscode - ./firefox + ./firefox.nix ./direnv.nix ./openssh.nix ./git.nix diff --git a/configurations/home-manager/leyla/packages/firefox.nix b/configurations/home-manager/leyla/packages/firefox.nix new file mode 100644 index 0000000..d166eb4 --- /dev/null +++ b/configurations/home-manager/leyla/packages/firefox.nix @@ -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 = [""]; + # } + ]; + }; + }; + }; + }; +} diff --git a/configurations/home-manager/leyla/packages/firefox/bookmarks.nix b/configurations/home-manager/leyla/packages/firefox/bookmarks.nix deleted file mode 100644 index 8435d45..0000000 --- a/configurations/home-manager/leyla/packages/firefox/bookmarks.nix +++ /dev/null @@ -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 = [""]; - # } - ]; - }; - }; - }; -} diff --git a/configurations/home-manager/leyla/packages/firefox/default.nix b/configurations/home-manager/leyla/packages/firefox/default.nix deleted file mode 100644 index 4246c68..0000000 --- a/configurations/home-manager/leyla/packages/firefox/default.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ - lib, - pkgs, - inputs, - ... -}: { - imports = [ - ./firefox.nix - ./bookmarks.nix - ./harden.nix - ]; - - config = { - programs.firefox = { - enable = true; - }; - }; -} diff --git a/configurations/home-manager/leyla/packages/firefox/firefox.nix b/configurations/home-manager/leyla/packages/firefox/firefox.nix deleted file mode 100644 index 1678353..0000000 --- a/configurations/home-manager/leyla/packages/firefox/firefox.nix +++ /dev/null @@ -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; - }; - }; - }; -} diff --git a/configurations/home-manager/leyla/packages/firefox/harden.nix b/configurations/home-manager/leyla/packages/firefox/harden.nix deleted file mode 100644 index 66310c2..0000000 --- a/configurations/home-manager/leyla/packages/firefox/harden.nix +++ /dev/null @@ -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; - }; - }; - }; -} diff --git a/configurations/home-manager/leyla/packages/git.nix b/configurations/home-manager/leyla/packages/git.nix index 499e37b..568cd7a 100644 --- a/configurations/home-manager/leyla/packages/git.nix +++ b/configurations/home-manager/leyla/packages/git.nix @@ -2,11 +2,9 @@ config = { programs = { git = { - settings = { - user.name = "Leyla Becker"; - user.email = "git@jan-leila.com"; - init.defaultBranch = "main"; - }; + userName = "Leyla Becker"; + userEmail = "git@jan-leila.com"; + extraConfig.init.defaultBranch = "main"; }; }; }; diff --git a/configurations/home-manager/leyla/packages/vscode/default.nix b/configurations/home-manager/leyla/packages/vscode/default.nix index 36168b2..ba9e48a 100644 --- a/configurations/home-manager/leyla/packages/vscode/default.nix +++ b/configurations/home-manager/leyla/packages/vscode/default.nix @@ -32,7 +32,6 @@ in { "javascript.updateImportsOnFileMove.enabled" = "always"; "editor.tabSize" = 2; "editor.insertSpaces" = false; - # "terminal.integrated.fontFamily" = "'Droid Sans Mono', 'monospace', monospace"; } ]; @@ -41,7 +40,6 @@ in { oneDark.enable = true; atomKeybindings.enable = true; openRemoteSsh.enable = true; - # openDyslexicFont.enable = false; # html development autoRenameTag.enable = true; @@ -69,9 +67,6 @@ in { # go development go.enable = true; - # rust development - rustAnalyzer.enable = true; - # claude development claudeDev = lib.mkIf ai-tooling-enabled { enable = true; diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index e2f9401..9fbdee6 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -57,6 +57,7 @@ "ata-ST18000NT001-3NF101_ZVTEF27J" "ata-ST18000NE000-3G6101_ZVTJ7359" ] + # TODO: this needs to be configured manually [ "ata-ST4000NE001-2MA101_WS2275P3" "ata-ST4000NE001-2MA101_WS227B9F" @@ -102,6 +103,18 @@ 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 = { @@ -213,12 +226,6 @@ }; services = { - # PostgreSQL database server - postgresql = { - enable = true; - adminUsers = ["leyla"]; - }; - # temp enable desktop environment for setup # Enable the X11 windowing system. xserver.enable = true; @@ -231,16 +238,6 @@ gnome.enable = true; }; - # Enable new reverse proxy system - reverseProxy = { - enable = true; - openFirewall = true; - acme = { - enable = true; - email = "jan-leila@protonmail.com"; - }; - }; - ollama = { enable = true; exposePort = true; @@ -298,35 +295,35 @@ jellyfin = { enable = true; - domain = "media.jan-leila.com"; - extraDomains = ["jellyfin.jan-leila.com"]; + subdomain = "media"; + extraSubdomains = ["jellyfin"]; }; immich = { enable = true; - domain = "photos.jan-leila.com"; + subdomain = "photos"; }; forgejo = { enable = true; - reverseProxy.domain = "git.jan-leila.com"; + subdomain = "git"; }; searx = { enable = true; - domain = "search.jan-leila.com"; + subdomain = "search"; }; actual = { - enable = true; - domain = "budget.jan-leila.com"; + enable = false; + subdomain = "budget"; }; home-assistant = { enable = true; - domain = "home.jan-leila.com"; + subdomain = "home"; openFirewall = true; - postgres.enable = true; + database = "postgres"; extensions = { sonos.enable = true; @@ -337,7 +334,7 @@ paperless = { enable = true; - domain = "documents.jan-leila.com"; + subdomain = "documents"; passwordFile = config.sops.secrets."services/paperless_password".path; }; @@ -346,21 +343,6 @@ openFirewall = true; }; - crab-hole = { - enable = true; - port = 8085; - openFirewall = true; - show_doc = true; - downstreams = { - host = { - enable = true; - openFirewall = true; - }; - }; - upstreams.cloudFlare.enable = true; - blocklists.ad_malware.enable = true; - }; - qbittorrent = { enable = true; mediaDir = "/srv/qbittorent"; @@ -368,28 +350,21 @@ webuiPort = 8084; }; - sonarr = { + filebot-cleanup = { enable = true; + licenseFile = "/srv/jellyfin/filebot_license.psm"; + }; + + sonarr = { + enable = false; openFirewall = true; }; radarr = { - enable = true; + enable = false; openFirewall = true; }; bazarr = { - enable = true; - openFirewall = true; - }; - lidarr = { - enable = true; - openFirewall = true; - }; - jackett = { - enable = true; - openFirewall = true; - }; - flaresolverr = { - enable = true; + enable = false; openFirewall = true; }; }; diff --git a/configurations/nixos/defiant/default.nix b/configurations/nixos/defiant/default.nix index 3013946..05975a1 100644 --- a/configurations/nixos/defiant/default.nix +++ b/configurations/nixos/defiant/default.nix @@ -4,5 +4,6 @@ ./hardware-configuration.nix ./configuration.nix ./packages.nix + ./filebot.nix ]; } diff --git a/configurations/nixos/defiant/filebot.nix b/configurations/nixos/defiant/filebot.nix new file mode 100644 index 0000000..aaf247d --- /dev/null +++ b/configurations/nixos/defiant/filebot.nix @@ -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"; + } + ]; + }; + }; + }; +} diff --git a/configurations/nixos/emergent/configuration.nix b/configurations/nixos/emergent/configuration.nix index 6121069..bb671f7 100644 --- a/configurations/nixos/emergent/configuration.nix +++ b/configurations/nixos/emergent/configuration.nix @@ -41,14 +41,12 @@ # installed opentabletdriver hardware.opentabletdriver.enable = true; - hardware.keyboard.qmk.enable = true; # Enable the GNOME Desktop Environment. services.displayManager.gdm.enable = true; services.desktopManager.gnome.enable = true; host = { - ai.enable = true; users = { eve = { isDesktopUser = true; @@ -70,9 +68,6 @@ }; 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/flake.lock b/flake.lock index 11fb672..9309105 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ ] }, "locked": { - "lastModified": 1760701190, - "narHash": "sha256-y7UhnWlER8r776JsySqsbTUh2Txf7K30smfHlqdaIQw=", + "lastModified": 1758287904, + "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", "owner": "nix-community", "repo": "disko", - "rev": "3a9450b26e69dcb6f8de6e2b07b3fc1c288d85f5", + "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", "type": "github" }, "original": { @@ -46,11 +46,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1761478231, - "narHash": "sha256-a6ROM73M0TSrooI+8/UMj5KWKOdaDFTycVeo8XJ3dk4=", + "lastModified": 1759403080, + "narHash": "sha256-EteyL8KyG9R5xzqyOBzyag4n2cSemu61VFrl3opJSqE=", "owner": "rycee", "repo": "nur-expressions", - "rev": "ae968708476302f8781fb5e245d53f112ed04111", + "rev": "8af6dfcbcbf1115a4f5aeed77ff0db5d3c02caf0", "type": "gitlab" }, "original": { @@ -111,6 +111,24 @@ "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, @@ -133,11 +151,11 @@ ] }, "locked": { - "lastModified": 1761530345, - "narHash": "sha256-+9+YCK9Lh6GThkXu/8JTxMFUnImIdZpb8ElUh6/F5Y8=", + "lastModified": 1759337100, + "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", "owner": "nix-community", "repo": "home-manager", - "rev": "bbaeb9f1c29e79bb1653b32c3d73244cdf4bd888", + "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", "type": "github" }, "original": { @@ -164,11 +182,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1755787066, - "narHash": "sha256-X2UwkUEban08GRSPXRr+kz8fckHqebr3P77qSvjoeOw=", - "rev": "ac9721a92e8138d29707824dbedb484c76948493", + "lastModified": 1759624822, + "narHash": "sha256-cf40qfsfpxJU/BnQ9PEj027LdPINNSsJqm+C6Ug93BA=", + "rev": "57333a0e600c5e096a609410a2f1059b97194b1e", "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": { "type": "tarball", @@ -185,11 +203,11 @@ ] }, "locked": { - "lastModified": 1759851320, - "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", + "lastModified": 1756511062, + "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", "ref": "refs/heads/main", - "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", - "revCount": 163, + "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", + "revCount": 162, "type": "git", "url": "https://git.lix.systems/lix-project/nixos-module.git" }, @@ -207,11 +225,11 @@ ] }, "locked": { - "lastModified": 1760821194, - "narHash": "sha256-UCsJ8eDuHL14u2GFIYEY/drtZ6jht5zN/G/6QNlEy2g=", + "lastModified": 1759342933, + "narHash": "sha256-mdlUFcrOfvT0Pm+Hko/6aR3xf1ao5JA2iem4KsEVjP4=", "owner": "utensils", "repo": "mcp-nixos", - "rev": "0ae453f38d0f088c31d4678da3a12b183165986f", + "rev": "50b02bcba32b941d2ec48fedef68641702ca5b0f", "type": "github" }, "original": { @@ -227,11 +245,11 @@ ] }, "locked": { - "lastModified": 1761339987, - "narHash": "sha256-IUaawVwItZKi64IA6kF6wQCLCzpXbk2R46dHn8sHkig=", + "lastModified": 1758805352, + "narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "7cd9aac79ee2924a85c211d21fafd394b06a38de", + "rev": "c48e963a5558eb1c3827d59d21c5193622a1477c", "type": "github" }, "original": { @@ -263,16 +281,17 @@ }, "nix-vscode-extensions": { "inputs": { + "flake-utils": "flake-utils_3", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1761530505, - "narHash": "sha256-SbuUyC5pfTcMa9JUqSxFyGJpCqoUsB74tboS22+lByY=", + "lastModified": 1759369908, + "narHash": "sha256-IIhaE6jAge64z+fIyi/8Vtu0JdTtapbp4CvwiuIkZ1E=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "5a5496a7d21265e0ce7641452daf6c560f0eb7a9", + "rev": "a66ad2141b1440a838ead278c6edfe8a4ce75e6c", "type": "github" }, "original": { @@ -283,11 +302,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1760958188, - "narHash": "sha256-2m1S4jl+GEDtlt2QqeHil8Ny456dcGSKJAM7q3j/BFU=", + "lastModified": 1759261527, + "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "d6645c340ef7d821602fd2cd199e8d1eed10afbc", + "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", "type": "github" }, "original": { @@ -315,11 +334,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1761373498, - "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=", + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", "owner": "nixos", "repo": "nixpkgs", - "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", "type": "github" }, "original": { @@ -370,11 +389,11 @@ ] }, "locked": { - "lastModified": 1760998189, - "narHash": "sha256-ee2e1/AeGL5X8oy/HXsZQvZnae6XfEVdstGopKucYLY=", + "lastModified": 1759188042, + "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", "owner": "Mic92", "repo": "sops-nix", - "rev": "5a7d18b5c55642df5c432aadb757140edfeb70b3", + "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", "type": "github" }, "original": { @@ -412,6 +431,21 @@ "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 acff772..7ce24f2 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-hpWdfeuhYylO+SFD3BsKI0s/xtObCDd5OcuJ6i/aEuI="; + sha256 = "sha256-Oyx7AIdA/2mwBaq7UzXOoyq/z2SU2sViMN40sY2RCQw="; }; appimageContents = appimageTools.extractType2 { @@ -23,6 +23,9 @@ 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 29d3414..4c085a5 100644 --- a/modules/home-manager-modules/default.nix +++ b/modules/home-manager-modules/default.nix @@ -5,7 +5,6 @@ ./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 ab56189..8c70cf6 100644 --- a/modules/home-manager-modules/gnome.nix +++ b/modules/home-manager-modules/gnome.nix @@ -1,16 +1,8 @@ { 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 { @@ -42,7 +34,7 @@ in { ]; default = "blue"; }; - extraExtensions = lib.mkOption { + extensions = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; description = "The set of extensions to install and enable in the user environment."; @@ -68,80 +60,16 @@ in { })); 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 = extensions; + home.packages = config.gnome.extensions; dconf = { settings = lib.mkMerge [ { "org/gnome/shell" = { disable-user-extensions = false; # enables user extensions - enabled-extensions = builtins.map (extension: extension.extensionUuid) 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"; @@ -149,23 +77,7 @@ in { "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 @@ -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; - }) ]; }; }; diff --git a/modules/home-manager-modules/impermanence.nix b/modules/home-manager-modules/impermanence.nix deleted file mode 100644 index 6c75edd..0000000 --- a/modules/home-manager-modules/impermanence.nix +++ /dev/null @@ -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; - }; - }) - ]; -} diff --git a/modules/home-manager-modules/openssh.nix b/modules/home-manager-modules/openssh.nix index afc98dd..9d77d10 100644 --- a/modules/home-manager-modules/openssh.nix +++ b/modules/home-manager-modules/openssh.nix @@ -95,7 +95,7 @@ ); } ) - (lib.mkIf config.impermanence.enable { + (lib.mkIf osConfig.host.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 5c14068..b9b91c4 100644 --- a/modules/home-manager-modules/programs/bitwarden.nix +++ b/modules/home-manager-modules/programs/bitwarden.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.bitwarden = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 8ad5e63..00b248f 100644 --- a/modules/home-manager-modules/programs/bruno.nix +++ b/modules/home-manager-modules/programs/bruno.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.bruno = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 dbe6e2b..9e5f34e 100644 --- a/modules/home-manager-modules/programs/calibre.nix +++ b/modules/home-manager-modules/programs/calibre.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.calibre = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 6c4526f..00ba525 100644 --- a/modules/home-manager-modules/programs/davinci-resolve.nix +++ b/modules/home-manager-modules/programs/davinci-resolve.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.dataHome}/DaVinciResolve" diff --git a/modules/home-manager-modules/programs/dbeaver.nix b/modules/home-manager-modules/programs/dbeaver.nix index 8b6c41a..a962459 100644 --- a/modules/home-manager-modules/programs/dbeaver.nix +++ b/modules/home-manager-modules/programs/dbeaver.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.dataHome}/DBeaverData/" diff --git a/modules/home-manager-modules/programs/default.nix b/modules/home-manager-modules/programs/default.nix index 3fff489..68e5c71 100644 --- a/modules/home-manager-modules/programs/default.nix +++ b/modules/home-manager-modules/programs/default.nix @@ -12,13 +12,11 @@ ./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 @@ -26,7 +24,6 @@ ./mapillary-uploader.nix ./inkscape.nix ./gimp.nix - ./guild-wars-2.nix ./proxmark3.nix ./freecad.nix ./onionshare.nix @@ -36,14 +33,11 @@ ./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 d5d7192..e8605a5 100644 --- a/modules/home-manager-modules/programs/discord.nix +++ b/modules/home-manager-modules/programs/discord.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.discord = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 deleted file mode 100644 index faa69c6..0000000 --- a/modules/home-manager-modules/programs/dungeon-draft.nix +++ /dev/null @@ -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. - ''; - } - ]; - }; -} diff --git a/modules/home-manager-modules/programs/firefox.nix b/modules/home-manager-modules/programs/firefox.nix index 8841887..907b619 100644 --- a/modules/home-manager-modules/programs/firefox.nix +++ b/modules/home-manager-modules/programs/firefox.nix @@ -1,6 +1,7 @@ { lib, config, + osConfig, ... }: let buildProfilePersistence = profile: { @@ -25,7 +26,7 @@ allowOther = true; }; 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 ( ( lib.attrsets.mapAttrsToList diff --git a/modules/home-manager-modules/programs/freecad.nix b/modules/home-manager-modules/programs/freecad.nix index 89668de..ec17205 100644 --- a/modules/home-manager-modules/programs/freecad.nix +++ b/modules/home-manager-modules/programs/freecad.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.freecad = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 4440831..b29230d 100644 --- a/modules/home-manager-modules/programs/gdx-liftoff.nix +++ b/modules/home-manager-modules/programs/gdx-liftoff.nix @@ -2,6 +2,7 @@ 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 925a2d9..428068e 100644 --- a/modules/home-manager-modules/programs/gimp.nix +++ b/modules/home-manager-modules/programs/gimp.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.gimp = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 deleted file mode 100644 index 3f68ec6..0000000 --- a/modules/home-manager-modules/programs/guild-wars-2.nix +++ /dev/null @@ -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. - ''; - } - ]; - }; -} diff --git a/modules/home-manager-modules/programs/idea.nix b/modules/home-manager-modules/programs/idea.nix index e59e7b2..f0a928c 100644 --- a/modules/home-manager-modules/programs/idea.nix +++ b/modules/home-manager-modules/programs/idea.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ # configuration diff --git a/modules/home-manager-modules/programs/inkscape.nix b/modules/home-manager-modules/programs/inkscape.nix index a26ddec..facb08f 100644 --- a/modules/home-manager-modules/programs/inkscape.nix +++ b/modules/home-manager-modules/programs/inkscape.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.inkscape = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 deleted file mode 100644 index 05327d1..0000000 --- a/modules/home-manager-modules/programs/kdenlive.nix +++ /dev/null @@ -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; - }; - } - ) - ]); -} diff --git a/modules/home-manager-modules/programs/krita.nix b/modules/home-manager-modules/programs/krita.nix index 3ba5560..d662251 100644 --- a/modules/home-manager-modules/programs/krita.nix +++ b/modules/home-manager-modules/programs/krita.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.krita = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 93163e7..b61ea58 100644 --- a/modules/home-manager-modules/programs/libreoffice.nix +++ b/modules/home-manager-modules/programs/libreoffice.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.libreoffice = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 e92c3d3..eca059d 100644 --- a/modules/home-manager-modules/programs/makemkv.nix +++ b/modules/home-manager-modules/programs/makemkv.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.makemkv = { @@ -29,7 +30,7 @@ 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}" = { directories = [ ".MakeMKV" diff --git a/modules/home-manager-modules/programs/mapillary-uploader.nix b/modules/home-manager-modules/programs/mapillary-uploader.nix index df1f093..38c1144 100644 --- a/modules/home-manager-modules/programs/mapillary-uploader.nix +++ b/modules/home-manager-modules/programs/mapillary-uploader.nix @@ -11,20 +11,7 @@ in { enable = mkEnableOption "Mapillary Desktop 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; - }; - } - ) - ]); + config = mkIf cfg.enable { + home.packages = [pkgs.mapillary-uploader]; + }; } diff --git a/modules/home-manager-modules/programs/mfoc.nix b/modules/home-manager-modules/programs/mfoc.nix index 6006c9b..7b92007 100644 --- a/modules/home-manager-modules/programs/mfoc.nix +++ b/modules/home-manager-modules/programs/mfoc.nix @@ -2,6 +2,7 @@ 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 4b42638..c53e3a9 100644 --- a/modules/home-manager-modules/programs/noisetorch.nix +++ b/modules/home-manager-modules/programs/noisetorch.nix @@ -2,6 +2,7 @@ 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 bfdba90..98c4fea 100644 --- a/modules/home-manager-modules/programs/obs.nix +++ b/modules/home-manager-modules/programs/obs.nix @@ -1,17 +1,13 @@ { lib, config, + osConfig, ... }: { config = lib.mkIf config.programs.obs-studio.enable (lib.mkMerge [ ( - lib.mkIf config.impermanence.enable { - home.persistence."/persist${config.home.homeDirectory}" = { - directories = [ - "${config.xdg.configHome}/obs-studio" - ]; - allowOther = true; - }; + lib.mkIf osConfig.host.impermanence.enable { + # TODO: map impermanence for obs } ) ]); diff --git a/modules/home-manager-modules/programs/obsidian.nix b/modules/home-manager-modules/programs/obsidian.nix index 824563d..4d28b3e 100644 --- a/modules/home-manager-modules/programs/obsidian.nix +++ b/modules/home-manager-modules/programs/obsidian.nix @@ -1,11 +1,12 @@ { lib, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.configHome}/obsidian" diff --git a/modules/home-manager-modules/programs/olympus.nix b/modules/home-manager-modules/programs/olympus.nix deleted file mode 100644 index 0e38eec..0000000 --- a/modules/home-manager-modules/programs/olympus.nix +++ /dev/null @@ -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; - }; - } - ) - ]); -} diff --git a/modules/home-manager-modules/programs/onionshare.nix b/modules/home-manager-modules/programs/onionshare.nix index 475f993..ed1903d 100644 --- a/modules/home-manager-modules/programs/onionshare.nix +++ b/modules/home-manager-modules/programs/onionshare.nix @@ -2,6 +2,7 @@ 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 c9d5e14..0260c91 100644 --- a/modules/home-manager-modules/programs/openrgb.nix +++ b/modules/home-manager-modules/programs/openrgb.nix @@ -2,27 +2,16 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.openrgb = { enable = lib.mkEnableOption "enable 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; - }; - } - ) - ]); + config = lib.mkIf config.programs.openrgb.enable { + home.packages = with pkgs; [ + openrgb + ]; + }; } diff --git a/modules/home-manager-modules/programs/openvpn.nix b/modules/home-manager-modules/programs/openvpn.nix index dcd499c..814c16d 100644 --- a/modules/home-manager-modules/programs/openvpn.nix +++ b/modules/home-manager-modules/programs/openvpn.nix @@ -2,6 +2,7 @@ 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 9246efd..d4e33b5 100644 --- a/modules/home-manager-modules/programs/pdfarranger.nix +++ b/modules/home-manager-modules/programs/pdfarranger.nix @@ -2,6 +2,7 @@ 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 bc37b86..d2c1fe2 100644 --- a/modules/home-manager-modules/programs/picard.nix +++ b/modules/home-manager-modules/programs/picard.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.picard = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 3ed25fd..ec0d887 100644 --- a/modules/home-manager-modules/programs/piper.nix +++ b/modules/home-manager-modules/programs/piper.nix @@ -2,6 +2,7 @@ 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 d0aea2a..a7004bd 100644 --- a/modules/home-manager-modules/programs/polycule.nix +++ b/modules/home-manager-modules/programs/polycule.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.polycule = { @@ -16,7 +17,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 5345169..9e6088f 100644 --- a/modules/home-manager-modules/programs/prostudiomasters.nix +++ b/modules/home-manager-modules/programs/prostudiomasters.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.prostudiomasters = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 513a610..dd11aae 100644 --- a/modules/home-manager-modules/programs/protonvpn.nix +++ b/modules/home-manager-modules/programs/protonvpn.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.configHome}/protonvpn" diff --git a/modules/home-manager-modules/programs/proxmark3.nix b/modules/home-manager-modules/programs/proxmark3.nix index 656be19..ad1e298 100644 --- a/modules/home-manager-modules/programs/proxmark3.nix +++ b/modules/home-manager-modules/programs/proxmark3.nix @@ -2,6 +2,7 @@ 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 61d13c0..02e23df 100644 --- a/modules/home-manager-modules/programs/qbittorrent.nix +++ b/modules/home-manager-modules/programs/qbittorrent.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.qbittorrent = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 8b42766..abc2442 100644 --- a/modules/home-manager-modules/programs/qflipper.nix +++ b/modules/home-manager-modules/programs/qflipper.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.qflipper = { @@ -15,7 +16,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 7db23a7..fdf0af9 100644 --- a/modules/home-manager-modules/programs/signal.nix +++ b/modules/home-manager-modules/programs/signal.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.configHome}/Signal" diff --git a/modules/home-manager-modules/programs/steam.nix b/modules/home-manager-modules/programs/steam.nix index fd98cb6..4661151 100644 --- a/modules/home-manager-modules/programs/steam.nix +++ b/modules/home-manager-modules/programs/steam.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.steam = { @@ -17,7 +18,7 @@ ]; } ( - lib.mkIf config.impermanence.enable { + lib.mkIf osConfig.host.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 c3b085d..2c58578 100644 --- a/modules/home-manager-modules/programs/tor-browser.nix +++ b/modules/home-manager-modules/programs/tor-browser.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { 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 ef6a881..5b52cd6 100644 --- a/modules/home-manager-modules/programs/ungoogled-chromium.nix +++ b/modules/home-manager-modules/programs/ungoogled-chromium.nix @@ -2,6 +2,7 @@ lib, pkgs, config, + osConfig, ... }: { 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}" = { directories = [ "${config.xdg.configHome}/chromium" diff --git a/modules/home-manager-modules/programs/via.nix b/modules/home-manager-modules/programs/via.nix index 0aa58e4..0b79452 100644 --- a/modules/home-manager-modules/programs/via.nix +++ b/modules/home-manager-modules/programs/via.nix @@ -2,28 +2,16 @@ lib, pkgs, config, + osConfig, ... }: { options.programs.via = { enable = lib.mkEnableOption "enable 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; - }; - } - ) - ]); + config = lib.mkIf config.programs.via.enable { + home.packages = with pkgs; [ + via + ]; + }; } diff --git a/modules/home-manager-modules/programs/vmware-workstation.nix b/modules/home-manager-modules/programs/vmware-workstation.nix deleted file mode 100644 index 8e9d406..0000000 --- a/modules/home-manager-modules/programs/vmware-workstation.nix +++ /dev/null @@ -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; - }; - } - ) - ] - ); -} diff --git a/modules/home-manager-modules/programs/vortex.nix b/modules/home-manager-modules/programs/vortex.nix deleted file mode 100644 index cb86526..0000000 --- a/modules/home-manager-modules/programs/vortex.nix +++ /dev/null @@ -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. - ''; - } - ]; - }; -} diff --git a/modules/home-manager-modules/programs/vscode/default.nix b/modules/home-manager-modules/programs/vscode/default.nix index f9d83dc..85f4a62 100644 --- a/modules/home-manager-modules/programs/vscode/default.nix +++ b/modules/home-manager-modules/programs/vscode/default.nix @@ -16,7 +16,6 @@ ./go.nix ./evenBetterToml.nix ./openRemoteSsh.nix - ./rustAnalyzer.nix ./astroVscode.nix ./vscodeMdx.nix ./claudeDev.nix @@ -24,6 +23,5 @@ ./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 deleted file mode 100644 index f1f6215..0000000 --- a/modules/home-manager-modules/programs/vscode/openDyslexicFont.nix +++ /dev/null @@ -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; - }; -} diff --git a/modules/home-manager-modules/programs/vscode/rustAnalyzer.nix b/modules/home-manager-modules/programs/vscode/rustAnalyzer.nix deleted file mode 100644 index 66e9ebe..0000000 --- a/modules/home-manager-modules/programs/vscode/rustAnalyzer.nix +++ /dev/null @@ -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 - ]; - }; - })); - }; -} diff --git a/modules/nixos-modules/server/actual/actual.nix b/modules/nixos-modules/server/actual/actual.nix deleted file mode 100644 index 4cca449..0000000 --- a/modules/nixos-modules/server/actual/actual.nix +++ /dev/null @@ -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; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/actual/const.nix b/modules/nixos-modules/server/actual/const.nix index 14b715e..13b068e 100644 --- a/modules/nixos-modules/server/actual/const.nix +++ b/modules/nixos-modules/server/actual/const.nix @@ -1,3 +1,3 @@ { - dataDirectory = "/var/lib/private/actual"; + dataDirectory = "/var/lib/actual/"; } diff --git a/modules/nixos-modules/server/actual/default.nix b/modules/nixos-modules/server/actual/default.nix index b59517b..546240e 100644 --- a/modules/nixos-modules/server/actual/default.nix +++ b/modules/nixos-modules/server/actual/default.nix @@ -1,8 +1,26 @@ { + lib, + config, + ... +}: let + const = import ./const.nix; + dataDirectory = const.dataDirectory; +in { imports = [ - ./actual.nix ./proxy.nix ./fail2ban.nix ./impermanence.nix ]; + + config = lib.mkIf config.services.actual.enable { + systemd.tmpfiles.rules = [ + "d ${dataDirectory} 2770 actual actual" + ]; + + services.actual = { + settings = { + ACTUAL_DATA_DIR = dataDirectory; + }; + }; + }; } diff --git a/modules/nixos-modules/server/actual/impermanence.nix b/modules/nixos-modules/server/actual/impermanence.nix index d870789..5eee95a 100644 --- a/modules/nixos-modules/server/actual/impermanence.nix +++ b/modules/nixos-modules/server/actual/impermanence.nix @@ -6,22 +6,11 @@ const = import ./const.nix; dataDirectory = const.dataDirectory; in { - options.services.actual = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.actual.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.actual.impermanence.enable { + config = lib.mkIf (config.services.actual.enable && config.host.impermanence.enable) { assertions = [ { - assertion = config.services.actual.settings.dataDir == dataDirectory; - message = "actual data location does not match persistence\nconfig directory: ${config.services.actual.settings.dataDir}\npersistence directory: ${dataDirectory}"; - } - { - assertion = config.systemd.services.actual.serviceConfig.DynamicUser or false; - message = "actual systemd service must have DynamicUser enabled to use private directory"; + assertion = config.services.actual.settings.ACTUAL_DATA_DIR == dataDirectory; + message = "actual data location does not match persistence"; } ]; environment.persistence."/persist/system/root" = { diff --git a/modules/nixos-modules/server/actual/proxy.nix b/modules/nixos-modules/server/actual/proxy.nix index 9d37574..6ca51e4 100644 --- a/modules/nixos-modules/server/actual/proxy.nix +++ b/modules/nixos-modules/server/actual/proxy.nix @@ -4,30 +4,17 @@ ... }: { options.services.actual = { - domain = lib.mkOption { + subdomain = lib.mkOption { type = lib.types.str; - description = "domain that actual will be hosted at"; - default = "actual.arpa"; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for actual"; - default = []; - }; - reverseProxy.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.actual.enable && config.services.reverseProxy.enable; + default = "actual"; + description = "subdomain of base domain that actual will be hosted at"; }; }; - config = lib.mkIf config.services.actual.reverseProxy.enable { - services.reverseProxy.services.actual = { - target = "http://localhost:${toString config.services.actual.settings.port}"; - domain = config.services.actual.domain; - extraDomains = config.services.actual.extraDomains; - - settings = { - forwardHeaders.enable = true; + config = lib.mkIf (config.services.actual.enable && config.host.reverse_proxy.enable) { + host = { + reverse_proxy.subdomains.${config.services.actual.subdomain} = { + target = "http://localhost:${toString config.services.actual.settings.port}"; }; }; }; diff --git a/modules/nixos-modules/server/bazarr/default.nix b/modules/nixos-modules/server/bazarr/default.nix index 86dbb4b..f39d940 100644 --- a/modules/nixos-modules/server/bazarr/default.nix +++ b/modules/nixos-modules/server/bazarr/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ + ./proxy.nix ./impermanence.nix ]; } diff --git a/modules/nixos-modules/server/bazarr/impermanence.nix b/modules/nixos-modules/server/bazarr/impermanence.nix index 70a45d1..22fb0e6 100644 --- a/modules/nixos-modules/server/bazarr/impermanence.nix +++ b/modules/nixos-modules/server/bazarr/impermanence.nix @@ -5,14 +5,7 @@ }: let bazarr_data_directory = "/var/lib/bazarr"; in { - options.services.bazarr = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.bazarr.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.bazarr.impermanence.enable { + config = lib.mkIf (config.services.bazarr.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.bazarr.dataDir == bazarr_data_directory; diff --git a/modules/nixos-modules/server/bazarr/proxy.nix b/modules/nixos-modules/server/bazarr/proxy.nix new file mode 100644 index 0000000..fe310d8 --- /dev/null +++ b/modules/nixos-modules/server/bazarr/proxy.nix @@ -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; + }; + }; +} diff --git a/modules/nixos-modules/server/crab-hole/crab-hole.nix b/modules/nixos-modules/server/crab-hole/crab-hole.nix deleted file mode 100644 index d76323a..0000000 --- a/modules/nixos-modules/server/crab-hole/crab-hole.nix +++ /dev/null @@ -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]; - }) - ]; - }; -} diff --git a/modules/nixos-modules/server/crab-hole/default.nix b/modules/nixos-modules/server/crab-hole/default.nix deleted file mode 100644 index 158a851..0000000 --- a/modules/nixos-modules/server/crab-hole/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - 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 deleted file mode 100644 index 51efc0c..0000000 --- a/modules/nixos-modules/server/crab-hole/impermanence.nix +++ /dev/null @@ -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"; - } - ]; - }; - }; -} diff --git a/modules/nixos-modules/server/default.nix b/modules/nixos-modules/server/default.nix index 2b33089..e550123 100644 --- a/modules/nixos-modules/server/default.nix +++ b/modules/nixos-modules/server/default.nix @@ -1,23 +1,20 @@ {...}: { imports = [ - ./reverseProxy - ./fail2ban - ./postgres + ./reverse_proxy.nix + ./fail2ban.nix + ./postgres.nix ./network_storage + ./podman.nix ./actual ./bazarr - ./crab-hole - ./flaresolverr ./forgejo ./home-assistant ./immich - ./jackett ./jellyfin - ./lidarr ./panoramax ./paperless - ./qbittorent + ./qbittorent.nix ./radarr ./searx ./sonarr diff --git a/modules/nixos-modules/server/fail2ban.nix b/modules/nixos-modules/server/fail2ban.nix new file mode 100644 index 0000000..d19aeeb --- /dev/null +++ b/modules/nixos-modules/server/fail2ban.nix @@ -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: " + '') + ); + }; + + 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"; + } + ]; + }; + }) + ]); +} diff --git a/modules/nixos-modules/server/fail2ban/default.nix b/modules/nixos-modules/server/fail2ban/default.nix deleted file mode 100644 index 30fca99..0000000 --- a/modules/nixos-modules/server/fail2ban/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./fail2ban.nix - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/fail2ban/fail2ban.nix b/modules/nixos-modules/server/fail2ban/fail2ban.nix deleted file mode 100644 index 261c68f..0000000 --- a/modules/nixos-modules/server/fail2ban/fail2ban.nix +++ /dev/null @@ -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: " - '') - ); - }; - - 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 {}; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/fail2ban/impermanence.nix b/modules/nixos-modules/server/fail2ban/impermanence.nix deleted file mode 100644 index 6e214b3..0000000 --- a/modules/nixos-modules/server/fail2ban/impermanence.nix +++ /dev/null @@ -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"; - } - ]; - }; - }; -} diff --git a/modules/nixos-modules/server/flaresolverr/default.nix b/modules/nixos-modules/server/flaresolverr/default.nix deleted file mode 100644 index 86dbb4b..0000000 --- a/modules/nixos-modules/server/flaresolverr/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{...}: { - imports = [ - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/flaresolverr/impermanence.nix b/modules/nixos-modules/server/flaresolverr/impermanence.nix deleted file mode 100644 index 4544e75..0000000 --- a/modules/nixos-modules/server/flaresolverr/impermanence.nix +++ /dev/null @@ -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"; - } - ]; - }; - }; -} diff --git a/modules/nixos-modules/server/forgejo/database.nix b/modules/nixos-modules/server/forgejo/database.nix index bb8781c..0417aab 100644 --- a/modules/nixos-modules/server/forgejo/database.nix +++ b/modules/nixos-modules/server/forgejo/database.nix @@ -2,31 +2,40 @@ lib, config, ... -}: let - usingPostgres = config.services.forgejo.database.type == "postgres"; -in { - config = lib.mkIf config.services.forgejo.enable { - assertions = [ +}: { + config = lib.mkIf config.services.forgejo.enable ( + lib.mkMerge [ { - assertion = !usingPostgres || config.services.postgresql.enable; - message = "PostgreSQL must be enabled when Forgejo database type is postgres"; - } - { - assertion = !(usingPostgres && config.services.forgejo.database.createDatabase) || (builtins.any (db: db == "forgejo") config.services.postgresql.ensureDatabases); - message = "Forgejo built-in database creation failed - expected 'forgejo' in ensureDatabases but got: ${builtins.toString config.services.postgresql.ensureDatabases}"; - } - { - assertion = !(usingPostgres && config.services.forgejo.database.createDatabase) || (builtins.any (user: user.name == "forgejo") config.services.postgresql.ensureUsers); - message = "Forgejo built-in user creation failed - expected user 'forgejo' in ensureUsers but got: ${builtins.toString (builtins.map (u: u.name) config.services.postgresql.ensureUsers)}"; - } - ]; + host = { + postgres = { + enable = true; + }; + }; - services.forgejo.database.createDatabase = lib.mkDefault usingPostgres; - - systemd.services.forgejo = lib.mkIf usingPostgres { - requires = [ - config.systemd.services.postgresql.name - ]; - }; - }; + assertions = [ + { + assertion = config.services.forgejo.settings.database.DB_TYPE == "postgres"; + message = "Forgejo database type must be postgres"; + } + ]; + } + (lib.mkIf config.host.postgres.enable { + host = { + postgres = { + extraUsers = { + forgejo = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + forgejo = { + name = "forgejo"; + }; + }; + }; + }; + }) + ] + ); } diff --git a/modules/nixos-modules/server/forgejo/default.nix b/modules/nixos-modules/server/forgejo/default.nix index 4333f69..1fdc8d9 100644 --- a/modules/nixos-modules/server/forgejo/default.nix +++ b/modules/nixos-modules/server/forgejo/default.nix @@ -1,9 +1,53 @@ { + lib, + config, + ... +}: let + const = import ./const.nix; + httpPort = const.httpPort; + sshPort = const.sshPort; + db_user = "forgejo"; +in { imports = [ - ./forgejo.nix ./proxy.nix ./database.nix ./fail2ban.nix ./impermanence.nix ]; + + config = lib.mkIf config.services.forgejo.enable { + assertions = [ + { + assertion = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER == config.users.users.git.name; + message = "Forgejo BUILTIN_SSH_SERVER_USER hardcoded value does not match expected git user name"; + } + ]; + + services.forgejo = { + database = { + type = "postgres"; + socket = "/run/postgresql"; + }; + lfs.enable = true; + settings = { + server = { + DOMAIN = "${config.services.forgejo.subdomain}.${config.host.reverse_proxy.hostname}"; + HTTP_PORT = httpPort; + START_SSH_SERVER = true; + SSH_LISTEN_PORT = sshPort; + SSH_PORT = 22; + BUILTIN_SSH_SERVER_USER = "git"; + ROOT_URL = "https://git.jan-leila.com"; + }; + service = { + DISABLE_REGISTRATION = true; + }; + database = { + DB_TYPE = "postgres"; + NAME = db_user; + USER = db_user; + }; + }; + }; + }; } diff --git a/modules/nixos-modules/server/forgejo/fail2ban.nix b/modules/nixos-modules/server/forgejo/fail2ban.nix index dfe221a..213c804 100644 --- a/modules/nixos-modules/server/forgejo/fail2ban.nix +++ b/modules/nixos-modules/server/forgejo/fail2ban.nix @@ -4,16 +4,7 @@ pkgs, ... }: { - options.services.forgejo = { - fail2ban = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.forgejo.enable && config.services.fail2ban.enable; - }; - }; - }; - - config = lib.mkIf config.services.forgejo.fail2ban.enable { + config = lib.mkIf (config.services.forgejo.enable && config.services.fail2ban.enable) { environment.etc = { "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( pkgs.lib.mkDefault (pkgs.lib.mkAfter '' diff --git a/modules/nixos-modules/server/forgejo/forgejo.nix b/modules/nixos-modules/server/forgejo/forgejo.nix deleted file mode 100644 index 70d3087..0000000 --- a/modules/nixos-modules/server/forgejo/forgejo.nix +++ /dev/null @@ -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; - }; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/forgejo/impermanence.nix b/modules/nixos-modules/server/forgejo/impermanence.nix index 6fe3de8..04f21a5 100644 --- a/modules/nixos-modules/server/forgejo/impermanence.nix +++ b/modules/nixos-modules/server/forgejo/impermanence.nix @@ -5,14 +5,7 @@ }: let stateDir = "/var/lib/forgejo"; in { - options.services.forgejo = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.forgejo.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.forgejo.impermanence.enable { + config = lib.mkIf (config.services.forgejo.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.forgejo.stateDir == stateDir; diff --git a/modules/nixos-modules/server/forgejo/proxy.nix b/modules/nixos-modules/server/forgejo/proxy.nix index c2d3131..51f769d 100644 --- a/modules/nixos-modules/server/forgejo/proxy.nix +++ b/modules/nixos-modules/server/forgejo/proxy.nix @@ -7,33 +7,16 @@ httpPort = const.httpPort; in { options.services.forgejo = { - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.forgejo.enable && config.services.reverseProxy.enable; - }; - domain = lib.mkOption { - type = lib.types.str; - description = "domain that forgejo will be hosted at"; - default = "git.jan-leila.com"; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for forgejo"; - default = []; - }; + subdomain = lib.mkOption { + type = lib.types.str; + description = "subdomain of base domain that forgejo will be hosted at"; + default = "forgejo"; }; }; - config = lib.mkIf config.services.forgejo.reverseProxy.enable { - services.reverseProxy.services.forgejo = { + config = lib.mkIf (config.services.forgejo.enable && config.host.reverse_proxy.enable) { + host.reverse_proxy.subdomains.${config.services.forgejo.subdomain} = { target = "http://localhost:${toString httpPort}"; - domain = config.services.forgejo.reverseProxy.domain; - extraDomains = config.services.forgejo.reverseProxy.extraDomains; - - settings = { - forwardHeaders.enable = true; - }; }; networking.firewall.allowedTCPPorts = [ diff --git a/modules/nixos-modules/server/home-assistant/database.nix b/modules/nixos-modules/server/home-assistant/database.nix index f1927ed..0ac8002 100644 --- a/modules/nixos-modules/server/home-assistant/database.nix +++ b/modules/nixos-modules/server/home-assistant/database.nix @@ -2,52 +2,55 @@ lib, config, ... -}: { - options.services.home-assistant = { - postgres = { - enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Use PostgreSQL instead of SQLite"; - }; - user = lib.mkOption { - type = lib.types.str; - default = "hass"; - description = "Database user name"; - }; - database = lib.mkOption { - type = lib.types.str; - default = "hass"; - description = "Database name"; - }; - }; - }; - - config = lib.mkIf config.services.home-assistant.enable { - assertions = [ +}: let + dbUser = "hass"; +in { + config = lib.mkIf config.services.home-assistant.enable ( + lib.mkMerge [ { - assertion = !config.services.home-assistant.postgres.enable || config.services.postgresql.enable; - message = "PostgreSQL must be enabled when using postgres database for Home Assistant"; - } - ]; + host = { + postgres = { + enable = true; + }; + }; - services.postgresql.databases.home-assistant = lib.mkIf config.services.home-assistant.postgres.enable { - enable = true; - user = config.services.home-assistant.postgres.user; - database = config.services.home-assistant.postgres.database; - }; - - services.home-assistant = lib.mkIf config.services.home-assistant.postgres.enable { - extraPackages = python3Packages: - with python3Packages; [ - psycopg2 + assertions = [ + { + assertion = config.services.home-assistant.database == "postgres"; + message = "Home Assistant database type must be postgres"; + } ]; - }; + } + (lib.mkIf config.host.postgres.enable { + host = { + postgres = { + extraUsers = { + ${dbUser} = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${dbUser} = { + name = dbUser; + }; + }; + }; + }; - systemd.services.home-assistant = lib.mkIf config.services.home-assistant.postgres.enable { - requires = [ - config.systemd.services.postgresql.name - ]; - }; - }; + services.home-assistant = { + extraPackages = python3Packages: + with python3Packages; [ + psycopg2 + ]; + }; + + systemd.services.home-assistant = { + requires = [ + config.systemd.services.postgresql.name + ]; + }; + }) + ] + ); } diff --git a/modules/nixos-modules/server/home-assistant/default.nix b/modules/nixos-modules/server/home-assistant/default.nix index b6f9356..83d8ba7 100644 --- a/modules/nixos-modules/server/home-assistant/default.nix +++ b/modules/nixos-modules/server/home-assistant/default.nix @@ -1,10 +1,112 @@ { + lib, + config, + ... +}: { imports = [ - ./home-assistant.nix ./proxy.nix ./database.nix ./fail2ban.nix ./impermanence.nix ./extensions ]; + + options.services.home-assistant = { + database = lib.mkOption { + type = lib.types.enum [ + "builtin" + "postgres" + ]; + description = "what database do we want to use"; + default = "builtin"; + }; + + extensions = { + sonos = { + enable = lib.mkEnableOption "enable the sonos plugin"; + port = lib.mkOption { + type = lib.types.int; + default = 1400; + description = "what port to use for sonos discovery"; + }; + }; + jellyfin = { + enable = lib.mkEnableOption "enable the jellyfin plugin"; + }; + wyoming = { + enable = lib.mkEnableOption "enable wyoming"; + }; + }; + }; + + config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [ + { + services.home-assistant = { + configDir = "/var/lib/hass"; + extraComponents = [ + "default_config" + "esphome" + "met" + "radio_browser" + "isal" + "zha" + "webostv" + "tailscale" + "syncthing" + "analytics_insights" + "unifi" + "openweathermap" + "ollama" + "mobile_app" + "logbook" + "ssdp" + "usb" + "webhook" + "bluetooth" + "dhcp" + "energy" + "history" + "backup" + "assist_pipeline" + "conversation" + "sun" + "zeroconf" + "cpuspeed" + ]; + config = { + http = { + server_port = 8123; + use_x_forwarded_for = true; + trusted_proxies = ["127.0.0.1" "::1"]; + ip_ban_enabled = true; + login_attempts_threshold = 10; + }; + homeassistant = { + external_url = "https://${config.services.home-assistant.subdomain}.${config.host.reverse_proxy.hostname}"; + # internal_url = "http://192.168.1.2:8123"; + }; + recorder.db_url = "postgresql://@/${config.services.home-assistant.configDir}"; + "automation manual" = []; + "automation ui" = "!include automations.yaml"; + mobile_app = {}; + }; + extraPackages = python3Packages: + with python3Packages; [ + hassil + numpy + gtts + ]; + }; + + # TODO: configure /var/lib/hass/secrets.yaml via sops + + networking.firewall.allowedUDPPorts = [ + 1900 + ]; + + systemd.tmpfiles.rules = [ + "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" + ]; + } + ]); } diff --git a/modules/nixos-modules/server/home-assistant/fail2ban.nix b/modules/nixos-modules/server/home-assistant/fail2ban.nix index 25194ef..6ac5900 100644 --- a/modules/nixos-modules/server/home-assistant/fail2ban.nix +++ b/modules/nixos-modules/server/home-assistant/fail2ban.nix @@ -3,46 +3,36 @@ pkgs, config, ... -}: { - options.services.home-assistant = { - fail2ban = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.fail2ban.enable && config.services.home-assistant.enable; - }; - }; +}: +lib.mkIf (config.services.fail2ban.enable && config.services.home-assistant.enable) { + environment.etc = { + "fail2ban/filter.d/hass.local".text = ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [INCLUDES] + before = common.conf + + [Definition] + failregex = ^%(__prefix_line)s.*Login attempt or request with invalid authentication from .*$ + + ignoreregex = + + [Init] + datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S + '') + ); }; - config = lib.mkIf config.services.home-assistant.fail2ban.enable { - environment.etc = { - "fail2ban/filter.d/hass.local".text = ( - pkgs.lib.mkDefault (pkgs.lib.mkAfter '' - [INCLUDES] - before = common.conf - - [Definition] - failregex = ^%(__prefix_line)s.*Login attempt or request with invalid authentication from .*$ - - ignoreregex = - - [Init] - datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S - '') - ); - }; - - services.fail2ban = { - jails = { - home-assistant-iptables.settings = { - enabled = true; - filter = "hass"; - action = ''iptables-multiport[name=HTTP, port="http,https"]''; - logpath = "${config.services.home-assistant.configDir}/*.log"; - backend = "auto"; - findtime = 600; - bantime = 600; - maxretry = 5; - }; + services.fail2ban = { + jails = { + home-assistant-iptables.settings = { + enabled = true; + filter = "hass"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.home-assistant.configDir}/*.log"; + backend = "auto"; + findtime = 600; + bantime = 600; + maxretry = 5; }; }; }; diff --git a/modules/nixos-modules/server/home-assistant/home-assistant.nix b/modules/nixos-modules/server/home-assistant/home-assistant.nix deleted file mode 100644 index fa58d5e..0000000 --- a/modules/nixos-modules/server/home-assistant/home-assistant.nix +++ /dev/null @@ -1,104 +0,0 @@ -{ - lib, - config, - ... -}: { - options.services.home-assistant = { - database = lib.mkOption { - type = lib.types.enum [ - "builtin" - "postgres" - ]; - description = "what database do we want to use"; - default = "builtin"; - }; - - extensions = { - sonos = { - enable = lib.mkEnableOption "enable the sonos plugin"; - port = lib.mkOption { - type = lib.types.int; - default = 1400; - description = "what port to use for sonos discovery"; - }; - }; - jellyfin = { - enable = lib.mkEnableOption "enable the jellyfin plugin"; - }; - wyoming = { - enable = lib.mkEnableOption "enable wyoming"; - }; - }; - }; - - config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [ - { - services.home-assistant = { - configDir = "/var/lib/hass"; - extraComponents = [ - "default_config" - "esphome" - "met" - "radio_browser" - "isal" - "zha" - "webostv" - "tailscale" - "syncthing" - "analytics_insights" - "unifi" - "openweathermap" - "ollama" - "mobile_app" - "logbook" - "ssdp" - "usb" - "webhook" - "bluetooth" - "dhcp" - "energy" - "history" - "backup" - "assist_pipeline" - "conversation" - "sun" - "zeroconf" - "cpuspeed" - ]; - config = { - http = { - server_port = 8123; - use_x_forwarded_for = true; - trusted_proxies = ["127.0.0.1" "::1"]; - ip_ban_enabled = true; - login_attempts_threshold = 10; - }; - homeassistant = { - external_url = "https://${config.services.home-assistant.domain}"; - # internal_url = "http://192.168.1.2:8123"; - }; - recorder.db_url = "postgresql://@/${config.services.home-assistant.configDir}"; - "automation manual" = []; - "automation ui" = "!include automations.yaml"; - mobile_app = {}; - }; - extraPackages = python3Packages: - with python3Packages; [ - hassil - numpy - gtts - ]; - }; - - # TODO: configure /var/lib/hass/secrets.yaml via sops - - networking.firewall.allowedUDPPorts = [ - 1900 - ]; - - systemd.tmpfiles.rules = [ - "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" - ]; - } - ]); -} diff --git a/modules/nixos-modules/server/home-assistant/proxy.nix b/modules/nixos-modules/server/home-assistant/proxy.nix index b756459..ba8f20d 100644 --- a/modules/nixos-modules/server/home-assistant/proxy.nix +++ b/modules/nixos-modules/server/home-assistant/proxy.nix @@ -4,39 +4,29 @@ ... }: { options.services.home-assistant = { - domain = lib.mkOption { + subdomain = lib.mkOption { type = lib.types.str; - description = "domain that home-assistant will be hosted at"; - default = "home-assistant.arpa"; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for home-assistant"; - default = []; - }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.reverseProxy.enable && config.services.home-assistant.enable; - }; + description = "subdomain of base domain that home-assistant will be hosted at"; + default = "home-assistant"; }; }; - config = lib.mkIf config.services.home-assistant.reverseProxy.enable { - services.reverseProxy.services.home-assistant = { - target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; - domain = config.services.home-assistant.domain; - extraDomains = config.services.home-assistant.extraDomains; + config = lib.mkIf (config.host.reverse_proxy.enable && config.services.home-assistant.enable) { + host = { + reverse_proxy.subdomains.${config.services.home-assistant.subdomain} = { + target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; - settings = { - proxyWebsockets.enable = true; + websockets.enable = true; forwardHeaders.enable = true; - # Custom timeout settings - proxyHeaders = { - enable = true; - timeout = 90; - }; + extraConfig = '' + add_header Upgrade $http_upgrade; + add_header Connection \"upgrade\"; + + proxy_buffering off; + + proxy_read_timeout 90; + ''; }; }; }; diff --git a/modules/nixos-modules/server/immich/database.nix b/modules/nixos-modules/server/immich/database.nix index 52af51e..74b1aaa 100644 --- a/modules/nixos-modules/server/immich/database.nix +++ b/modules/nixos-modules/server/immich/database.nix @@ -3,28 +3,24 @@ config, ... }: { - config = lib.mkIf config.services.immich.enable { - assertions = [ - { - assertion = !config.services.immich.database.enable || config.services.postgresql.enable; - message = "PostgreSQL must be enabled when using postgres database for Immich"; - } - { - assertion = !(config.services.immich.database.enable && config.services.immich.database.createDB) || (builtins.any (db: db == "immich") config.services.postgresql.ensureDatabases); - message = "Immich built-in database creation failed - expected 'immich' in ensureDatabases but got: ${builtins.toString config.services.postgresql.ensureDatabases}"; - } - { - assertion = !(config.services.immich.database.enable && config.services.immich.database.createDB) || (builtins.any (user: user.name == "immich") config.services.postgresql.ensureUsers); - message = "Immich built-in user creation failed - expected user 'immich' in ensureUsers but got: ${builtins.toString (builtins.map (u: u.name) config.services.postgresql.ensureUsers)}"; - } - ]; - - # Note: Immich has built-in database creation via services.immich.database.createDB we only add the systemd dependency - - systemd.services.immich-server = lib.mkIf config.services.immich.database.enable { - requires = [ - config.systemd.services.postgresql.name - ]; - }; - }; + config = lib.mkIf config.services.immich.enable (lib.mkMerge [ + { + host = { + postgres = { + enable = true; + }; + }; + } + (lib.mkIf config.host.postgres.enable { + host = { + postgres = { + extraUsers = { + ${config.services.immich.database.user} = { + isClient = true; + }; + }; + }; + }; + }) + ]); } diff --git a/modules/nixos-modules/server/immich/fail2ban.nix b/modules/nixos-modules/server/immich/fail2ban.nix index 21593e7..c9ec87b 100644 --- a/modules/nixos-modules/server/immich/fail2ban.nix +++ b/modules/nixos-modules/server/immich/fail2ban.nix @@ -4,16 +4,7 @@ pkgs, ... }: { - options.services.immich = { - fail2ban = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.fail2ban.enable && config.services.immich.enable; - }; - }; - }; - - config = lib.mkIf config.services.immich.fail2ban.enable { + config = lib.mkIf (config.services.fail2ban.enable && config.services.immich.enable) { environment.etc = { "fail2ban/filter.d/immich.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter '' [Definition] diff --git a/modules/nixos-modules/server/immich/impermanence.nix b/modules/nixos-modules/server/immich/impermanence.nix index 56e51d0..f63d178 100644 --- a/modules/nixos-modules/server/immich/impermanence.nix +++ b/modules/nixos-modules/server/immich/impermanence.nix @@ -5,14 +5,7 @@ }: let mediaLocation = "/var/lib/immich"; in { - options.services.immich = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.immich.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.immich.impermanence.enable { + config = lib.mkIf (config.services.immich.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.immich.mediaLocation == mediaLocation; diff --git a/modules/nixos-modules/server/immich/proxy.nix b/modules/nixos-modules/server/immich/proxy.nix index 9c8c165..dae2420 100644 --- a/modules/nixos-modules/server/immich/proxy.nix +++ b/modules/nixos-modules/server/immich/proxy.nix @@ -4,40 +4,31 @@ ... }: { options.services.immich = { - domain = lib.mkOption { + subdomain = lib.mkOption { type = lib.types.str; - description = "domain that immich will be hosted at"; - default = "immich.arpa"; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for immich"; - default = []; - }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.immich.enable && config.services.reverseProxy.enable; - }; + description = "subdomain of base domain that immich will be hosted at"; + default = "immich"; }; }; - config = lib.mkIf config.services.immich.reverseProxy.enable { - services.reverseProxy.services.immich = { - target = "http://localhost:${toString config.services.immich.port}"; - domain = config.services.immich.domain; - extraDomains = config.services.immich.extraDomains; + config = lib.mkIf (config.services.immich.enable && config.host.reverse_proxy.enable) { + host = { + reverse_proxy.subdomains.${config.services.immich.subdomain} = { + target = "http://localhost:${toString config.services.immich.port}"; - settings = { - proxyWebsockets.enable = true; + websockets.enable = true; forwardHeaders.enable = true; - maxBodySize = 50000; - # Custom timeout settings - proxyHeaders = { - enable = true; - timeout = 600; - }; + extraConfig = '' + # allow large file uploads + client_max_body_size 50000M; + + # set timeout + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + proxy_redirect off; + ''; }; }; }; diff --git a/modules/nixos-modules/server/jackett/default.nix b/modules/nixos-modules/server/jackett/default.nix deleted file mode 100644 index 86dbb4b..0000000 --- a/modules/nixos-modules/server/jackett/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{...}: { - imports = [ - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/jackett/impermanence.nix b/modules/nixos-modules/server/jackett/impermanence.nix deleted file mode 100644 index 24fc5e6..0000000 --- a/modules/nixos-modules/server/jackett/impermanence.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - lib, - config, - ... -}: let - jackett_data_directory = "/var/lib/jackett/.config/Jackett"; -in { - options.services.jackett = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.jackett.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.jackett.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/jellyfin/default.nix b/modules/nixos-modules/server/jellyfin/default.nix index 2dbdcfd..0d88481 100644 --- a/modules/nixos-modules/server/jellyfin/default.nix +++ b/modules/nixos-modules/server/jellyfin/default.nix @@ -1,8 +1,38 @@ { + lib, + pkgs, + config, + ... +}: let + jellyfinPort = 8096; + dlanPort = 1900; +in { imports = [ - ./jellyfin.nix ./proxy.nix ./fail2ban.nix ./impermanence.nix ]; + + options.services.jellyfin = { + media_directory = lib.mkOption { + type = lib.types.str; + description = "directory jellyfin media will be hosted at"; + default = "/srv/jellyfin/media"; + }; + }; + + config = lib.mkIf config.services.jellyfin.enable { + environment.systemPackages = [ + pkgs.jellyfin + pkgs.jellyfin-web + pkgs.jellyfin-ffmpeg + ]; + + networking.firewall.allowedTCPPorts = [jellyfinPort dlanPort]; + + systemd.tmpfiles.rules = [ + "d ${config.services.jellyfin.media_directory} 2770 jellyfin jellyfin_media" + "A ${config.services.jellyfin.media_directory} - - - - u:jellyfin:rwX,g:jellyfin_media:rwX,o::-" + ]; + }; } diff --git a/modules/nixos-modules/server/jellyfin/impermanence.nix b/modules/nixos-modules/server/jellyfin/impermanence.nix index cbcb54f..e0b3b5d 100644 --- a/modules/nixos-modules/server/jellyfin/impermanence.nix +++ b/modules/nixos-modules/server/jellyfin/impermanence.nix @@ -6,14 +6,7 @@ jellyfin_data_directory = "/var/lib/jellyfin"; jellyfin_cache_directory = "/var/cache/jellyfin"; in { - options.services.jellyfin = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.jellyfin.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.jellyfin.impermanence.enable { + config = lib.mkIf (config.services.jellyfin.enable && config.host.impermanence.enable) { fileSystems."/persist/system/jellyfin".neededForBoot = true; host.storage.pool.extraDatasets = { diff --git a/modules/nixos-modules/server/jellyfin/jellyfin.nix b/modules/nixos-modules/server/jellyfin/jellyfin.nix deleted file mode 100644 index 9bfa921..0000000 --- a/modules/nixos-modules/server/jellyfin/jellyfin.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ - lib, - pkgs, - config, - ... -}: let - jellyfinPort = 8096; - dlanPort = 1900; -in { - options.services.jellyfin = { - media_directory = lib.mkOption { - type = lib.types.str; - description = "directory jellyfin media will be hosted at"; - default = "/srv/jellyfin/media"; - }; - }; - - config = lib.mkIf config.services.jellyfin.enable { - environment.systemPackages = [ - pkgs.jellyfin - pkgs.jellyfin-web - pkgs.jellyfin-ffmpeg - ]; - - networking.firewall.allowedTCPPorts = [jellyfinPort dlanPort]; - - systemd.tmpfiles.rules = [ - "d ${config.services.jellyfin.media_directory} 2770 jellyfin jellyfin_media" - "A ${config.services.jellyfin.media_directory} - - - - u:jellyfin:rwX,g:jellyfin_media:rwX,o::-" - ]; - }; -} diff --git a/modules/nixos-modules/server/jellyfin/proxy.nix b/modules/nixos-modules/server/jellyfin/proxy.nix index 35289e7..1020a19 100644 --- a/modules/nixos-modules/server/jellyfin/proxy.nix +++ b/modules/nixos-modules/server/jellyfin/proxy.nix @@ -6,36 +6,33 @@ jellyfinPort = 8096; in { options.services.jellyfin = { - domain = lib.mkOption { + subdomain = lib.mkOption { type = lib.types.str; - description = "domain that jellyfin will be hosted at"; - default = "jellyfin.arpa"; + description = "subdomain of base domain that jellyfin will be hosted at"; + default = "jellyfin"; }; - extraDomains = lib.mkOption { + extraSubdomains = lib.mkOption { type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for jellyfin"; + description = "ex subdomain of base domain that jellyfin will be hosted at"; default = []; }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.jellyfin.enable && config.services.reverseProxy.enable; - }; - }; }; - config = lib.mkIf config.services.jellyfin.reverseProxy.enable { - services.reverseProxy.services.jellyfin = { + config = lib.mkIf (config.services.jellyfin.enable && config.host.reverse_proxy.enable) { + host.reverse_proxy.subdomains.jellyfin = { target = "http://localhost:${toString jellyfinPort}"; - domain = config.services.jellyfin.domain; - extraDomains = config.services.jellyfin.extraDomains; - settings = { - forwardHeaders.enable = true; - maxBodySize = 20; - noSniff.enable = true; - proxyBuffering.enable = false; - }; + subdomain = config.services.jellyfin.subdomain; + extraSubdomains = config.services.jellyfin.extraSubdomains; + + forwardHeaders.enable = true; + + extraConfig = '' + client_max_body_size 20M; + add_header X-Content-Type-Options "nosniff"; + + proxy_buffering off; + ''; }; }; } diff --git a/modules/nixos-modules/server/lidarr/default.nix b/modules/nixos-modules/server/lidarr/default.nix deleted file mode 100644 index 86dbb4b..0000000 --- a/modules/nixos-modules/server/lidarr/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{...}: { - imports = [ - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/lidarr/impermanence.nix b/modules/nixos-modules/server/lidarr/impermanence.nix deleted file mode 100644 index 5d3aa3f..0000000 --- a/modules/nixos-modules/server/lidarr/impermanence.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - lib, - config, - ... -}: let - lidarr_data_directory = "/var/lib/lidarr/.config/Lidarr"; -in { - options.services.lidarr = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.lidarr.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.lidarr.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/network_storage/default.nix b/modules/nixos-modules/server/network_storage/default.nix index cd100ab..eaac7fe 100644 --- a/modules/nixos-modules/server/network_storage/default.nix +++ b/modules/nixos-modules/server/network_storage/default.nix @@ -1,6 +1,90 @@ { + config, + lib, + ... +}: let + export_directory = config.host.network_storage.export_directory; +in { imports = [ - ./network_storage.nix ./nfs.nix ]; + + options = { + host.network_storage = { + enable = lib.mkEnableOption "is this machine going to export network storage"; + export_directory = lib.mkOption { + type = lib.types.path; + description = "what are exports going to be stored in"; + default = "/exports"; + }; + directories = lib.mkOption { + type = lib.types.listOf (lib.types.submodule ({config, ...}: { + options = { + folder = lib.mkOption { + type = lib.types.str; + description = "what is the name of this export directory"; + }; + bind = lib.mkOption { + type = lib.types.nullOr lib.types.path; + description = "is this directory bound to anywhere"; + default = null; + }; + user = lib.mkOption { + type = lib.types.str; + description = "what user owns this directory"; + default = "nouser"; + }; + group = lib.mkOption { + type = lib.types.str; + description = "what group owns this directory"; + default = "nogroup"; + }; + _directory = lib.mkOption { + internal = true; + readOnly = true; + type = lib.types.path; + default = "${export_directory}/${config.folder}"; + }; + }; + })); + description = "list of directory names to export"; + }; + }; + }; + + config = lib.mkIf config.host.network_storage.enable (lib.mkMerge [ + { + # create any folders that we need to have for our exports + systemd.tmpfiles.rules = + [ + "d ${config.host.network_storage.export_directory} 2775 nobody nogroup -" + ] + ++ ( + builtins.map ( + directory: "d ${directory._directory} 2770 ${directory.user} ${directory.group}" + ) + config.host.network_storage.directories + ); + + # set up any bind mounts that we need for our exports + fileSystems = builtins.listToAttrs ( + builtins.map (directory: + lib.attrsets.nameValuePair directory._directory { + device = directory.bind; + options = ["bind"]; + }) ( + builtins.filter (directory: directory.bind != null) config.host.network_storage.directories + ) + ); + } + # (lib.mkIf config.host.impermanence.enable { + # environment.persistence."/persist/system/root" = { + # enable = true; + # hideMounts = true; + # directories = [ + # config.host.network_storage.export_directory + # ]; + # }; + # }) + ]); } diff --git a/modules/nixos-modules/server/network_storage/network_storage.nix b/modules/nixos-modules/server/network_storage/network_storage.nix deleted file mode 100644 index ebc3bee..0000000 --- a/modules/nixos-modules/server/network_storage/network_storage.nix +++ /dev/null @@ -1,86 +0,0 @@ -{ - config, - lib, - ... -}: let - export_directory = config.host.network_storage.export_directory; -in { - options = { - host.network_storage = { - enable = lib.mkEnableOption "is this machine going to export network storage"; - export_directory = lib.mkOption { - type = lib.types.path; - description = "what are exports going to be stored in"; - default = "/exports"; - }; - directories = lib.mkOption { - type = lib.types.listOf (lib.types.submodule ({config, ...}: { - options = { - folder = lib.mkOption { - type = lib.types.str; - description = "what is the name of this export directory"; - }; - bind = lib.mkOption { - type = lib.types.nullOr lib.types.path; - description = "is this directory bound to anywhere"; - default = null; - }; - user = lib.mkOption { - type = lib.types.str; - description = "what user owns this directory"; - default = "nouser"; - }; - group = lib.mkOption { - type = lib.types.str; - description = "what group owns this directory"; - default = "nogroup"; - }; - _directory = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.path; - default = "${export_directory}/${config.folder}"; - }; - }; - })); - description = "list of directory names to export"; - }; - }; - }; - - config = lib.mkIf config.host.network_storage.enable (lib.mkMerge [ - { - # create any folders that we need to have for our exports - systemd.tmpfiles.rules = - [ - "d ${config.host.network_storage.export_directory} 2775 nobody nogroup -" - ] - ++ ( - builtins.map ( - directory: "d ${directory._directory} 2770 ${directory.user} ${directory.group}" - ) - config.host.network_storage.directories - ); - - # set up any bind mounts that we need for our exports - fileSystems = builtins.listToAttrs ( - builtins.map (directory: - lib.attrsets.nameValuePair directory._directory { - device = directory.bind; - options = ["bind"]; - }) ( - builtins.filter (directory: directory.bind != null) config.host.network_storage.directories - ) - ); - } - # (lib.mkIf config.host.impermanence.enable { - # environment.persistence."/persist/system/root" = { - # enable = true; - # hideMounts = true; - # directories = [ - # config.host.network_storage.export_directory - # ]; - # }; - # }) - ]); -} diff --git a/modules/nixos-modules/server/panoramax/database.nix b/modules/nixos-modules/server/panoramax/database.nix index 1721726..8679f9a 100644 --- a/modules/nixos-modules/server/panoramax/database.nix +++ b/modules/nixos-modules/server/panoramax/database.nix @@ -3,46 +3,32 @@ config, ... }: { - options.services.panoramax = { - database = { - postgres = { - enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Use PostgreSQL instead of SQLite"; - }; - user = lib.mkOption { - type = lib.types.str; - default = "panoramax"; - description = "Database user name"; - }; - database = lib.mkOption { - type = lib.types.str; - default = "panoramax"; - description = "Database name"; + config = lib.mkIf config.services.panoramax.enable (lib.mkMerge [ + { + host = { + postgres = { + enable = true; }; }; - }; - }; - - config = lib.mkIf config.services.panoramax.enable { - assertions = [ - { - assertion = !config.services.panoramax.database.postgres.enable || config.services.postgresql.enable; - message = "PostgreSQL must be enabled when using postgres database for Panoramax"; + } + ( + lib.mkIf config.host.postgres.enable { + host = { + postgres = { + extraUsers = { + ${config.services.panoramax.database.user} = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${config.services.panoramax.database.name} = { + name = config.services.panoramax.database.user; + }; + }; + }; + }; } - ]; - - services.postgresql.databases.panoramax = lib.mkIf config.services.panoramax.database.postgres.enable { - enable = true; - user = config.services.panoramax.database.postgres.user; - database = config.services.panoramax.database.postgres.database; - }; - - systemd.services.panoramax = lib.mkIf config.services.panoramax.database.postgres.enable { - requires = [ - config.systemd.services.postgresql.name - ]; - }; - }; + ) + ]); } diff --git a/modules/nixos-modules/server/panoramax/impermanence.nix b/modules/nixos-modules/server/panoramax/impermanence.nix index e25ef92..011c322 100644 --- a/modules/nixos-modules/server/panoramax/impermanence.nix +++ b/modules/nixos-modules/server/panoramax/impermanence.nix @@ -1,16 +1,10 @@ { lib, config, + osConfig, ... }: { - options.services.panoramax = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.panoramax.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.panoramax.impermanence.enable { + config = lib.mkIf (config.services.panoramax.enable && osConfig.host.impermanence.enable) { # TODO: configure impermanence for panoramax data # This would typically include directories like: # - /var/lib/panoramax diff --git a/modules/nixos-modules/server/panoramax/proxy.nix b/modules/nixos-modules/server/panoramax/proxy.nix index 7cd7111..79f9326 100644 --- a/modules/nixos-modules/server/panoramax/proxy.nix +++ b/modules/nixos-modules/server/panoramax/proxy.nix @@ -4,35 +4,31 @@ ... }: { options.services.panoramax = { - domain = lib.mkOption { + subdomain = lib.mkOption { type = lib.types.str; - description = "domain that panoramax will be hosted at"; - default = "panoramax.arpa"; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for panoramax"; - default = []; - }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.panoramax.enable && config.services.reverseProxy.enable; - }; + description = "subdomain of base domain that panoramax will be hosted at"; + default = "panoramax"; }; }; - config = lib.mkIf config.services.panoramax.reverseProxy.enable { - services.reverseProxy.services.panoramax = { - target = "http://localhost:${toString config.services.panoramax.port}"; - domain = config.services.panoramax.domain; - extraDomains = config.services.panoramax.extraDomains; + config = lib.mkIf (config.services.panoramax.enable && config.host.reverse_proxy.enable) { + host = { + reverse_proxy.subdomains.${config.services.panoramax.subdomain} = { + target = "http://localhost:${toString config.services.panoramax.port}"; - settings = { - proxyWebsockets.enable = true; + websockets.enable = true; forwardHeaders.enable = true; - maxBodySize = 100000; - timeout = 300; + + extraConfig = '' + # allow large file uploads for panoramic images + client_max_body_size 100M; + + # set timeout for image processing + proxy_read_timeout 300s; + proxy_send_timeout 300s; + send_timeout 300s; + proxy_redirect off; + ''; }; }; }; diff --git a/modules/nixos-modules/server/paperless/database.nix b/modules/nixos-modules/server/paperless/database.nix index c63e59d..6f4ce51 100644 --- a/modules/nixos-modules/server/paperless/database.nix +++ b/modules/nixos-modules/server/paperless/database.nix @@ -3,28 +3,32 @@ lib, ... }: { - config = lib.mkIf config.services.paperless.enable { - assertions = [ - { - assertion = !config.services.paperless.database.createLocally || config.services.postgresql.enable; - message = "PostgreSQL must be enabled when using local postgres database for Paperless"; + config = lib.mkIf config.services.paperless.enable (lib.mkMerge [ + { + host = { + postgres = { + enable = true; + }; + }; + } + ( + lib.mkIf config.host.postgres.enable { + host = { + postgres = { + extraUsers = { + ${config.services.paperless.database.user} = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${config.services.paperless.database.user} = { + name = config.services.paperless.database.user; + }; + }; + }; + }; } - { - assertion = !config.services.paperless.database.createLocally || (builtins.any (db: db == "paperless") config.services.postgresql.ensureDatabases); - message = "Paperless built-in database creation failed - expected 'paperless' in ensureDatabases but got: ${builtins.toString config.services.postgresql.ensureDatabases}"; - } - { - assertion = !config.services.paperless.database.createLocally || (builtins.any (user: user.name == "paperless") config.services.postgresql.ensureUsers); - message = "Paperless built-in user creation failed - expected user 'paperless' in ensureUsers but got: ${builtins.toString (builtins.map (u: u.name) config.services.postgresql.ensureUsers)}"; - } - ]; - - services.paperless.database.createLocally = lib.mkDefault true; - - systemd.services.paperless-scheduler = lib.mkIf config.services.paperless.database.createLocally { - requires = [ - config.systemd.services.postgresql.name - ]; - }; - }; + ) + ]); } diff --git a/modules/nixos-modules/server/paperless/default.nix b/modules/nixos-modules/server/paperless/default.nix index 7e5e16b..a6878eb 100644 --- a/modules/nixos-modules/server/paperless/default.nix +++ b/modules/nixos-modules/server/paperless/default.nix @@ -1,9 +1,35 @@ { + config, + lib, + ... +}: { imports = [ - ./paperless.nix ./proxy.nix ./database.nix ./fail2ban.nix ./impermanence.nix ]; + + options.services.paperless = { + database = { + user = lib.mkOption { + type = lib.types.str; + description = "what is the user and database that we are going to use for paperless"; + default = "paperless"; + }; + }; + }; + + config = lib.mkIf config.services.paperless.enable { + services.paperless = { + domain = "${config.services.paperless.subdomain}.${config.host.reverse_proxy.hostname}"; + configureTika = true; + settings = { + PAPERLESS_DBENGINE = "postgresql"; + PAPERLESS_DBHOST = "/run/postgresql"; + PAPERLESS_DBNAME = config.services.paperless.database.user; + PAPERLESS_DBUSER = config.services.paperless.database.user; + }; + }; + }; } diff --git a/modules/nixos-modules/server/paperless/impermanence.nix b/modules/nixos-modules/server/paperless/impermanence.nix index fc87ea7..d9e17bd 100644 --- a/modules/nixos-modules/server/paperless/impermanence.nix +++ b/modules/nixos-modules/server/paperless/impermanence.nix @@ -5,14 +5,7 @@ }: let dataDir = "/var/lib/paperless"; in { - options.services.paperless = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.paperless.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.paperless.impermanence.enable { + config = lib.mkIf (config.services.paperless.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.paperless.dataDir == dataDir; diff --git a/modules/nixos-modules/server/paperless/paperless.nix b/modules/nixos-modules/server/paperless/paperless.nix deleted file mode 100644 index 5bcbfed..0000000 --- a/modules/nixos-modules/server/paperless/paperless.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - config, - lib, - ... -}: { - options.services.paperless = { - database = { - user = lib.mkOption { - type = lib.types.str; - description = "what is the user and database that we are going to use for paperless"; - default = "paperless"; - }; - }; - }; - - config = lib.mkIf config.services.paperless.enable { - services.paperless = { - configureTika = true; - settings = { - PAPERLESS_DBENGINE = "postgresql"; - PAPERLESS_DBHOST = "/run/postgresql"; - PAPERLESS_DBNAME = config.services.paperless.database.user; - PAPERLESS_DBUSER = config.services.paperless.database.user; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/paperless/proxy.nix b/modules/nixos-modules/server/paperless/proxy.nix index 9d152c9..2910f07 100644 --- a/modules/nixos-modules/server/paperless/proxy.nix +++ b/modules/nixos-modules/server/paperless/proxy.nix @@ -4,29 +4,25 @@ ... }: { options.services.paperless = { - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for paperless"; - default = []; - }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.paperless.enable && config.services.reverseProxy.enable; - }; + subdomain = lib.mkOption { + type = lib.types.str; + description = "subdomain of base domain that paperless will be hosted at"; + default = "paperless"; }; }; - config = lib.mkIf config.services.paperless.reverseProxy.enable { - services.reverseProxy.services.paperless = { - target = "http://${config.services.paperless.address}:${toString config.services.paperless.port}"; - domain = config.services.paperless.domain; - extraDomains = config.services.paperless.extraDomains; + config = lib.mkIf (config.services.paperless.enable && config.host.reverse_proxy.enable) { + host = { + reverse_proxy.subdomains.${config.services.paperless.subdomain} = { + target = "http://${config.services.paperless.address}:${toString config.services.paperless.port}"; - settings = { - proxyWebsockets.enable = true; + websockets.enable = true; forwardHeaders.enable = true; - maxBodySize = 50000; + + extraConfig = '' + # allow large file uploads + client_max_body_size 50000M; + ''; }; }; }; diff --git a/modules/nixos-modules/server/podman.nix b/modules/nixos-modules/server/podman.nix new file mode 100644 index 0000000..9301140 --- /dev/null +++ b/modules/nixos-modules/server/podman.nix @@ -0,0 +1,73 @@ +{ + lib, + config, + ... +}: { + options.host.podman = { + enable = lib.mkEnableOption "should podman be enabled on this computer"; + macvlan = { + subnet = lib.mkOption { + type = lib.types.str; + description = "Subnet for macvlan address range"; + }; + gateway = lib.mkOption { + type = lib.types.str; + description = "Gateway for macvlan"; + # TODO: see if we can default this to systemd network gateway + }; + networkInterface = lib.mkOption { + type = lib.types.str; + description = "Parent network interface for macvlan"; + # TODO: see if we can default this some interface? + }; + }; + }; + config = lib.mkIf config.host.podman.enable { + systemd = { + services = { + # "podman-network-macvlan" = { + # path = [pkgs.podman]; + # serviceConfig = { + # Type = "oneshot"; + # RemainAfterExit = true; + # ExecStop = "podman network rm -f macvlan"; + # }; + # script = '' + # podman network inspect macvlan || podman network create --driver macvlan --subnet ${config.host.podman.macvlan.subnet} --gateway ${config.host.podman.macvlan.gateway} --opt parent=${config.host.podman.macvlan.networkInterface} macvlan + # ''; + # partOf = ["podman-compose-root.target"]; + # wantedBy = ["podman-compose-root.target"]; + # }; + }; + # disable computer sleeping + targets = { + # Root service + # When started, this will automatically create all resources and start + # the containers. When stopped, this will teardown all resources. + "podman-compose-root" = { + unitConfig = { + Description = "Root target for podman targets."; + }; + wantedBy = ["multi-user.target"]; + }; + }; + }; + + virtualisation = { + # Runtime + podman = { + enable = true; + autoPrune.enable = true; + dockerCompat = true; + # defaultNetwork.settings = { + # # Required for container networking to be able to use names. + # dns_enabled = true; + # }; + }; + + oci-containers = { + backend = "podman"; + }; + }; + }; +} diff --git a/modules/nixos-modules/server/postgres.nix b/modules/nixos-modules/server/postgres.nix new file mode 100644 index 0000000..71ce44c --- /dev/null +++ b/modules/nixos-modules/server/postgres.nix @@ -0,0 +1,121 @@ +{ + config, + lib, + pkgs, + ... +}: let + dataDir = "/var/lib/postgresql/16"; + adminUsers = lib.lists.filter (user: user.isAdmin) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers); + clientUsers = lib.lists.filter (user: user.isClient) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers); + createUsers = lib.lists.filter (user: user.createUser) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers); + createDatabases = lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraDatabases; +in { + options = { + host.postgres = { + enable = lib.mkEnableOption "enable postgres"; + extraUsers = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { + options = { + name = lib.mkOption { + type = lib.types.str; + default = name; + }; + isAdmin = lib.mkOption { + type = lib.types.bool; + default = false; + }; + isClient = lib.mkOption { + type = lib.types.bool; + default = false; + }; + createUser = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; + })); + default = {}; + }; + extraDatabases = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { + options = { + name = lib.mkOption { + type = lib.types.str; + default = name; + }; + }; + })); + default = {}; + }; + }; + }; + + config = lib.mkIf config.host.postgres.enable (lib.mkMerge [ + { + services = { + postgresql = { + enable = true; + package = pkgs.postgresql_16; + ensureUsers = + [ + { + name = "postgres"; + } + ] + ++ ( + builtins.map (user: { + name = user.name; + ensureDBOwnership = true; + }) + createUsers + ); + ensureDatabases = builtins.map (database: database.name) createDatabases; + identMap = + '' + # ArbitraryMapName systemUser DBUser + + # Administration Users + superuser_map root postgres + superuser_map postgres postgres + '' + + ( + lib.strings.concatLines (builtins.map (user: "superuser_map ${user.name} postgres") adminUsers) + ) + + '' + + # Client Users + '' + + ( + lib.strings.concatLines (builtins.map (user: "user_map ${user.name} ${user.name}") clientUsers) + ); + # configuration here lets users access the db that matches their name and lets user postgres access everything + authentication = pkgs.lib.mkOverride 10 '' + # type database DBuser origin-address auth-method optional_ident_map + local all postgres peer map=superuser_map + local sameuser all peer map=user_map + ''; + }; + }; + } + + (lib.mkIf config.host.impermanence.enable { + assertions = [ + { + assertion = config.services.postgresql.dataDir == dataDir; + message = "postgres data directory does not match persistence"; + } + ]; + environment.persistence."/persist/system/root" = { + enable = true; + hideMounts = true; + directories = [ + { + directory = dataDir; + user = "postgres"; + group = "postgres"; + } + ]; + }; + }) + ]); +} diff --git a/modules/nixos-modules/server/postgres/default.nix b/modules/nixos-modules/server/postgres/default.nix deleted file mode 100644 index abf4ade..0000000 --- a/modules/nixos-modules/server/postgres/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./postgres.nix - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/postgres/impermanence.nix b/modules/nixos-modules/server/postgres/impermanence.nix deleted file mode 100644 index a67fb1a..0000000 --- a/modules/nixos-modules/server/postgres/impermanence.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - config, - lib, - ... -}: let - dataDir = "/var/lib/postgresql/16"; -in { - config = lib.mkIf (config.services.postgresql.enable && config.host.impermanence.enable) { - assertions = [ - { - assertion = config.services.postgresql.dataDir == dataDir; - message = "postgres data directory does not match persistence"; - } - ]; - environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; - directories = [ - { - directory = dataDir; - user = "postgres"; - group = "postgres"; - } - ]; - }; - }; -} diff --git a/modules/nixos-modules/server/postgres/postgres.nix b/modules/nixos-modules/server/postgres/postgres.nix deleted file mode 100644 index af7d1b4..0000000 --- a/modules/nixos-modules/server/postgres/postgres.nix +++ /dev/null @@ -1,122 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - enabledDatabases = lib.filterAttrs (_: db: db.enable) config.services.postgresql.databases; - extraDatabasesList = config.services.postgresql.extraDatabases; - - serviceDatabaseUsers = lib.mapAttrsToList (_: db: { - name = db.user; - ensureDBOwnership = true; - }) (lib.filterAttrs (_: db: db.ensureUser) enabledDatabases); - - extraDatabaseUsers = - builtins.map (dbName: { - name = dbName; - ensureDBOwnership = true; - }) - extraDatabasesList; - - serviceDatabases = lib.mapAttrsToList (_: db: db.database) enabledDatabases; - extraDatabaseNames = extraDatabasesList; - - serviceUserMappings = lib.mapAttrsToList (_: db: "user_map ${db.user} ${db.user}") enabledDatabases; - extraUserMappings = builtins.map (dbName: "user_map ${dbName} ${dbName}") extraDatabasesList; - - builtinServiceMappings = let - forgejoMapping = lib.optional (config.services.forgejo.enable && config.services.forgejo.database.type == "postgres") "user_map forgejo forgejo"; - immichMapping = lib.optional (config.services.immich.enable && config.services.immich.database.enable) "user_map immich immich"; - paperlessMapping = lib.optional (config.services.paperless.enable && config.services.paperless.database.createLocally) "user_map paperless paperless"; - in - forgejoMapping ++ immichMapping ++ paperlessMapping; -in { - options = { - services.postgresql = { - databases = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { - options = { - enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Whether to create this database and user"; - }; - user = lib.mkOption { - type = lib.types.str; - default = name; - description = "Database user name"; - }; - database = lib.mkOption { - type = lib.types.str; - default = name; - description = "Database name"; - }; - ensureUser = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Whether to ensure the user exists"; - }; - }; - })); - default = {}; - description = "Databases to create for services"; - }; - - extraDatabases = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "Additional databases to create (user name will match database name)"; - example = ["custom_db" "test_db"]; - }; - - adminUsers = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "System users who should have PostgreSQL superuser access"; - example = ["leyla" "admin"]; - }; - }; - }; - - config = lib.mkIf config.services.postgresql.enable { - services = { - postgresql = { - package = pkgs.postgresql_16; - - ensureUsers = - [ - {name = "postgres";} - ] - ++ serviceDatabaseUsers ++ extraDatabaseUsers; - - ensureDatabases = serviceDatabases ++ extraDatabaseNames; - - identMap = - '' - # ArbitraryMapName systemUser DBUser - - # Administration Users - superuser_map root postgres - superuser_map postgres postgres - '' - + ( - lib.strings.concatLines (builtins.map (user: "superuser_map ${user} postgres") config.services.postgresql.adminUsers) - ) - + '' - - # Client Users - '' - + ( - lib.strings.concatLines (serviceUserMappings ++ extraUserMappings ++ builtinServiceMappings) - ); - - authentication = pkgs.lib.mkOverride 10 '' - # type database DBuser origin-address auth-method optional_ident_map - local all postgres peer map=superuser_map - local sameuser all peer map=user_map - ''; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/qbittorent.nix b/modules/nixos-modules/server/qbittorent.nix new file mode 100644 index 0000000..2d54587 --- /dev/null +++ b/modules/nixos-modules/server/qbittorent.nix @@ -0,0 +1,65 @@ +{ + lib, + config, + ... +}: let + qbittorent_profile_directory = "/var/lib/qBittorrent/"; +in { + options.services.qbittorrent = { + mediaDir = lib.mkOption { + type = lib.types.path; + description = lib.mdDoc '' + The directory to create to store qbittorrent media. + ''; + }; + }; + + config = lib.mkIf config.services.qbittorrent.enable (lib.mkMerge [ + (lib.mkIf config.host.impermanence.enable { + fileSystems."/persist/system/qbittorrent".neededForBoot = true; + + host.storage.pool.extraDatasets = { + # sops age key needs to be available to pre persist for user generation + "persist/system/qbittorrent" = { + type = "zfs_fs"; + mountpoint = "/persist/system/qbittorrent"; + options = { + canmount = "on"; + }; + }; + }; + + assertions = [ + { + assertion = config.services.qbittorrent.profileDir == qbittorent_profile_directory; + message = "qbittorrent data directory does not match persistence"; + } + ]; + + environment.persistence = { + "/persist/system/root" = { + directories = [ + { + directory = qbittorent_profile_directory; + user = "qbittorrent"; + group = "qbittorrent"; + } + ]; + }; + + "/persist/system/qbittorrent" = { + enable = true; + hideMounts = true; + directories = [ + { + directory = config.services.qbittorrent.mediaDir; + user = "qbittorrent"; + group = "qbittorrent"; + mode = "1775"; + } + ]; + }; + }; + }) + ]); +} diff --git a/modules/nixos-modules/server/qbittorent/default.nix b/modules/nixos-modules/server/qbittorent/default.nix deleted file mode 100644 index f7511e6..0000000 --- a/modules/nixos-modules/server/qbittorent/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./qbittorent.nix - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/qbittorent/impermanence.nix b/modules/nixos-modules/server/qbittorent/impermanence.nix deleted file mode 100644 index 1489e7d..0000000 --- a/modules/nixos-modules/server/qbittorent/impermanence.nix +++ /dev/null @@ -1,61 +0,0 @@ -{ - lib, - config, - ... -}: let - qbittorent_profile_directory = "/var/lib/qBittorrent/"; -in { - options.services.qbittorrent = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.qbittorrent.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.qbittorrent.impermanence.enable { - fileSystems."/persist/system/qbittorrent".neededForBoot = true; - - host.storage.pool.extraDatasets = { - # sops age key needs to be available to pre persist for user generation - "persist/system/qbittorrent" = { - type = "zfs_fs"; - mountpoint = "/persist/system/qbittorrent"; - options = { - canmount = "on"; - }; - }; - }; - - assertions = [ - { - assertion = config.services.qbittorrent.profileDir == qbittorent_profile_directory; - message = "qbittorrent data directory does not match persistence"; - } - ]; - - environment.persistence = { - "/persist/system/root" = { - directories = [ - { - directory = qbittorent_profile_directory; - user = "qbittorrent"; - group = "qbittorrent"; - } - ]; - }; - - "/persist/system/qbittorrent" = { - enable = true; - hideMounts = true; - directories = [ - { - directory = config.services.qbittorrent.mediaDir; - user = "qbittorrent"; - group = "qbittorrent"; - mode = "1775"; - } - ]; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/qbittorent/qbittorent.nix b/modules/nixos-modules/server/qbittorent/qbittorent.nix deleted file mode 100644 index 44603c8..0000000 --- a/modules/nixos-modules/server/qbittorent/qbittorent.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ - lib, - config, - ... -}: { - options.services.qbittorrent = { - mediaDir = lib.mkOption { - type = lib.types.path; - description = lib.mdDoc '' - The directory to create to store qbittorrent media. - ''; - }; - }; - - config = lib.mkIf config.services.qbittorrent.enable { - # Main qbittorrent configuration goes here if needed - }; -} diff --git a/modules/nixos-modules/server/radarr/default.nix b/modules/nixos-modules/server/radarr/default.nix index 86dbb4b..f39d940 100644 --- a/modules/nixos-modules/server/radarr/default.nix +++ b/modules/nixos-modules/server/radarr/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ + ./proxy.nix ./impermanence.nix ]; } diff --git a/modules/nixos-modules/server/radarr/impermanence.nix b/modules/nixos-modules/server/radarr/impermanence.nix index c948e3a..4a3242c 100644 --- a/modules/nixos-modules/server/radarr/impermanence.nix +++ b/modules/nixos-modules/server/radarr/impermanence.nix @@ -5,14 +5,7 @@ }: let radarr_data_directory = "/var/lib/radarr/.config/Radarr"; in { - options.services.radarr = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.radarr.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.radarr.impermanence.enable { + config = lib.mkIf (config.services.radarr.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.radarr.dataDir == radarr_data_directory; diff --git a/modules/nixos-modules/server/radarr/proxy.nix b/modules/nixos-modules/server/radarr/proxy.nix new file mode 100644 index 0000000..ec5f575 --- /dev/null +++ b/modules/nixos-modules/server/radarr/proxy.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + ... +}: { + options.services.radarr = { + 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.radarr.enable && config.services.radarr.subdomain != null) { + host.reverse_proxy.subdomains.radarr = { + subdomain = config.services.radarr.subdomain; + extraSubdomains = config.services.radarr.extraSubdomains; + target = "http://127.0.0.1:7878"; + websockets.enable = true; + forwardHeaders.enable = true; + }; + }; +} diff --git a/modules/nixos-modules/server/reverseProxy/default.nix b/modules/nixos-modules/server/reverseProxy/default.nix deleted file mode 100644 index 5d57175..0000000 --- a/modules/nixos-modules/server/reverseProxy/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./reverseProxy.nix - ./impermanence.nix - ]; -} diff --git a/modules/nixos-modules/server/reverseProxy/impermanence.nix b/modules/nixos-modules/server/reverseProxy/impermanence.nix deleted file mode 100644 index 7af55df..0000000 --- a/modules/nixos-modules/server/reverseProxy/impermanence.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - lib, - config, - ... -}: let - dataDir = "/var/lib/acme"; -in { - config = lib.mkIf (config.host.impermanence.enable && config.services.reverseProxy.enable) { - environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; - directories = [ - { - directory = dataDir; - user = "acme"; - group = "acme"; - } - ]; - }; - }; -} diff --git a/modules/nixos-modules/server/reverseProxy/reverseProxy.nix b/modules/nixos-modules/server/reverseProxy/reverseProxy.nix deleted file mode 100644 index eecc9bf..0000000 --- a/modules/nixos-modules/server/reverseProxy/reverseProxy.nix +++ /dev/null @@ -1,176 +0,0 @@ -{ - lib, - config, - ... -}: { - options.services.reverseProxy = { - enable = lib.mkEnableOption "turn on the reverse proxy"; - openFirewall = lib.mkEnableOption "open the firewall"; - refuseUnmatchedDomains = lib.mkOption { - type = lib.types.bool; - description = "refuse connections for domains that don't match any configured virtual hosts"; - default = true; - }; - ports = { - http = lib.mkOption { - type = lib.types.port; - description = "HTTP port for the reverse proxy"; - default = 80; - }; - https = lib.mkOption { - type = lib.types.port; - description = "HTTPS port for the reverse proxy"; - default = 443; - }; - }; - acme = { - enable = lib.mkOption { - type = lib.types.bool; - description = "enable ACME certificate management"; - default = true; - }; - email = lib.mkOption { - type = lib.types.str; - description = "email address for ACME certificate registration"; - }; - }; - services = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { - options = { - target = lib.mkOption { - type = lib.types.str; - description = "what url will all traffic to this application be forwarded to"; - }; - domain = lib.mkOption { - type = lib.types.str; - description = "what is the default subdomain to be used for this application to be used for"; - default = name; - }; - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for this domain"; - default = []; - }; - settings = { - certificateRenewal.enable = lib.mkOption { - type = lib.types.bool; - description = "auto renew certificates"; - default = true; - }; - forceSSL.enable = lib.mkOption { - type = lib.types.bool; - description = "auto renew certificates"; - default = true; - }; - proxyHeaders = { - enable = lib.mkEnableOption "should we proxy headers"; - timeout = lib.mkOption { - type = lib.types.int; - default = 60; - }; - }; - proxyWebsockets.enable = lib.mkEnableOption "should the default config proxy websockets"; - forwardHeaders.enable = lib.mkEnableOption "should the default config contain forward headers"; - noSniff.enable = lib.mkEnableOption "should the no sniff flags be set"; - proxyBuffering.enable = lib.mkOption { - type = lib.types.bool; - description = "should proxy buffering be enabled"; - default = true; - }; - maxBodySize = lib.mkOption { - type = lib.types.nullOr lib.types.int; - description = ""; - default = null; - }; - }; - }; - })); - }; - }; - - config = let - httpPort = config.services.reverseProxy.ports.http; - httpsPort = config.services.reverseProxy.ports.https; - in - lib.mkIf config.services.reverseProxy.enable { - security.acme = lib.mkIf config.services.reverseProxy.acme.enable { - acceptTerms = true; - defaults.email = config.services.reverseProxy.acme.email; - }; - - services.nginx = { - enable = true; - virtualHosts = lib.mkMerge ( - (lib.optionals config.services.reverseProxy.refuseUnmatchedDomains [ - { - "_" = { - default = true; - serverName = "_"; - locations."/" = { - extraConfig = '' - return 444; - ''; - }; - }; - } - ]) - ++ lib.lists.flatten ( - lib.attrsets.mapAttrsToList ( - name: service: let - hostConfig = { - forceSSL = service.settings.forceSSL.enable; - enableACME = service.settings.certificateRenewal.enable; - locations = { - "/" = { - proxyPass = service.target; - proxyWebsockets = service.settings.proxyWebsockets.enable; - recommendedProxySettings = service.settings.forwardHeaders.enable; - extraConfig = let - # Client upload size configuration - maxBodySizeConfig = - lib.optionalString (service.settings.maxBodySize != null) - "client_max_body_size ${toString service.settings.maxBodySize}M;"; - - # Security header configuration - noSniffConfig = - lib.optionalString service.settings.noSniff.enable - "add_header X-Content-Type-Options nosniff;"; - - # Proxy buffering configuration - proxyBufferingConfig = - lib.optionalString (!service.settings.proxyBuffering.enable) - "proxy_buffering off;"; - - # Proxy timeout configuration - proxyTimeoutConfig = - lib.optionalString service.settings.proxyHeaders.enable - '' - proxy_read_timeout ${toString service.settings.proxyHeaders.timeout}s; - proxy_connect_timeout ${toString service.settings.proxyHeaders.timeout}s; - proxy_send_timeout ${toString service.settings.proxyHeaders.timeout}s; - ''; - in - maxBodySizeConfig + noSniffConfig + proxyBufferingConfig + proxyTimeoutConfig; - }; - }; - }; - in ( - [ - { - ${service.domain} = hostConfig; - } - ] - ++ builtins.map (domain: {${domain} = hostConfig;}) - service.extraDomains - ) - ) - config.services.reverseProxy.services - ) - ); - }; - networking.firewall.allowedTCPPorts = lib.mkIf config.services.reverseProxy.openFirewall [ - httpPort - httpsPort - ]; - }; -} diff --git a/modules/nixos-modules/server/reverse_proxy.nix b/modules/nixos-modules/server/reverse_proxy.nix new file mode 100644 index 0000000..26b4374 --- /dev/null +++ b/modules/nixos-modules/server/reverse_proxy.nix @@ -0,0 +1,128 @@ +{ + lib, + config, + ... +}: let + dataDir = "/var/lib/acme"; + httpPort = 80; + httpsPort = 443; +in { + options.host.reverse_proxy = { + enable = lib.mkEnableOption "turn on the reverse proxy"; + hostname = lib.mkOption { + type = lib.types.str; + description = "what host name are we going to be proxying from"; + }; + forceSSL = lib.mkOption { + type = lib.types.bool; + description = "force connections to use https"; + default = config.host.reverse_proxy.enableACME; + }; + enableACME = lib.mkOption { + type = lib.types.bool; + description = "auto renew certificates"; + default = true; + }; + subdomains = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { + options = { + subdomain = lib.mkOption { + type = lib.types.str; + description = "what is the default subdomain to be used for this application to be used for"; + default = name; + }; + extraSubdomains = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "extra domains that should be configured for this domain"; + default = []; + }; + + target = lib.mkOption { + type = lib.types.str; + description = "what url will all traffic to this application be forwarded to"; + }; + + websockets.enable = lib.mkEnableOption "should the default config proxy websockets"; + + forwardHeaders.enable = lib.mkEnableOption "should the default config contain forward headers"; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + description = '' + These lines go to the end of the upstream verbatim. + ''; + }; + }; + })); + }; + }; + + config = lib.mkIf config.host.reverse_proxy.enable (lib.mkMerge [ + { + security.acme = lib.mkIf config.host.reverse_proxy.enableACME { + acceptTerms = true; + defaults.email = "jan-leila@protonmail.com"; + }; + + services.nginx = { + enable = true; + virtualHosts = lib.mkMerge ( + lib.lists.flatten ( + lib.attrsets.mapAttrsToList ( + name: value: let + hostConfig = { + forceSSL = config.host.reverse_proxy.forceSSL; + enableACME = config.host.reverse_proxy.enableACME; + locations = { + "/" = { + proxyPass = value.target; + proxyWebsockets = value.websockets.enable; + recommendedProxySettings = value.forwardHeaders.enable; + extraConfig = + value.extraConfig; + }; + }; + }; + in ( + [ + { + ${"${value.subdomain}.${config.host.reverse_proxy.hostname}"} = hostConfig; + } + ] + ++ builtins.map (subdomain: {${"${subdomain}.${config.host.reverse_proxy.hostname}"} = hostConfig;}) + value.extraSubdomains + ) + ) + config.host.reverse_proxy.subdomains + ) + ); + }; + + networking.firewall.allowedTCPPorts = [ + httpPort + httpsPort + ]; + } + (lib.mkIf config.host.impermanence.enable { + # TODO: figure out how to write an assertion for this + # assertions = [ + # { + # assertion = security.acme.certs..directory == dataDir; + # message = "postgres data directory does not match persistence"; + # } + # ]; + environment.persistence."/persist/system/root" = { + enable = true; + hideMounts = true; + directories = [ + { + directory = dataDir; + user = "acme"; + group = "acme"; + } + ]; + }; + }) + ]); +} diff --git a/modules/nixos-modules/server/searx/default.nix b/modules/nixos-modules/server/searx/default.nix index 5426380..ac84c1d 100644 --- a/modules/nixos-modules/server/searx/default.nix +++ b/modules/nixos-modules/server/searx/default.nix @@ -1,6 +1,63 @@ { + config, + lib, + inputs, + ... +}: { imports = [ - ./searx.nix ./proxy.nix ]; + + config = lib.mkIf config.services.searx.enable { + sops.secrets = { + "services/searx" = { + sopsFile = "${inputs.secrets}/defiant-services.yaml"; + }; + }; + + services.searx = { + environmentFile = config.sops.secrets."services/searx".path; + + # Rate limiting + limiterSettings = { + real_ip = { + x_for = 1; + ipv4_prefix = 32; + ipv6_prefix = 56; + }; + + botdetection = { + ip_limit = { + filter_link_local = true; + link_token = true; + }; + }; + }; + + settings = { + server = { + port = 8083; + secret_key = "@SEARXNG_SECRET@"; + }; + + # Search engine settings + search = { + safe_search = 2; + autocomplete_min = 2; + autocomplete = "duckduckgo"; + }; + + # Enabled plugins + enabled_plugins = [ + "Basic Calculator" + "Hash plugin" + "Tor check plugin" + "Open Access DOI rewrite" + "Hostnames plugin" + "Unit converter plugin" + "Tracker URL remover" + ]; + }; + }; + }; } diff --git a/modules/nixos-modules/server/searx/proxy.nix b/modules/nixos-modules/server/searx/proxy.nix index e994e4a..0c1eae1 100644 --- a/modules/nixos-modules/server/searx/proxy.nix +++ b/modules/nixos-modules/server/searx/proxy.nix @@ -4,27 +4,18 @@ ... }: { options.services.searx = { - extraDomains = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "extra domains that should be configured for searx"; - default = []; - }; - reverseProxy = { - enable = lib.mkOption { - type = lib.types.bool; - default = config.services.searx.enable && config.services.reverseProxy.enable; - }; + subdomain = lib.mkOption { + type = lib.types.str; + description = "subdomain of base domain that searx will be hosted at"; + default = "searx"; }; }; - config = lib.mkIf config.services.searx.reverseProxy.enable { - services.reverseProxy.services.searx = { - target = "http://localhost:${toString config.services.searx.settings.server.port}"; - domain = config.services.searx.domain; - extraDomains = config.services.searx.extraDomains; - - settings = { - forwardHeaders.enable = true; + config = lib.mkIf (config.services.searx.enable && config.host.reverse_proxy.enable) { + host = { + reverse_proxy.subdomains.searx = { + subdomain = config.services.searx.subdomain; + target = "http://localhost:${toString config.services.searx.settings.server.port}"; }; }; }; diff --git a/modules/nixos-modules/server/searx/searx.nix b/modules/nixos-modules/server/searx/searx.nix deleted file mode 100644 index d4d4012..0000000 --- a/modules/nixos-modules/server/searx/searx.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ - config, - lib, - inputs, - ... -}: { - config = lib.mkIf config.services.searx.enable { - sops.secrets = { - "services/searx" = { - sopsFile = "${inputs.secrets}/defiant-services.yaml"; - }; - }; - - services.searx = { - environmentFile = config.sops.secrets."services/searx".path; - - # Rate limiting - limiterSettings = { - real_ip = { - x_for = 1; - ipv4_prefix = 32; - ipv6_prefix = 56; - }; - - botdetection = { - ip_limit = { - filter_link_local = true; - link_token = true; - }; - }; - }; - - settings = { - server = { - port = 8083; - secret_key = "@SEARXNG_SECRET@"; - }; - - # Search engine settings - search = { - safe_search = 2; - autocomplete_min = 2; - autocomplete = "duckduckgo"; - }; - - # Enabled plugins - enabled_plugins = [ - "Basic Calculator" - "Hash plugin" - "Tor check plugin" - "Open Access DOI rewrite" - "Hostnames plugin" - "Unit converter plugin" - "Tracker URL remover" - ]; - }; - }; - }; -} diff --git a/modules/nixos-modules/server/sonarr/default.nix b/modules/nixos-modules/server/sonarr/default.nix index 86dbb4b..f39d940 100644 --- a/modules/nixos-modules/server/sonarr/default.nix +++ b/modules/nixos-modules/server/sonarr/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ + ./proxy.nix ./impermanence.nix ]; } diff --git a/modules/nixos-modules/server/sonarr/impermanence.nix b/modules/nixos-modules/server/sonarr/impermanence.nix index 5b90ee9..abc843c 100644 --- a/modules/nixos-modules/server/sonarr/impermanence.nix +++ b/modules/nixos-modules/server/sonarr/impermanence.nix @@ -5,14 +5,7 @@ }: let sonarr_data_directory = "/var/lib/sonarr/.config/NzbDrone"; in { - options.services.sonarr = { - impermanence.enable = lib.mkOption { - type = lib.types.bool; - default = config.services.sonarr.enable && config.host.impermanence.enable; - }; - }; - - config = lib.mkIf config.services.sonarr.impermanence.enable { + config = lib.mkIf (config.services.sonarr.enable && config.host.impermanence.enable) { assertions = [ { assertion = config.services.sonarr.dataDir == sonarr_data_directory; diff --git a/modules/nixos-modules/server/sonarr/proxy.nix b/modules/nixos-modules/server/sonarr/proxy.nix new file mode 100644 index 0000000..22b90a6 --- /dev/null +++ b/modules/nixos-modules/server/sonarr/proxy.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + ... +}: { + options.services.sonarr = { + 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.sonarr.enable && config.services.sonarr.subdomain != null) { + host.reverse_proxy.subdomains.sonarr = { + subdomain = config.services.sonarr.subdomain; + extraSubdomains = config.services.sonarr.extraSubdomains; + target = "http://127.0.0.1:8989"; + websockets.enable = true; + forwardHeaders.enable = true; + }; + }; +} diff --git a/modules/nixos-modules/server/wyoming.nix b/modules/nixos-modules/server/wyoming.nix index c9a1474..4894dd4 100644 --- a/modules/nixos-modules/server/wyoming.nix +++ b/modules/nixos-modules/server/wyoming.nix @@ -37,9 +37,9 @@ openwakeword = { enable = true; uri = "tcp://0.0.0.0:10400"; - # preloadModels = [ - # "ok_nabu" - # ]; + preloadModels = [ + "ok_nabu" + ]; # TODO: custom models }; }; diff --git a/modules/nixos-modules/users.nix b/modules/nixos-modules/users.nix index 987e080..137ae4b 100644 --- a/modules/nixos-modules/users.nix +++ b/modules/nixos-modules/users.nix @@ -29,8 +29,6 @@ radarr = 2014; sonarr = 2015; bazarr = 2016; - lidarr = 2017; - crab-hole = 2018; }; gids = { @@ -52,8 +50,6 @@ radarr = 2014; sonarr = 2015; bazarr = 2016; - lidarr = 2017; - crab-hole = 2018; }; users = config.users.users; @@ -225,18 +221,6 @@ 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 = { @@ -277,7 +261,6 @@ in { users.radarr.name users.sonarr.name users.bazarr.name - users.lidarr.name leyla eve ivy @@ -382,20 +365,6 @@ 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 6750450..36a1201 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -1,15 +1,5 @@ #!/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 @@ -52,29 +42,14 @@ while [ $# -gt 0 ]; do ;; --help|-h) echo "--help -h: print this message" - 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 "--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 "--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 ;; *) @@ -85,21 +60,10 @@ while [ $# -gt 0 ]; do shift done -target=${target:-$default_target} +target=${target:-$(hostname)} flake=${flake:-$target} -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 +mode=${mode:-switch} +user=${user:-$USER} command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake" @@ -127,4 +91,4 @@ then then rm -r result fi -fi +fi \ No newline at end of file