diff --git a/README.md b/README.md index bc31eca..141c2fd 100644 --- a/README.md +++ b/README.md @@ -41,30 +41,33 @@ nix multi user, multi system, configuration with `sops` secret management, `home ## Research topics - Look into this for auto rotating sops keys `https://technotim.live/posts/rotate-sops-encryption-keys/` -- Look into this for flake templates https://nix.dev/manual/nix/2.22/command-ref/new-cli/nix3-flake-init +- Look into this for npins https://jade.fyi/blog/pinning-nixos-with-npins/ - https://nixos-and-flakes.thiscute.world/ +- nix config mcp https://github.com/utensils/mcp-nixos # Tasks: ## Tech Debt - monitor configuration in `~/.config/monitors.xml` should be sym linked to `/run/gdm/.config/monitors.xml` (https://www.reddit.com/r/NixOS/comments/u09cz9/home_manager_create_my_own_symlinks_automatically/) -- syncthing folder passwords - nfs export should be backed by the same values for server and client ## New Features -- offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) -- samba mounts +- crab-hole +- figure out why syncthing and jellyfins permissions don't propagate downwards - figure out steam vr things? -- Open GL? -- rotate sops encryption keys periodically (and somehow sync between devices?) +- auto turn off on power loss - nut - zfs email after scrubbing # TODO: test this -- wake on LAN for updates -- ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix +- SMART test with email results +- fix nfs +- samba mounts +- offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) +- Create Tor guard/relay server +- migrate away from flakes and move to npins +- whisper +- figure out ai vs code plugin +- nix mcp - zfs encryption FIDO2 2fa (look into shavee) - Secure Boot - https://github.com/nix-community/lanzaboote -- SMART test with email results -- Create Tor guard/relay server +- rotate sops encryption keys periodically (and somehow sync between devices?) +- wake on LAN for updates - remote distributed builds - https://nix.dev/tutorials/nixos/distributed-builds-setup.html -- migrate away from flakes and move to npins -- fix nfs -- fix home assistant -- create adguard server \ No newline at end of file +- ISO target that contains authorized keys for nixos-anywhere https://github.com/diegofariasm/yggdrasil/blob/4acc43ebc7bcbf2e41376d14268e382007e94d78/hosts/bootstrap/default.nix \ No newline at end of file diff --git a/configurations/home-manager/leyla/dconf.nix b/configurations/home-manager/leyla/dconf.nix index 5818641..ef75db6 100644 --- a/configurations/home-manager/leyla/dconf.nix +++ b/configurations/home-manager/leyla/dconf.nix @@ -1,26 +1,23 @@ {pkgs, ...}: { config = { + gnome = { + extraWindowControls = true; + colorScheme = "prefer-dark"; + clockFormat = "24h"; + extensions = [ + pkgs.gnomeExtensions.dash-to-dock + ]; + hotkeys = { + "Open Terminal" = { + binding = "t"; + command = "kgx"; + }; + }; + }; + dconf = { enable = true; settings = { - "org/gnome/desktop/interface".color-scheme = "prefer-dark"; - - "org/gnome/desktop/wm/preferences".button-layout = ":minimize,maximize,close"; - - "org/gnome/shell" = { - disable-user-extensions = false; # enables user extensions - enabled-extensions = [ - # Put UUIDs of extensions that you want to enable here. - # If the extension you want to enable is packaged in nixpkgs, - # you can easily get its UUID by accessing its extensionUuid - # field (look at the following example). - pkgs.gnomeExtensions.dash-to-dock.extensionUuid - - # Alternatively, you can manually pass UUID as a string. - # "dash-to-dock@micxgx.gmail.com" - ]; - }; - "org/gnome/shell/extensions/dash-to-dock" = { "dock-position" = "LEFT"; "intellihide-mode" = "ALL_WINDOWS"; @@ -29,18 +26,6 @@ "show-mounts" = false; }; - "org/gnome/settings-daemon/plugins/media-keys" = { - custom-keybindings = [ - "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/" - ]; - }; - - "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = { - binding = "t"; - command = "kgx"; - name = "Open Terminal"; - }; - "org/gnome/shell" = { favorite-apps = ["org.gnome.Nautilus.desktop" "firefox.desktop" "codium.desktop" "steam.desktop" "org.gnome.Console.desktop"]; # app-picker-layout = diff --git a/configurations/home-manager/leyla/default.nix b/configurations/home-manager/leyla/default.nix index 49abfe1..538eab8 100644 --- a/configurations/home-manager/leyla/default.nix +++ b/configurations/home-manager/leyla/default.nix @@ -82,31 +82,5 @@ # EDITOR = "emacs"; }; }; - - user = { - continue = { - enable = true; - docs = { - "Continue Docs" = { - startUrl = "https://docs.continue.dev"; - }; - "Nixpkgs" = { - startUrl = "https://ryantm.github.io/nixpkgs/#preface"; - }; - "Nix Manual" = { - startUrl = "https://nixos.org/manual/nixos/stable/"; - }; - "Home manager Manual" = { - startUrl = "https://nix-community.github.io/home-manager/"; - }; - "Nix Docs" = { - startUrl = "https://nix.dev/index.html"; - }; - "Linux Man Page" = { - startUrl = "https://linux.die.net/man/"; - }; - }; - }; - }; }; } diff --git a/configurations/home-manager/leyla/packages/default.nix b/configurations/home-manager/leyla/packages/default.nix index bbd8152..63f9661 100644 --- a/configurations/home-manager/leyla/packages/default.nix +++ b/configurations/home-manager/leyla/packages/default.nix @@ -69,8 +69,6 @@ in { (with pkgs; [ aileron - gnomeExtensions.dash-to-dock - proxmark3 ]) ++ ( diff --git a/configurations/home-manager/leyla/packages/vscode/default.nix b/configurations/home-manager/leyla/packages/vscode/default.nix index c21e01d..f911104 100644 --- a/configurations/home-manager/leyla/packages/vscode/default.nix +++ b/configurations/home-manager/leyla/packages/vscode/default.nix @@ -1,31 +1,20 @@ { lib, pkgs, - inputs, config, osConfig, ... }: let nix-development-enabled = osConfig.host.nix-development.enable; - ai-tooling-enabled = config.user.continue.enable && osConfig.host.ai.enable; + ai-tooling-enabled = osConfig.host.ai.enable; in { config = lib.mkIf config.user.isDesktopUser { - nixpkgs = { - overlays = [ - inputs.nix-vscode-extensions.overlays.default - ]; - }; - programs = { bash.shellAliases = { code = "codium"; }; - vscode = let - extensions = inputs.nix-vscode-extensions.extensions.${pkgs.system}; - open-vsx = extensions.open-vsx; - vscode-marketplace = extensions.vscode-marketplace; - in { + vscode = { package = pkgs.vscodium; mutableExtensionsDir = false; @@ -57,12 +46,13 @@ in { }; }) (lib.mkIf ai-tooling-enabled { - "continue.telemetryEnabled" = false; - }) + }) ]; - extensions = ( - with open-vsx; + extensions = let + extension-pkgs = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; + in ( + with extension-pkgs.open-vsx; [ # vs code feel extensions ms-vscode.atom-keybindings @@ -80,7 +70,7 @@ in { dsznajder.es7-react-js-snippets dbaeumer.vscode-eslint standard.vscode-standard - firsttris.vscode-jest-runner + orta.vscode-jest stylelint.vscode-stylelint tauri-apps.tauri-vscode @@ -101,14 +91,18 @@ in { kamadorueda.alejandra ]) ++ ( - with vscode-marketplace; + with extension-pkgs.vscode-marketplace; [ # js extensions karyfoundation.nearley ] ++ (lib.lists.optionals ai-tooling-enabled [ - continue.continue - ]) + ]) + ) + ++ ( + with pkgs.codium-extensions; [ + ai-code + ] ) ); }; diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index 7d9c6d8..960e90b 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -17,6 +17,12 @@ "services/zfs_smtp_token" = { sopsFile = "${inputs.secrets}/defiant-services.yaml"; }; + "services/paperless_password" = { + sopsFile = "${inputs.secrets}/defiant-services.yaml"; + mode = "0700"; + owner = "paperless"; + group = "paperless"; + }; }; host = { @@ -109,13 +115,6 @@ }; }; }; - # home-assistant = { - # enable = false; - # subdomain = "home"; - # }; - adguardhome = { - enable = false; - }; }; systemd.network = { @@ -282,10 +281,23 @@ subdomain = "search"; }; - virt-home-assistant = { - enable = false; - networkBridge = "bond0"; - hostDevice = "0x10c4:0xea60"; + home-assistant = { + enable = true; + subdomain = "home"; + openFirewall = true; + database = "postgres"; + + extensions = { + sonos.enable = true; + jellyfin.enable = true; + wyoming.enable = true; + }; + }; + + paperless = { + enable = true; + subdomain = "documents"; + passwordFile = config.sops.secrets."services/paperless_password".path; }; qbittorrent = { diff --git a/configurations/nixos/horizon/configuration.nix b/configurations/nixos/horizon/configuration.nix index 42dcbb9..99b6ee9 100644 --- a/configurations/nixos/horizon/configuration.nix +++ b/configurations/nixos/horizon/configuration.nix @@ -126,6 +126,13 @@ }; syncthing.enable = true; + + ollama = { + enable = true; + loadModels = [ + "llama3.1:8b" + ]; + }; }; # Enable touchpad support (enabled default in most desktopManager). diff --git a/flake.lock b/flake.lock index 2d00dff..a32ae84 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1750680230, - "narHash": "sha256-kD88T/NqmcgfOBFAwphN30ccaUdj6K6+LG0XdM2w2LA=", + "lastModified": 1752113600, + "narHash": "sha256-7LYDxKxZgBQ8LZUuolAQ8UkIB+jb4A2UmiR+kzY9CLI=", "owner": "nix-community", "repo": "disko", - "rev": "8fd2d6c75009ac75f9a6fb18c33a239806778d01", + "rev": "79264292b7e3482e5702932949de9cbb69fedf6d", "type": "github" }, "original": { @@ -28,11 +28,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1750737804, - "narHash": "sha256-wClGd2PhxdjjphR6wIgoiDcR+Gfg4/+FyseSOjIIzVU=", + "lastModified": 1752379414, + "narHash": "sha256-0R3slhrjrnzyxR/fAYy5UliZvSgaVS38YCESBdH5RJw=", "owner": "rycee", "repo": "nur-expressions", - "rev": "aaaf4fec792bad465ea4a35c0be5bc2a54f33095", + "rev": "51e77bb95540b7dd6c60f8fd65a0c472a2c9c3b7", "type": "gitlab" }, "original": { @@ -115,11 +115,11 @@ ] }, "locked": { - "lastModified": 1750730235, - "narHash": "sha256-rZErlxiV7ssvI8t7sPrKU+fRigNc2KvoKZG3gtUtK50=", + "lastModified": 1752467539, + "narHash": "sha256-4kaR+xmng9YPASckfvIgl5flF/1nAZOplM+Wp9I5SMI=", "owner": "nix-community", "repo": "home-manager", - "rev": "d07e9cceb4994ed64a22b9b36f8b76923e87ac38", + "rev": "1e54837569e0b80797c47be4720fab19e0db1616", "type": "github" }, "original": { @@ -185,11 +185,11 @@ ] }, "locked": { - "lastModified": 1750618568, - "narHash": "sha256-w9EG5FOXrjXGfbqCcQg9x1lMnTwzNDW5BMXp8ddy15E=", + "lastModified": 1751313918, + "narHash": "sha256-HsJM3XLa43WpG+665aGEh8iS8AfEwOIQWk3Mke3e7nk=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "1dd19f19e4b53a1fd2e8e738a08dd5fe635ec7e5", + "rev": "e04a388232d9a6ba56967ce5b53a8a6f713cdfcf", "type": "github" }, "original": { @@ -227,11 +227,11 @@ ] }, "locked": { - "lastModified": 1750730765, - "narHash": "sha256-MIcOcvxqAXUv2TJjf19aVXdtVrD8Gkcfi4W4pKkT0Lw=", + "lastModified": 1752459325, + "narHash": "sha256-46TgjdxT02a4nFd9HCXCf8kK5ZSH7r9gYROLtc8zVOg=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "1a1442e13dc1730de0443f80dcf02658365e999a", + "rev": "61c2e99ebd586f463a6c0ebe3d931e74883b163d", "type": "github" }, "original": { @@ -242,11 +242,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1750431636, - "narHash": "sha256-vnzzBDbCGvInmfn2ijC4HsIY/3W1CWbwS/YQoFgdgPg=", + "lastModified": 1752048960, + "narHash": "sha256-gATnkOe37eeVwKKYCsL+OnS2gU4MmLuZFzzWCtaKLI8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "1552a9f4513f3f0ceedcf90320e48d3d47165712", + "rev": "7ced9122cff2163c6a0212b8d1ec8c33a1660806", "type": "github" }, "original": { @@ -258,11 +258,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1750506804, - "narHash": "sha256-VLFNc4egNjovYVxDGyBYTrvVCgDYgENp5bVi9fPTDYc=", + "lastModified": 1751984180, + "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4206c4cb56751df534751b058295ea61357bbbaa", + "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", "type": "github" }, "original": { @@ -293,11 +293,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1749061163, - "narHash": "sha256-WflcbitH7ErNZBFqZCdy1ODUqKF51xbu2zYfqA35+1M=", + "lastModified": 1752531440, + "narHash": "sha256-04tQ3EUrtmZ7g6fVUkZC4AbAG+Z7lng79qU3jsiqWJY=", "ref": "refs/heads/main", - "rev": "1c5c059c0c7b6ce691993262fe10a2b63e1c31ba", - "revCount": 19, + "rev": "f016767c13aa36dde91503f7a9f01bdd02468045", + "revCount": 20, "type": "git", "url": "ssh://git@git.jan-leila.com/jan-leila/nix-config-secrets.git" }, @@ -313,11 +313,11 @@ ] }, "locked": { - "lastModified": 1750119275, - "narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=", + "lastModified": 1751606940, + "narHash": "sha256-KrDPXobG7DFKTOteqdSVeL1bMVitDcy7otpVZWDE6MA=", "owner": "Mic92", "repo": "sops-nix", - "rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2", + "rev": "3633fc4acf03f43b260244d94c71e9e14a2f6e0d", "type": "github" }, "original": { diff --git a/modules/common-modules/overlays/default.nix b/modules/common-modules/overlays/default.nix index 1fab060..465e83f 100644 --- a/modules/common-modules/overlays/default.nix +++ b/modules/common-modules/overlays/default.nix @@ -2,5 +2,6 @@ {inputs, ...}: { nixpkgs.overlays = [ inputs.steam-fetcher.overlays.default + inputs.nix-vscode-extensions.overlays.default ]; } diff --git a/modules/common-modules/pkgs/codium-extensions/ai-code.nix b/modules/common-modules/pkgs/codium-extensions/ai-code.nix new file mode 100644 index 0000000..ccd4cb8 --- /dev/null +++ b/modules/common-modules/pkgs/codium-extensions/ai-code.nix @@ -0,0 +1,42 @@ +{ + buildNpmPackage, + vscode-utils, + pkgs, + ... +}: let + version = "0.0.1"; + pname = "ai-code"; + publisher = "jan-leila"; + vsix = buildNpmPackage { + inherit version pname; + + src = builtins.fetchGit { + url = "ssh://git@git.jan-leila.com/jan-leila/ai-code.git"; + rev = "480b51830602b28009e6b5c5014e7e2970a0a3b3"; + }; + + npmDepsHash = "sha256-WxLb+e0itOCIRXpVOjcbPm6QNWbdSKZOPeXLyOa4ROQ="; + + nativeBuildInputs = with pkgs; [ + vsce + ]; + + buildPhase = '' + ${pkgs.vsce}/bin/vsce package -o ${pname}.zip + ''; + + installPhase = '' + mkdir -p $out + mv ${pname}.zip $out/${pname}.zip + ''; + }; +in + vscode-utils.buildVscodeExtension { + inherit pname version; + + src = "${vsix}/${pname}.zip"; + + vscodeExtUniqueId = "${publisher}.${pname}"; + vscodeExtPublisher = publisher; + vscodeExtName = pname; + } diff --git a/modules/common-modules/pkgs/codium-extensions/default.nix b/modules/common-modules/pkgs/codium-extensions/default.nix new file mode 100644 index 0000000..a60e8a0 --- /dev/null +++ b/modules/common-modules/pkgs/codium-extensions/default.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: { + ai-code = pkgs.callPackage ./ai-code.nix {}; +} diff --git a/modules/common-modules/pkgs/default.nix b/modules/common-modules/pkgs/default.nix index e955354..16f3a3c 100644 --- a/modules/common-modules/pkgs/default.nix +++ b/modules/common-modules/pkgs/default.nix @@ -19,5 +19,8 @@ (final: prev: { gdx-liftoff = pkgs.callPackage ./gdx-liftoff.nix {}; }) + (final: prev: { + codium-extensions = pkgs.callPackage ./codium-extensions {}; + }) ]; } diff --git a/modules/home-manager-modules/continue.nix b/modules/home-manager-modules/continue.nix deleted file mode 100644 index 20ec52b..0000000 --- a/modules/home-manager-modules/continue.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ - lib, - pkgs, - config, - osConfig, - ... -}: let - ai-tooling-enabled = config.user.continue.enable && osConfig.host.ai.enable; -in { - options.user.continue = { - enable = lib.mkEnableOption "should continue be enabled on this machine"; - docs = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { - options = { - name = lib.mkOption { - type = lib.types.str; - default = name; - }; - startUrl = lib.mkOption { - type = lib.types.str; - }; - }; - })); - }; - context = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { - options = { - provider = lib.mkOption { - type = lib.types.str; - default = name; - }; - }; - })); - default = { - "code" = {}; - "docs" = {}; - "diff" = {}; - "terminal" = {}; - "problems" = {}; - "folder" = {}; - "codebase" = {}; - }; - }; - }; - - config = - lib.mkIf ai-tooling-enabled - (lib.mkMerge [ - { - home = { - file = { - ".continue/config.yaml".source = (pkgs.formats.yaml {}).generate "continue-config" { - name = "Assistant"; - version = "1.0.0"; - schema = "v1"; - models = lib.attrsets.attrValues osConfig.host.ai.models; - context = lib.attrsets.attrValues config.user.continue.context; - docs = lib.attrsets.attrValues config.user.continue.docs; - }; - }; - }; - } - (lib.mkIf osConfig.host.impermanence.enable { - home.persistence."/persist${config.home.homeDirectory}" = { - directories = [ - ".continue/index" - ".continue/sessions" - ]; - allowOther = true; - }; - }) - ]); -} diff --git a/modules/home-manager-modules/default.nix b/modules/home-manager-modules/default.nix index 73876f4..4c085a5 100644 --- a/modules/home-manager-modules/default.nix +++ b/modules/home-manager-modules/default.nix @@ -6,7 +6,7 @@ ./flipperzero.nix ./i18n.nix ./openssh.nix - ./continue.nix + ./gnome.nix ./programs ]; } diff --git a/modules/home-manager-modules/gnome.nix b/modules/home-manager-modules/gnome.nix new file mode 100644 index 0000000..8c70cf6 --- /dev/null +++ b/modules/home-manager-modules/gnome.nix @@ -0,0 +1,106 @@ +{ + lib, + config, + ... +}: { + options.gnome = { + extraWindowControls = lib.mkEnableOption "Should we add back in the minimize and maximize window controls?"; + clockFormat = lib.mkOption { + type = lib.types.enum [ + "12h" + "24h" + ]; + default = "24h"; + }; + colorScheme = lib.mkOption { + type = lib.types.enum [ + "default" + "prefer-dark" + "prefer-light" + ]; + default = "default"; + }; + accentColor = lib.mkOption { + type = lib.types.enum [ + "blue" + "teal" + "green" + "yellow" + "orange" + "red" + "pink" + "purple" + "slate" + ]; + default = "blue"; + }; + extensions = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = []; + description = "The set of extensions to install and enable in the user environment."; + }; + hotkeys = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({name, ...}: { + options = { + key = lib.mkOption { + type = lib.types.strMatching "[a-zA-Z0-9-]+"; + default = builtins.replaceStrings [" " "/" "_"] ["-" "-" "-"] name; + }; + name = lib.mkOption { + type = lib.types.str; + default = name; + }; + binding = lib.mkOption { + type = lib.types.str; + }; + command = lib.mkOption { + type = lib.types.str; + }; + }; + })); + default = {}; + }; + }; + + config = { + home.packages = config.gnome.extensions; + dconf = { + settings = lib.mkMerge [ + { + "org/gnome/shell" = { + disable-user-extensions = false; # enables user extensions + enabled-extensions = builtins.map (extension: extension.extensionUuid) config.gnome.extensions; + }; + + "org/gnome/desktop/wm/preferences".button-layout = lib.mkIf config.gnome.extraWindowControls ":minimize,maximize,close"; + + "org/gnome/desktop/interface".color-scheme = config.gnome.colorScheme; + "org/gnome/desktop/interface".accent-color = config.gnome.accentColor; + "org/gnome/desktop/interface".clock-format = config.gnome.clockFormat; + } + ( + lib.mkMerge ( + builtins.map (value: let + entry = "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${value.key}"; + in { + ${entry} = { + binding = value.binding; + command = value.command; + name = value.name; + }; + + "org/gnome/settings-daemon/plugins/media-keys" = { + custom-keybindings = [ + "/${entry}/" + ]; + }; + }) + ( + lib.attrsets.mapAttrsToList (_: value: value) config.gnome.hotkeys + ) + ) + ) + ]; + }; + }; +} diff --git a/modules/home-manager-modules/programs/anki.nix b/modules/home-manager-modules/programs/anki.nix index 083d205..c2f93ea 100644 --- a/modules/home-manager-modules/programs/anki.nix +++ b/modules/home-manager-modules/programs/anki.nix @@ -1,29 +1,15 @@ { lib, - pkgs, config, osConfig, ... }: { - options.programs.anki = { - enable = lib.mkEnableOption "enable anki"; - }; - - config = lib.mkIf config.programs.anki.enable (lib.mkMerge [ - { - home.packages = with pkgs; [ - anki + config = lib.mkIf (config.programs.anki.enable && osConfig.host.impermanence.enable) { + home.persistence."/persist${config.home.homeDirectory}" = { + directories = [ + "${config.xdg.dataHome}/Anki2/" ]; - } - ( - lib.mkIf osConfig.host.impermanence.enable { - home.persistence."/persist${config.home.homeDirectory}" = { - directories = [ - "${config.xdg.dataHome}/Anki2/" - ]; - allowOther = true; - }; - } - ) - ]); + allowOther = true; + }; + }; } diff --git a/modules/nixos-modules/impermanence.nix b/modules/nixos-modules/impermanence.nix index 2f38cd3..7735e97 100644 --- a/modules/nixos-modules/impermanence.nix +++ b/modules/nixos-modules/impermanence.nix @@ -25,6 +25,18 @@ } ]; + # fixes issues with /var/lib/private not having the correct permissions https://github.com/nix-community/impermanence/issues/254 + system.activationScripts."createPersistentStorageDirs".deps = ["var-lib-private-permissions" "users" "groups"]; + system.activationScripts = { + "var-lib-private-permissions" = { + deps = ["specialfs"]; + text = '' + mkdir -p /persist/system/root/var/lib/private + chmod 0700 /persist/system/root/var/lib/private + ''; + }; + }; + programs.fuse.userAllowOther = true; boot.initrd.postResumeCommands = lib.mkAfter '' diff --git a/modules/nixos-modules/ollama.nix b/modules/nixos-modules/ollama.nix index a29a9aa..99819bf 100644 --- a/modules/nixos-modules/ollama.nix +++ b/modules/nixos-modules/ollama.nix @@ -28,10 +28,6 @@ }; })) (lib.mkIf config.host.impermanence.enable { - # TODO: move this somewhere common - systemd.tmpfiles.rules = [ - "d /var/lib/private 0700 root root" - ]; environment.persistence."/persist/system/root" = { enable = true; hideMounts = true; diff --git a/modules/nixos-modules/server/adguardhome.nix b/modules/nixos-modules/server/adguardhome.nix deleted file mode 100644 index 866ad8a..0000000 --- a/modules/nixos-modules/server/adguardhome.nix +++ /dev/null @@ -1,72 +0,0 @@ -{ - lib, - config, - ... -}: let - dnsPort = 53; -in { - options.host.adguardhome = { - enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; - directory = lib.mkOption { - type = lib.types.str; - default = "/var/lib/AdGuardHome/"; - }; - }; - config = lib.mkIf config.host.adguardhome.enable (lib.mkMerge [ - { - services.adguardhome = { - enable = true; - mutableSettings = false; - settings = { - dns = { - bootstrap_dns = [ - "1.1.1.1" - "9.9.9.9" - ]; - upstream_dns = [ - "dns.quad9.net" - ]; - }; - filtering = { - protection_enabled = true; - filtering_enabled = true; - - parental_enabled = false; # Parental control-based DNS requests filtering. - safe_search = { - enabled = false; # Enforcing "Safe search" option for search engines, when possible. - }; - }; - # The following notation uses map - # to not have to manually create {enabled = true; url = "";} for every filter - # This is, however, fully optional - filters = - map (url: { - enabled = true; - url = url; - }) [ - "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt" - "https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt" # The Big List of Hacked Malware Web Sites - "https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt" # malicious url blocklist - ]; - }; - }; - - networking.firewall.allowedTCPPorts = [ - dnsPort - ]; - } - (lib.mkIf config.host.impermanence.enable { - environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; - directories = [ - { - directory = config.host.adguardhome.directory; - user = "adguardhome"; - group = "adguardhome"; - } - ]; - }; - }) - ]); -} diff --git a/modules/nixos-modules/server/default.nix b/modules/nixos-modules/server/default.nix index 7beee8b..95c7096 100644 --- a/modules/nixos-modules/server/default.nix +++ b/modules/nixos-modules/server/default.nix @@ -8,9 +8,10 @@ ./jellyfin.nix ./forgejo.nix ./searx.nix - ./virt-home-assistant.nix - ./adguardhome.nix + ./home-assistant.nix + ./wyoming.nix ./immich.nix ./qbittorent.nix + ./paperless.nix ]; } diff --git a/modules/nixos-modules/server/fail2ban.nix b/modules/nixos-modules/server/fail2ban.nix index be83e6f..d19aeeb 100644 --- a/modules/nixos-modules/server/fail2ban.nix +++ b/modules/nixos-modules/server/fail2ban.nix @@ -16,20 +16,6 @@ in { failregex = "limiting requests, excess:.* by zone.*client: " '') ); - # "fail2ban/filter.d/hass.local".text = lib.mkIf config.services.home-assistant.enable ( - # pkgs.lib.mkDefault (pkgs.lib.mkAfter '' - # [INCLUDES] - # before = common.conf - - # [Definition] - # failregex = ^%(__prefix_line)s.*Login attempt or request with invalid authentication from .*$ - - # ignoreregex = - - # [Init] - # datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S - # '') - # ); }; services.fail2ban = { @@ -61,16 +47,6 @@ in { bantime = 600; maxretry = 5; }; - # home-assistant-iptables.settings = lib.mkIf config.services.home-assistant.enable { - # enabled = true; - # filter = "hass"; - # action = ''iptables-multiport[name=HTTP, port="http,https"]''; - # logpath = "${config.services.home-assistant.configDir}/*.log"; - # backend = "auto"; - # findtime = 600; - # bantime = 600; - # maxretry = 5; - # }; # TODO; figure out if there is any fail2ban things we can do on searx # searx-iptables.settings = lib.mkIf config.services.searx.enable {}; }; diff --git a/modules/nixos-modules/server/forgejo.nix b/modules/nixos-modules/server/forgejo.nix index 40a5303..7898daa 100644 --- a/modules/nixos-modules/server/forgejo.nix +++ b/modules/nixos-modules/server/forgejo.nix @@ -28,6 +28,12 @@ in { extraUsers = { ${db_user} = { isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${db_user} = { + name = db_user; }; }; }; diff --git a/modules/nixos-modules/server/home-assistant.nix b/modules/nixos-modules/server/home-assistant.nix index a90bd6d..57bedc1 100644 --- a/modules/nixos-modules/server/home-assistant.nix +++ b/modules/nixos-modules/server/home-assistant.nix @@ -1,130 +1,229 @@ { lib, + pkgs, config, - inputs, ... }: let configDir = "/var/lib/hass"; + dbUser = "hass"; in { - options.host.home-assistant = { - enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; + options.services.home-assistant = { subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that home-assistant will be hosted at"; default = "home-assistant"; }; + + database = lib.mkOption { + type = lib.types.enum [ + "builtin" + "postgres" + ]; + description = "what database do we want to use"; + default = "builtin"; + }; + + 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.host.home-assistant.enable (lib.mkMerge [ + config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [ { - virtualisation.libvirt = { - swtpm.enable = true; - connections."qemu:///session" = { - networks = [ - { - definition = inputs.nix-virt.lib.network.writeXML (inputs.nix-virt.lib.network.templates.bridge - { - uuid = "d57e37e2-311f-4e5c-a484-97c2210c2770"; - subnet_byte = 71; - }); - active = true; - } - ]; - domains = [ - { - definition = inputs.nix-virt.lib.domain.writeXML (inputs.nix-virt.lib.domain.templates.linux - { - name = "Home Assistant"; - uuid = "c5cc0efc-6101-4c1d-be31-acbba203ccde"; - memory = { - count = 4; - unit = "GiB"; - }; - # storage_vol = { - # pool = "MyPool"; - # volume = "Penguin.qcow2"; - # }; - }); - } - ]; + host = { + reverse_proxy.subdomains.${config.services.home-assistant.subdomain} = { + target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; + + websockets.enable = true; + forwardHeaders.enable = true; + + extraConfig = '' + add_header Upgrade $http_upgrade; + add_header Connection \"upgrade\"; + + proxy_buffering off; + + proxy_read_timeout 90; + ''; }; }; - # systemd.tmpfiles.rules = [ - # "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" - # ]; - # services.home-assistant = { - # enable = true; - # configDir = configDir; - # extraComponents = [ - # "met" - # "radio_browser" - # "isal" - # "zha" - # "jellyfin" - # "webostv" - # "tailscale" - # "syncthing" - # "sonos" - # "analytics_insights" - # "unifi" - # "openweathermap" - # ]; - # config = { - # http = { - # server_port = 8082; - # use_x_forwarded_for = true; - # trusted_proxies = ["127.0.0.1" "::1"]; - # ip_ban_enabled = true; - # login_attempts_threshold = 10; - # }; - # # recorder.db_url = "postgresql://@/${db_user}"; - # "automation manual" = []; - # "automation ui" = "!include automations.yaml"; - # }; - # extraPackages = python3Packages: - # with python3Packages; [ - # hassil - # numpy - # gtts - # ]; - # }; - # host = { - # reverse_proxy.subdomains.${config.host.home-assistant.subdomain} = { - # target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; + services.home-assistant = { + configDir = configDir; + extraComponents = [ + "default_config" + "esphome" + "met" + "radio_browser" + "isal" + "zha" + "webostv" + "tailscale" + "syncthing" + "analytics_insights" + "unifi" + "openweathermap" + "ollama" + "mobile_app" + "logbook" + "ssdp" + "usb" + "webhook" + "bluetooth" + "dhcp" + "energy" + "history" + "backup" + "assist_pipeline" + "conversation" + "sun" + "zeroconf" + "cpuspeed" + ]; + config = { + http = { + server_port = 8123; + use_x_forwarded_for = true; + trusted_proxies = ["127.0.0.1" "::1"]; + ip_ban_enabled = true; + login_attempts_threshold = 10; + }; + homeassistant = { + external_url = "https://${config.services.home-assistant.subdomain}.${config.host.reverse_proxy.hostname}"; + # internal_url = "http://192.168.1.2:8123"; + }; + recorder.db_url = "postgresql://@/${dbUser}"; + "automation manual" = []; + "automation ui" = "!include automations.yaml"; + mobile_app = {}; + }; + extraPackages = python3Packages: + with python3Packages; [ + hassil + numpy + gtts + ]; + }; - # websockets.enable = true; - # forwardHeaders.enable = true; + # TODO: configure /var/lib/hass/secrets.yaml via sops - # extraConfig = '' - # add_header Upgrade $http_upgrade; - # add_header Connection \"upgrade\"; + networking.firewall.allowedUDPPorts = [ + 1900 + ]; - # proxy_buffering off; - - # proxy_read_timeout 90; - # ''; - # }; - # }; + systemd.tmpfiles.rules = [ + "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" + ]; } + (lib.mkIf (config.services.home-assistant.extensions.sonos.enable) { + services.home-assistant.extraComponents = ["sonos"]; + networking.firewall.allowedTCPPorts = [ + config.services.home-assistant.extensions.sonos.port + ]; + }) + (lib.mkIf (config.services.home-assistant.extensions.jellyfin.enable) { + services.home-assistant.extraComponents = ["jellyfin"]; + # TODO: configure port, address, and login information here + }) + (lib.mkIf (config.services.home-assistant.extensions.wyoming.enable) { + services.home-assistant.extraComponents = ["wyoming"]; + services.wyoming.enable = true; + }) + (lib.mkIf (config.services.home-assistant.database == "postgres") { + host = { + postgres = { + enable = true; + extraUsers = { + ${dbUser} = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${dbUser} = { + name = dbUser; + }; + }; + }; + }; + + services.home-assistant = { + extraPackages = python3Packages: + with python3Packages; [ + psycopg2 + ]; + }; + + systemd.services.home-assistant = { + requires = [ + config.systemd.services.postgresql.name + ]; + }; + }) + (lib.mkIf config.services.fail2ban.enable { + environment.etc = { + "fail2ban/filter.d/hass.local".text = lib.mkIf config.services.home-assistant.enable ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [INCLUDES] + before = common.conf + + [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 = lib.mkIf config.services.home-assistant.enable { + enabled = true; + filter = "hass"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.home-assistant.configDir}/*.log"; + backend = "auto"; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + }; + }; + }) (lib.mkIf config.host.impermanence.enable { - # assertions = [ - # { - # assertion = config.services.home-assistant.configDir == configDir; - # message = "home assistant config directory does not match persistence"; - # } - # ]; - # environment.persistence."/persist/system/root" = { - # enable = true; - # hideMounts = true; - # directories = [ - # { - # directory = configDir; - # user = "hass"; - # group = "hass"; - # } - # ]; - # }; + assertions = [ + { + assertion = config.services.home-assistant.configDir == configDir; + message = "home assistant config directory does not match persistence"; + } + ]; + environment.persistence."/persist/system/root" = { + enable = true; + hideMounts = true; + directories = [ + { + directory = configDir; + user = "hass"; + group = "hass"; + } + ]; + }; }) ]); } diff --git a/modules/nixos-modules/server/jellyfin.nix b/modules/nixos-modules/server/jellyfin.nix index a8bbe71..bad04c9 100644 --- a/modules/nixos-modules/server/jellyfin.nix +++ b/modules/nixos-modules/server/jellyfin.nix @@ -55,7 +55,7 @@ in { } (lib.mkIf config.services.fail2ban.enable { environment.etc = { - "fail2ban/filter.d/jellyfin.local".text = lib.mkIf config.services.jellyfin.enable ( + "fail2ban/filter.d/jellyfin.local".text = ( pkgs.lib.mkDefault (pkgs.lib.mkAfter '' [Definition] failregex = "^.*Authentication request for .* has been denied \\\(IP: \"\"\\\)\\\." @@ -65,7 +65,7 @@ in { services.fail2ban = { jails = { - jellyfin-iptables.settings = lib.mkIf config.services.jellyfin.enable { + jellyfin-iptables.settings = { enabled = true; filter = "jellyfin"; action = ''iptables-multiport[name=HTTP, port="http,https"]''; diff --git a/modules/nixos-modules/server/paperless.nix b/modules/nixos-modules/server/paperless.nix new file mode 100644 index 0000000..0243d53 --- /dev/null +++ b/modules/nixos-modules/server/paperless.nix @@ -0,0 +1,110 @@ +{ + config, + lib, + pkgs, + ... +}: let + dataDir = "/var/lib/paperless"; +in { + options.services.paperless = { + subdomain = lib.mkOption { + type = lib.types.str; + description = "subdomain of base domain that paperless will be hosted at"; + default = "paperless"; + }; + database = { + user = lib.mkOption { + type = lib.types.str; + description = "what is the user and database that we are going to use for paperless"; + default = "paperless"; + }; + }; + }; + + config = lib.mkIf config.services.paperless.enable (lib.mkMerge [ + { + host = { + reverse_proxy.subdomains.${config.services.paperless.subdomain} = { + target = "http://${config.services.paperless.address}:${toString config.services.paperless.port}"; + + websockets.enable = true; + forwardHeaders.enable = true; + + extraConfig = '' + # allow large file uploads + client_max_body_size 50000M; + ''; + }; + postgres = { + enable = true; + extraUsers = { + ${config.services.paperless.database.user} = { + isClient = true; + createUser = true; + }; + }; + extraDatabases = { + ${config.services.paperless.database.user} = { + name = config.services.paperless.database.user; + }; + }; + }; + }; + services.paperless = { + configureTika = true; + settings = { + PAPERLESS_URL = "https://${config.services.paperless.subdomain}.${config.host.reverse_proxy.hostname}"; + + PAPERLESS_DBENGINE = "postgresql"; + PAPERLESS_DBHOST = "/run/postgresql"; + PAPERLESS_DBNAME = config.services.paperless.database.user; + PAPERLESS_DBUSER = config.services.paperless.database.user; + }; + }; + } + (lib.mkIf config.services.fail2ban.enable { + environment.etc = { + "fail2ban/filter.d/paperless.local".text = ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [Definition] + failregex = Login failed for user `.*` from (?:IP|private IP) ``\.$ + ignoreregex = + + '') + ); + }; + + services.fail2ban = { + jails = { + paperless.settings = { + enabled = true; + filter = "paperless"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.paperless.dataDir}/log/*.log"; + backend = "auto"; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + }; + }; + }) + (lib.mkIf config.host.impermanence.enable { + assertions = [ + { + assertion = config.services.paperless.dataDir == dataDir; + message = "paperless data location does not match persistence"; + } + ]; + environment.persistence."/persist/system/root" = { + directories = [ + { + directory = dataDir; + user = "paperless"; + group = "paperless"; + } + ]; + }; + }) + ]); +} diff --git a/modules/nixos-modules/server/podman.nix b/modules/nixos-modules/server/podman.nix index e806e65..9301140 100644 --- a/modules/nixos-modules/server/podman.nix +++ b/modules/nixos-modules/server/podman.nix @@ -4,7 +4,7 @@ ... }: { options.host.podman = { - enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; + enable = lib.mkEnableOption "should podman be enabled on this computer"; macvlan = { subnet = lib.mkOption { type = lib.types.str; diff --git a/modules/nixos-modules/server/virt-home-assistant.nix b/modules/nixos-modules/server/virt-home-assistant.nix deleted file mode 100644 index 4212668..0000000 --- a/modules/nixos-modules/server/virt-home-assistant.nix +++ /dev/null @@ -1,155 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: { - options.services.virt-home-assistant = { - enable = lib.mkEnableOption "Wether to enable home assistant virtual machine"; - networkBridge = lib.mkOption { - type = lib.types.str; - description = "what network bridge should we attach to the image"; - }; - hostDevice = lib.mkOption { - type = lib.types.str; - description = "what host devices should be attached to the image"; - }; - initialVersion = lib.mkOption { - type = lib.types.str; - description = "what home assistant image version should we pull for initial instal"; - default = "15.0"; - }; - imageName = lib.mkOption { - type = lib.types.str; - description = "where should the image be installed to"; - default = "home-assistant.qcow2"; - }; - installLocation = lib.mkOption { - type = lib.types.str; - description = "where should the image be installed to"; - default = "/etc/hass"; - }; - virtualMachineName = lib.mkOption { - type = lib.types.str; - description = "what name should we give the virtual machine"; - default = "home-assistant"; - }; - subdomain = lib.mkOption { - type = lib.types.str; - description = "subdomain of base domain that home-assistant will be hosted at"; - default = "home-assistant"; - }; - }; - config = lib.mkIf config.services.virt-home-assistant.enable (lib.mkMerge [ - { - # environment.systemPackages = with pkgs; [ - # virt-manager - # ]; - - # TODO: move this to external module and just have an assertion here that its enabled - # enable virtualization on the system - virtualisation = { - libvirtd = { - enable = true; - qemu.ovmf.enable = true; - }; - }; - - # TODO: deactivation script? - # create service to install and start the container - systemd.services.virt-install-home-assistant = let - # TODO: all of these need to be escaped to be used in commands reliably - bridgedNetwork = config.services.virt-home-assistant.networkBridge; - hostDevice = config.services.virt-home-assistant.hostDevice; - virtualMachineName = config.services.virt-home-assistant.virtualMachineName; - imageName = config.services.virt-home-assistant.imageName; - installLocation = config.services.virt-home-assistant.installLocation; - installImage = "${installLocation}/${imageName}"; - initialVersion = config.services.virt-home-assistant.initialVersion; - - home-assistant-qcow2 = pkgs.fetchurl { - name = "home-assistant.qcow2"; - url = "https://github.com/home-assistant/operating-system/releases/download/${initialVersion}/haos_ova-${initialVersion}.qcow2.xz"; - hash = "sha256-V1BEjvvLNbMMKJVyMCmipjQ/3owoJteeVxoF9LDHo1U="; - postFetch = '' - cp $out src.xz - rm -r $out - ${pkgs.xz}/bin/unxz src.xz --stdout > $out/${imageName} - ''; - }; - - # Write a script to install the Home Assistant OS qcow2 image - virtInstallScript = pkgs.writeShellScriptBin "virt-install-hass" '' - # Copy the initial image out of the package store to the install location if we don't have one yet - if [ ! -f ${installImage} ]; then - cp ${home-assistant-qcow2} ${installLocation} - fi - - # Check if VM already exists, and other pre-conditions - if ! ${pkgs.libvirt}/bin/virsh list --all | grep -q ${virtualMachineName}; then - ${pkgs.virt-manager}/bin/virt-install --name ${virtualMachineName} \ - --description "Home Assistant OS" \ - --os-variant=generic \ - --boot uefi \ - --ram=2048 \ - --vcpus=2 \ - --import \ - --disk ${installImage},bus=sata \ - --network bridge=${bridgedNetwork} \ - --host-device ${hostDevice} \ - --graphics none - ${pkgs.libvirt}/bin/virsh autostart ${virtualMachineName} - fi - ''; - in { - description = "Install and start Home Assistant"; - wantedBy = ["multi-user.target"]; - after = ["local-fs.target"]; - requires = ["libvirtd.service"]; - serviceConfig.Type = "oneshot"; - serviceConfig = { - ExecStart = "${virtInstallScript}/bin/virt-install-hass"; - }; - }; - - # TODO: figure out what we need to proxy to the virtual image - # host = { - # reverse_proxy.subdomains.${config.services.virt-home-assistant.subdomain} = { - # target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}"; - - # websockets.enable = true; - # forwardHeaders.enable = true; - - # extraConfig = '' - # add_header Upgrade $http_upgrade; - # add_header Connection \"upgrade\"; - - # proxy_buffering off; - - # proxy_read_timeout 90; - # ''; - # }; - # }; - } - (lib.mkIf config.services.fail2ban.enable { - # TODO: figure out how to write a config for this, prob based on nginx proxy logs? - }) - (lib.mkIf config.host.impermanence.enable { - # assertions = [ - # { - # assertion = config.services.virt-home-assistant.installLocation == configDir; - # message = "home assistant install location does not match persistence"; - # } - # ]; - environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; - directories = [ - { - directory = config.services.virt-home-assistant.installLocation; - } - ]; - }; - }) - ]); -} diff --git a/modules/nixos-modules/server/wyoming.nix b/modules/nixos-modules/server/wyoming.nix new file mode 100644 index 0000000..4894dd4 --- /dev/null +++ b/modules/nixos-modules/server/wyoming.nix @@ -0,0 +1,63 @@ +{ + lib, + config, + ... +}: { + options.services.wyoming.enable = lib.mkEnableOption "should wyoming be enabled on this device"; + config = lib.mkIf config.services.wyoming.enable (lib.mkMerge [ + { + services.wyoming = { + # Text to speech + piper = { + servers = { + "en" = { + enable = true; + # see https://github.com/rhasspy/rhasspy3/blob/master/programs/tts/piper/script/download.py + voice = "en-us-amy-low"; + uri = "tcp://0.0.0.0:10200"; + speaker = 0; + }; + }; + }; + + # Speech to text + faster-whisper = { + servers = { + "en" = { + enable = true; + # see https://github.com/rhasspy/rhasspy3/blob/master/programs/asr/faster-whisper/script/download.py + model = "tiny-int8"; + language = "en"; + uri = "tcp://0.0.0.0:10300"; + device = "cpu"; + }; + }; + }; + + openwakeword = { + enable = true; + uri = "tcp://0.0.0.0:10400"; + preloadModels = [ + "ok_nabu" + ]; + # TODO: custom models + }; + }; + + # needs access to /proc/cpuinfo + systemd.services."wyoming-faster-whisper-en".serviceConfig.ProcSubset = lib.mkForce "all"; + } + (lib.mkIf config.host.impermanence.enable { + environment.persistence."/persist/system/root" = { + enable = true; + hideMounts = true; + directories = [ + { + directory = "/var/lib/private/wyoming"; + mode = "0700"; + } + ]; + }; + }) + ]); +} diff --git a/modules/nixos-modules/users.nix b/modules/nixos-modules/users.nix index 68bd78b..a774e44 100644 --- a/modules/nixos-modules/users.nix +++ b/modules/nixos-modules/users.nix @@ -24,6 +24,7 @@ git = 2009; immich = 2010; qbittorrent = 2011; + paperless = 2012; }; gids = { @@ -40,6 +41,7 @@ git = 2009; immich = 2010; qbittorrent = 2011; + paperless = 2012; }; users = config.users.users; @@ -169,6 +171,12 @@ in { isNormalUser = true; group = config.users.users.qbittorrent.name; }; + + paperless = { + uid = lib.mkForce uids.paperless; + isSystemUser = true; + group = config.users.users.paperless.name; + }; }; groups = { @@ -273,6 +281,13 @@ in { leyla ]; }; + + paperless = { + gid = lib.mkForce gids.paperless; + members = [ + users.paperless.name + ]; + }; }; }; } diff --git a/nix-config-secrets b/nix-config-secrets index 1c5c059..f016767 160000 --- a/nix-config-secrets +++ b/nix-config-secrets @@ -1 +1 @@ -Subproject commit 1c5c059c0c7b6ce691993262fe10a2b63e1c31ba +Subproject commit f016767c13aa36dde91503f7a9f01bdd02468045 diff --git a/rebuild.sh b/rebuild.sh index 32fd303..36a1201 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -65,7 +65,7 @@ flake=${flake:-$target} mode=${mode:-switch} user=${user:-$USER} -command="nixos-rebuild $mode --use-remote-sudo --ask-sudo-password --flake .#$flake" +command="nixos-rebuild $mode --sudo --ask-sudo-password --flake .#$flake" if [[ $host ]]; then