From b2f9f5a25393d39f11f74aebc0500647c134142b Mon Sep 17 00:00:00 2001 From: Mohammad Rafiq Date: Mon, 2 Jun 2025 17:04:45 +0800 Subject: [PATCH] feat(nixosModules/server): add librechat from my fork --- flake.lock | 19 ++- flake.nix | 2 +- modules/nixos/server/librechat/default.nix | 182 ++++++--------------- systems/x86_64-linux/apollo/default.nix | 44 +---- systems/x86_64-linux/nemesis/default.nix | 47 ------ 5 files changed, 61 insertions(+), 233 deletions(-) diff --git a/flake.lock b/flake.lock index 7ec1ade..b69cffb 100644 --- a/flake.lock +++ b/flake.lock @@ -531,17 +531,18 @@ }, "rrvsh-nixpkgs": { "locked": { - "lastModified": 1748824126, - "narHash": "sha256-EjrHRlTvzECAFH0YSfR+kcK1Q1qDDVX0mQatjpvzwGo=", - "ref": "refs/heads/librechat-module", - "rev": "b6ef5cc34d3699f505e09308b16fe7c0ea8178fc", - "revCount": 808478, - "type": "git", - "url": "file:///home/rafiq/repos/nixpkgs" + "lastModified": 1748853793, + "narHash": "sha256-UoWP2Y4r6ntlFNj02afKRukNDTMj/ufKfvNhRwzqzS8=", + "owner": "rrvsh", + "repo": "nixpkgs", + "rev": "eb9aad05033afb7ed417cb187480d20c8daa08b7", + "type": "github" }, "original": { - "type": "git", - "url": "file:///home/rafiq/repos/nixpkgs" + "owner": "rrvsh", + "ref": "librechat-module", + "repo": "nixpkgs", + "type": "github" } }, "rust-overlay": { diff --git a/flake.nix b/flake.nix index cf718fe..14f6938 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ { inputs = { - rrvsh-nixpkgs.url = "git+file:///home/rafiq/repos/nixpkgs"; + rrvsh-nixpkgs.url = "github:rrvsh/nixpkgs/librechat-module"; crane.url = "github:ipetkov/crane"; disko.inputs.nixpkgs.follows = "nixpkgs"; disko.url = "github:nix-community/disko"; diff --git a/modules/nixos/server/librechat/default.nix b/modules/nixos/server/librechat/default.nix index 2e95421..736a2e9 100644 --- a/modules/nixos/server/librechat/default.nix +++ b/modules/nixos/server/librechat/default.nix @@ -1,4 +1,5 @@ { + inputs, config, lib, pkgs, @@ -6,147 +7,60 @@ }: let cfg = config.server.librechat; - configFile = pkgs.writeTextFile { - name = "librechat.yaml"; - text = lib.generators.toYAML { } cfg.settings; - }; - # Thanks to https://github.com/nix-community/home-manager/blob/60e4624302d956fe94d3f7d96a560d14d70591b9/modules/lib/shell.nix :) - export = n: v: ''export ${n}="${builtins.toString v}"''; - exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars); - exportCredentials = n: _: ''export ${n}="$(${pkgs.systemd}/bin/systemd-creds cat ${n}_FILE)"''; - exportAllCredentials = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList exportCredentials vars); - transformCredential = n: v: "${n}_FILE:${v}"; - getLoadCredentialList = lib.mapAttrsToList transformCredential cfg.credentials; - environmentVariablesFile = pkgs.writeTextFile { - name = "librechat-env-variables.sh"; - text = # sh - '' - # Thanks to https://github.com/nix-community/home-manager/blob/release-25.05/modules/home-environment.nix :) - # Only source this once. - if [ -n "$__LC_ENV_VARS_SOURCED" ]; then return; fi - export __LC_ENV_VARS_SOURCED=1 - - export CONFIG_PATH=${configFile} - ${exportAll cfg.env} - ${exportAllCredentials cfg.credentials} - ''; - }; - allowedPorts = - if cfg.openFirewall then (if cfg.env ? PORT then [ cfg.env.port ] else [ 3080 ]) else [ ]; in { + + imports = [ + "${inputs.rrvsh-nixpkgs}/nixos/modules/services/web-apps/librechat.nix" + ]; + options.server.librechat = { - enable = lib.mkEnableOption "Whether to enable the LibreChat server."; - openFirewall = lib.mkEnableOption "Whether to open the port in the firewall."; - path = lib.mkOption { - type = lib.types.str; - default = "/var/lib/librechat"; - description = "Absolute path for where the LibreChat server will use as its working directory."; - }; - user = lib.mkOption { - type = lib.types.str; - default = "librechat"; - description = "The user to run the service as."; - }; - group = lib.mkOption { - type = lib.types.str; - default = "librechat"; - description = "The group to run the service as."; - }; - credentials = lib.mkOption { - type = lib.types.lazyAttrsOf lib.types.path; - default = { }; - example = { - CREDS_KEY = /run/secrets/creds_key; - }; - description = "Environment variables which are loaded from the contents of files at a file paths, mainly used for secrets. See https://www.librechat.ai/docs/configuration/dotenv for a full list."; - }; - env = lib.mkOption { - type = - with lib.types; - lazyAttrsOf (oneOf [ - str - path - int - float - ]); - example = { - ALLOW_REGISTRATION = "true"; - HOST = "0.0.0.0"; - CONSOLE_JSON_STRING_LENGTH = 255; - }; - default = { }; - description = "Environment variables that will be set for the service. See https://www.librechat.ai/docs/configuration/dotenv for a full list."; - }; - settings = lib.mkOption { - type = lib.types.attrs; - default = { }; - example = # nix - '' - { - version = "1.0.8"; - cache = true; - interface = { - privacyPolicy = { - externalUrl = "https://librechat.ai/privacy-policy"; - openNewTab = true; - }; - }; - endpoints = { - custom = [ - { - name = "OpenRouter"; - # Note that the following $ should be escaped with a backslash, not ''' - apiKey = "''${OPENROUTER_KEY}"; - baseURL = "https://openrouter.ai/api/v1"; - models = { - default = ["meta-llama/llama-3-70b-instruct"]; - fetch = true; - }; - titleConvo = true; - titleModule = "meta-llama/llama-3-70b-instruct"; - dropParams = ["stop"]; - modelDisplayLabel = "OpenRouter"; - } - ]; - }; - } - ''; - description = "A free-form attribute set that will be written to librechat.yaml. You can use environment variables by wrapping them in \${}. Take care to escape the \$ character."; - }; + enable = lib.mkEnableOption ""; }; config = lib.mkIf cfg.enable { - networking.firewall.allowedTCPPorts = allowedPorts; - systemd.services.librechat = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - description = "Open-source app for all your AI conversations, fully customizable and compatible with any AI provider"; - serviceConfig = { - Type = "simple"; - User = cfg.user; - Group = cfg.group; - PermissionsStartOnly = "true"; # run mkdir as root - ExecStartPre = [ - "${pkgs.coreutils}/bin/mkdir -p ${cfg.path}" - "${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${cfg.path}" - "${pkgs.coreutils}/bin/chmod 775 ${cfg.path}" - ]; - LoadCredential = getLoadCredentialList; + services.librechat = { + enable = true; + openFirewall = true; + port = 3080; + env = { + HOST = "0.0.0.0"; + ALLOW_REGISTRATION = "true"; + MONGO_URI = "mongodb://apollo:27017"; + }; + credentials = { + CREDS_KEY = config.sops.secrets."librechat/creds_key".path; + CREDS_IV = config.sops.secrets."librechat/creds_iv".path; + JWT_SECRET = config.sops.secrets."librechat/jwt_secret".path; + JWT_REFRESH_SECRET = config.sops.secrets."librechat/jwt_refresh_secret".path; + }; + settings = { + version = "1.0.8"; + cache = true; + interface = { + privacyPolicy = { + externalUrl = "https://librechat.ai/privacy-policy"; + openNewTab = true; + }; + }; + endpoints = { + custom = [ + { + name = "OpenRouter"; + apiKey = "\${OPENROUTER_KEY}"; + baseURL = "https://openrouter.ai/api/v1"; + models = { + default = [ "meta-llama/llama-3-70b-instruct" ]; + fetch = true; + }; + titleConvo = true; + titleModule = "meta-llama/llama-3-70b-instruct"; + dropParams = [ "stop" ]; + modelDisplayLabel = "OpenRouter"; + } + ]; + }; }; - script = # sh - '' - cd ${cfg.path} - source ${environmentVariablesFile} - ${pkgs.librechat}/bin/librechat-server - ''; }; - users.users.librechat = lib.mkIf (cfg.user == "librechat") { - name = "librechat"; - isSystemUser = true; - group = "librechat"; - description = "LibreChat server user"; - }; - users.groups.librechat = lib.mkIf (cfg.user == "librechat") { }; }; } diff --git a/systems/x86_64-linux/apollo/default.nix b/systems/x86_64-linux/apollo/default.nix index 10a2988..c73d048 100644 --- a/systems/x86_64-linux/apollo/default.nix +++ b/systems/x86_64-linux/apollo/default.nix @@ -1,10 +1,10 @@ { config, lib, + inputs, ... }: { - system = { hostname = "apollo"; mainUser.name = "rafiq"; @@ -25,47 +25,7 @@ enableDDNS = true; mountHelios = true; databases.mongodb.enable = true; - librechat = { - enable = true; - openFirewall = true; - env = { - HOST = "0.0.0.0"; - MONGO_URI = "mongodb://apollo:27017"; - }; - credentials = { - CREDS_KEY = config.sops.secrets."librechat/creds_key".path; - CREDS_IV = config.sops.secrets."librechat/creds_iv".path; - JWT_SECRET = config.sops.secrets."librechat/jwt_secret".path; - JWT_REFRESH_SECRET = config.sops.secrets."librechat/jwt_refresh_secret".path; - }; - settings = { - version = "1.0.8"; - cache = true; - interface = { - privacyPolicy = { - externalUrl = "https://librechat.ai/privacy-policy"; - openNewTab = true; - }; - }; - endpoints = { - custom = [ - { - name = "OpenRouter"; - apiKey = "\${OPENROUTER_KEY}"; - baseURL = "https://openrouter.ai/api/v1"; - models = { - default = [ "meta-llama/llama-3-70b-instruct" ]; - fetch = true; - }; - titleConvo = true; - titleModule = "meta-llama/llama-3-70b-instruct"; - dropParams = [ "stop" ]; - modelDisplayLabel = "OpenRouter"; - } - ]; - }; - }; - }; + librechat.enable = true; }; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; diff --git a/systems/x86_64-linux/nemesis/default.nix b/systems/x86_64-linux/nemesis/default.nix index fc5eaeb..fa086aa 100644 --- a/systems/x86_64-linux/nemesis/default.nix +++ b/systems/x86_64-linux/nemesis/default.nix @@ -5,10 +5,6 @@ ... }: { - imports = [ - "${inputs.rrvsh-nixpkgs}/nixos/modules/services/web-apps/librechat.nix" - ]; - system = { hostname = "nemesis"; mainUser.name = "rafiq"; @@ -60,48 +56,5 @@ }; }; - services.librechat = { - enable = true; - openFirewall = true; - env = { - HOST = "0.0.0.0"; - ALLOW_REGISTRATION = "true"; - MONGO_URI = "mongodb://apollo:27017"; - }; - credentials = { - CREDS_KEY = config.sops.secrets."librechat/creds_key".path; - CREDS_IV = config.sops.secrets."librechat/creds_iv".path; - JWT_SECRET = config.sops.secrets."librechat/jwt_secret".path; - JWT_REFRESH_SECRET = config.sops.secrets."librechat/jwt_refresh_secret".path; - }; - settings = { - version = "1.0.8"; - cache = true; - interface = { - privacyPolicy = { - externalUrl = "https://librechat.ai/privacy-policy"; - openNewTab = true; - }; - }; - endpoints = { - custom = [ - { - name = "OpenRouter"; - apiKey = "\${OPENROUTER_KEY}"; - baseURL = "https://openrouter.ai/api/v1"; - models = { - default = [ "meta-llama/llama-3-70b-instruct" ]; - fetch = true; - }; - titleConvo = true; - titleModule = "meta-llama/llama-3-70b-instruct"; - dropParams = [ "stop" ]; - modelDisplayLabel = "OpenRouter"; - } - ]; - }; - }; - }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; }