diff --git a/flake.lock b/flake.lock index 8d1fe82..0f754df 100644 --- a/flake.lock +++ b/flake.lock @@ -807,6 +807,26 @@ "type": "github" } }, + "lard": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1785561652, + "narHash": "sha256-6Fz6Rp/fl1frafpWFZM022/MR0T+a4LDkdEh5NdRoZ0=", + "owner": "taciturnaxolotl", + "repo": "lard", + "rev": "efa4251641867c3982a5638d83c141736846bdb3", + "type": "github" + }, + "original": { + "owner": "taciturnaxolotl", + "repo": "lard", + "type": "github" + } + }, "lucide-src": { "flake": false, "locked": { @@ -997,11 +1017,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1784497964, - "narHash": "sha256-vlHUuqAcbcH2RKmHbPiuQzbv1pnzzavXnI62RD0bqCU=", + "lastModified": 1785454630, + "narHash": "sha256-LQy14TZp77TwbQf40gg1V3jo8FwJG0jGDkAH+zRHqg8=", "owner": "nixos", "repo": "nixpkgs", - "rev": "241313f4e8e508cb9b13278c2b0fa25b9ca27163", + "rev": "1559d3daa3ecc813a650b79375ea61b6741b8746", "type": "github" }, "original": { @@ -1315,6 +1335,7 @@ "hyprland-contrib": "hyprland-contrib", "import-tree": "import-tree", "impure": "impure", + "lard": "lard", "nix-darwin": "nix-darwin", "nix-vscode-extensions": "nix-vscode-extensions", "nixarr": "nixarr", diff --git a/flake.nix b/flake.nix index f170a66..d1931f8 100644 --- a/flake.nix +++ b/flake.nix @@ -79,6 +79,11 @@ inputs.nixpkgs.follows = "nixpkgs-unstable"; }; + lard = { + url = "github:taciturnaxolotl/lard"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + flare = { url = "github:ByteAtATime/flare/feat/nix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -177,6 +182,7 @@ pear = inputs.pear.packages.${prev.stdenv.hostPlatform.system}.default; herald = inputs.herald.packages.${prev.stdenv.hostPlatform.system}.default; potluck = inputs.potluck.packages.${prev.stdenv.hostPlatform.system}.default; + lard = inputs.lard.packages.${prev.stdenv.hostPlatform.system}.default; tangle-of-trust = inputs.tangle-of-trust.packages.${prev.stdenv.hostPlatform.system}.default; }) ]; diff --git a/machines/terebithia/default.nix b/machines/terebithia/default.nix index e331234..5ec2d75 100644 --- a/machines/terebithia/default.nix +++ b/machines/terebithia/default.nix @@ -177,6 +177,10 @@ file = ../../secrets/potluck.age; owner = "potluck"; }; + lard = { + file = ../../secrets/lard.age; + owner = "lard"; + }; paperless-oidc = { file = ../../secrets/paperless-oidc.age; owner = "paperless"; @@ -524,6 +528,16 @@ healthUrl = "https://backend.potluck.dunkirk.sh/healthz"; }; + atelier.services.lard = { + enable = true; + domain = "lard.dunkirk.sh"; + secretsFile = config.age.secrets.lard.path; + healthUrl = "https://lard.dunkirk.sh/healthz"; + allowedClientIds = [ "ikc_NEil8GK01UX2O9AvbcDrv" ]; + allowedUsers = [ "https://dunkirk.sh/" ]; + collectorClientId = "ikc_NEil8GK01UX2O9AvbcDrv"; + }; + atelier.services.tangled = { enable = true; owner = "did:plc:krxbvxvis5skq7jj6eot23ul"; diff --git a/modules/nixos/services/lard.nix b/modules/nixos/services/lard.nix new file mode 100644 index 0000000..d8e8372 --- /dev/null +++ b/modules/nixos/services/lard.nix @@ -0,0 +1,77 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + mkService = import ../../lib/mkService.nix; + + baseModule = mkService { + name = "lard"; + description = "Lard — memory layer for homelab LLM sessions"; + defaultPort = 7477; + runtime = "custom"; + startCommand = "${pkgs.lard}/bin/lard"; + + extraOptions = { + authMode = lib.mkOption { + type = lib.types.enum [ + "none" + "token" + "oauth" + ]; + default = "oauth"; + description = "Authentication mode for lard"; + }; + + authServer = lib.mkOption { + type = lib.types.str; + default = "https://indiko.dunkirk.sh"; + description = "Authorization server URL (oauth mode)"; + }; + + allowedClientIds = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "OAuth client IDs allowed to access lard"; + }; + + allowedUsers = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "User identity URLs allowed to access lard"; + }; + + collectorClientId = lib.mkOption { + type = lib.types.str; + default = ""; + description = "OAuth client ID the server publishes for edge collectors to use"; + }; + }; + + extraConfig = cfg: { + atelier.services.lard.environment = { + LARD_ADDR = ":${toString cfg.port}"; + LARD_DB = "${cfg.dataDir}/data/lard.db"; + LARD_MEMORY_DIR = "${cfg.dataDir}/data/memory"; + LARD_AUTH = cfg.authMode; + LARD_AUTH_SERVER = cfg.authServer; + LARD_PUBLIC_URL = "https://${cfg.domain}"; + LARD_OAUTH_CLIENT_IDS = lib.concatStringsSep "," cfg.allowedClientIds; + LARD_OAUTH_USERS = lib.concatStringsSep "," cfg.allowedUsers; + } // lib.optionalAttrs (cfg.collectorClientId != "") { + LARD_COLLECTOR_CLIENT_ID = cfg.collectorClientId; + }; + + atelier.services.lard.data = { + sqlite = "${cfg.dataDir}/data/lard.db"; + files = [ "${cfg.dataDir}/data/memory" ]; + }; + }; + }; +in +{ + imports = [ baseModule ]; +} diff --git a/secrets/lard.age b/secrets/lard.age new file mode 100644 index 0000000000000000000000000000000000000000..e0a803794e9295da588bbbd66322c74f417f4904 GIT binary patch literal 706 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!*`Do#{zDNJ@Z2;|BO4=eZb_f9La z%*jYE*LTqmG){LnDe#M^bjdcY2#tsc&UW@PaQ3jw_i{?BFw`##OZQ7o$u}?YFU&DD zuT1CiPfK#CH1KwJF)zu_H1TvUG%YcXbO{S{O1B6s2{o*;NHtF}^!9ZvE)OuvH>^nX z463jUv`7spNDucc$TD~0@^&%J&Tuqy$@0(4b94@$jNomH^|kt4D-thOz{ZFEQzWx3dtxjsLC}pEp+$yDGCorOyLTO^3JjJDs(I> zi3)VgO!0T|@lNyh&&kaU3Q0CGiS#r{^(rvR@r?90it_e!(@r&yC@M|2tg`e9Ei^Oq z$@Ji|tTc#nw}^E0GBkBAh%yN+j!e?`NOnt2O!3XHC@VG&DAU$2at%!@EiMdAHuo$u zj|ej^4=Q%a%*;y)O)m-J@<}c;%Xcc!E(U-yI z0e6E1k7j;PF;sQ%#V{eQMa#n%DLl=&6_ literal 0 HcmV?d00001 diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 1849730..033f248 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -90,6 +90,9 @@ in "potluck.age".publicKeys = [ kierank ]; + "lard.age".publicKeys = [ + kierank + ]; "protonvpn-wg.age".publicKeys = [ kierank ];