Compare commits
47 commits
feature/li
...
release-25
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ab817090f | |||
| 86afbb213c | |||
| b6546f3ab0 | |||
| 0fc3d4da92 | |||
| a7daa3b9f3 | |||
| dd7fea5711 | |||
| 7613e6cb6b | |||
| fe6b0d6c47 | |||
| fc83c6652d | |||
| da86a8eb57 | |||
| e8f2000053 | |||
| 7d73c46b94 | |||
| 179a02731b | |||
| 8967439585 | |||
| 2323c97d89 | |||
| 529ca4d572 | |||
| 5e963c26ec | |||
| fff1263c85 | |||
| 49c93c82e0 | |||
| fd68579042 | |||
| b3fda57098 | |||
| dad762369c | |||
| d953dd7f8a | |||
| 93cadc467a | |||
| b9736a5f50 | |||
| a43fa6440b | |||
| d31510c64c | |||
| f7a032864c | |||
| 8ad8b1f633 | |||
| 15cbf5d4ff | |||
| 4683cb1136 | |||
| 5f6ad9ecf5 | |||
| e76a05b512 | |||
| a0a39253f4 | |||
| a42c91f99e | |||
| 5aebc805a6 | |||
| e801c318a7 | |||
| c114c6da0a | |||
| 0c13e9dabd | |||
| cff8f40bb0 | |||
| 7a3ecf1545 | |||
| 7e5a951877 | |||
| d093bc3dc6 | |||
| aa1d2bbe48 | |||
| 31f195ff89 | |||
| aea241d610 | |||
| a5e0b2b117 |
10 changed files with 517 additions and 86 deletions
|
|
@ -60,7 +60,7 @@ Rebuild_nixos() {
|
||||||
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
[[ -n "$TARGET_HOST" || -n "$BUILD_HOST" ]] && CMD+=("--ask-sudo-password")
|
||||||
|
|
||||||
# Build config first so we can diff it
|
# Build config first so we can diff it
|
||||||
local BUILD_CMD=("nixos-rebuild" "build" "--flake" "$FLAKE")
|
local BUILD_CMD=("nixos-rebuild" "build" "--no-build-output" "--flake" "$FLAKE")
|
||||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||||
[ -n "$BUILD_HOST" ] && BUILD_CMD+=("--build-host" "$BUILD_HOST")
|
[ -n "$BUILD_HOST" ] && BUILD_CMD+=("--build-host" "$BUILD_HOST")
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ Rebuild_home() {
|
||||||
|
|
||||||
# Build config first so we can diff it
|
# Build config first so we can diff it
|
||||||
if [ "$ROLLBACK" = 0 ]; then
|
if [ "$ROLLBACK" = 0 ]; then
|
||||||
local BUILD_CMD=("home-manager" "build" "--flake" "$FLAKE")
|
local BUILD_CMD=("home-manager" "build" "--no-out-link" "--flake" "$FLAKE")
|
||||||
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
[ "$SHOW_TRACE" = 1 ] && BUILD_CMD+=("--show-trace")
|
||||||
_status "Building Home Manager configuration '$FLAKE'..."
|
_status "Building Home Manager configuration '$FLAKE'..."
|
||||||
_status "Executing command: ${BUILD_CMD[*]}"
|
_status "Executing command: ${BUILD_CMD[*]}"
|
||||||
|
|
|
||||||
46
modules/home/hyprland/applications/bitwarden/default.nix
Normal file
46
modules/home/hyprland/applications/bitwarden/default.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.wayland.windowManager.hyprland;
|
||||||
|
app = cfg.applications.password-manager.default;
|
||||||
|
|
||||||
|
inherit (lib) mkDefault mkIf;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ../../../rofi-rbw ];
|
||||||
|
|
||||||
|
config = mkIf (cfg.enable && app == "rofi-rbw") {
|
||||||
|
programs.rbw = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
# email = "you@example.tld"; # You have to set this in your config
|
||||||
|
pinentry = mkDefault pkgs.pinentry-gnome3;
|
||||||
|
lock_timeout = mkDefault 3600;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.rofi-rbw = {
|
||||||
|
enable = true;
|
||||||
|
package = mkDefault pkgs.rofi-rbw-wayland;
|
||||||
|
settings = {
|
||||||
|
selector = mkDefault "bemenu";
|
||||||
|
selector-args = mkDefault "-i -l 20";
|
||||||
|
action = mkDefault "copy";
|
||||||
|
typing-key-delay = mkDefault 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.librewolf = mkIf config.programs.librewolf.enable {
|
||||||
|
profiles.default.extensions.packages =
|
||||||
|
with inputs.nur.legacyPackages."${pkgs.stdenv.hostPlatform.system}".repos.rycee.firefox-addons; [
|
||||||
|
bitwarden
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -56,6 +56,7 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./bitwarden
|
||||||
./bemenu
|
./bemenu
|
||||||
./dmenu-bluetooth
|
./dmenu-bluetooth
|
||||||
./dunst-toggle
|
./dunst-toggle
|
||||||
|
|
|
||||||
|
|
@ -8,67 +8,230 @@
|
||||||
let
|
let
|
||||||
cfg = config.services.librechat-oci;
|
cfg = config.services.librechat-oci;
|
||||||
|
|
||||||
image = pkgs.dockerTools.pullImage {
|
defaultImages = {
|
||||||
imageName = "ghcr.io/danny-avila/librechat";
|
librechat = pkgs.dockerTools.pullImage {
|
||||||
imageDigest = "sha256:a46254938507971e0d4f7ed3f9d116bd9b118f4810b5b75eb716baf575645068";
|
imageName = "ghcr.io/danny-avila/librechat";
|
||||||
hash = "sha256-zevUN6vrs3hymwCGFmk/YXlUzYjN37H+EO5aLxYchyc=";
|
imageDigest = "sha256:a46254938507971e0d4f7ed3f9d116bd9b118f4810b5b75eb716baf575645068";
|
||||||
finalImageName = "ghcr.io/danny-avila/librechat";
|
hash = "sha256-zevUN6vrs3hymwCGFmk/YXlUzYjN37H+EO5aLxYchyc=";
|
||||||
finalImageTag = "v0.8.5";
|
finalImageName = "ghcr.io/danny-avila/librechat";
|
||||||
|
finalImageTag = "v0.8.5";
|
||||||
|
};
|
||||||
|
|
||||||
|
meilisearch = pkgs.dockerTools.pullImage {
|
||||||
|
imageName = "getmeili/meilisearch";
|
||||||
|
imageDigest = "sha256:b839a48d008d4e67e57f78dcff5b21d5e8b8fa066bacd11f97824d6307abb0dd";
|
||||||
|
hash = "sha256-+hypvjFDSdnnWAO4tARTnjNd/6HlF6pMg1L6UUffdYM=";
|
||||||
|
finalImageName = "getmeili/meilisearch";
|
||||||
|
finalImageTag = "v1.44.0";
|
||||||
|
};
|
||||||
|
|
||||||
|
mongodb = pkgs.dockerTools.pullImage {
|
||||||
|
imageName = "mongo";
|
||||||
|
imageDigest = "sha256:098862b1339f031900ca66cf8fef799e616d6324fa41b9a263f2ec899552c1ef";
|
||||||
|
hash = "sha256-XuWnvcqAAkAGshdQtnngKOOJP2Bd33FXTbGHTRX3nUc=";
|
||||||
|
finalImageName = "mongo";
|
||||||
|
finalImageTag = "8.0.20";
|
||||||
|
};
|
||||||
|
|
||||||
|
vectordb = pkgs.dockerTools.pullImage {
|
||||||
|
imageName = "pgvector/pgvector";
|
||||||
|
imageDigest = "sha256:8809cfffff0082cf260c9ac752f1dd1afc77f6f0a55c4e6411321e78efc3d9a5";
|
||||||
|
hash = "sha256-rc6gQLMzv8UOZVLmWKGUESNIo+iPf5DR7T79AmbzWc4=";
|
||||||
|
finalImageName = "pgvector/pgvector";
|
||||||
|
finalImageTag = "0.8.0-pg15-trixie";
|
||||||
|
};
|
||||||
|
|
||||||
|
ragApi = pkgs.dockerTools.pullImage {
|
||||||
|
imageName = "registry.librechat.ai/danny-avila/librechat-rag-api-dev-lite";
|
||||||
|
imageDigest = "sha256:6dfb6832661ff9c26fa329c823ce266059e33567670a763e9ecb9b566b8daa68";
|
||||||
|
hash = "sha256-k8pkEgbqT4NU2+2ZjdRFlfFvMUk/1p+pkysbELh95pM=";
|
||||||
|
finalImageName = "registry.librechat.ai/danny-avila/librechat-rag-api-dev-lite";
|
||||||
|
finalImageTag = "latest";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
defaultEnv = {
|
defaultEnv = {
|
||||||
|
# Server
|
||||||
HOST = "0.0.0.0";
|
HOST = "0.0.0.0";
|
||||||
PORT = "3080";
|
PORT = toString cfg.port;
|
||||||
NO_INDEX = "true";
|
NO_INDEX = "true";
|
||||||
DEBUG_LOGGING = "false";
|
TRUST_PROXY = "1";
|
||||||
|
|
||||||
|
# Logging
|
||||||
CONSOLE_JSON = "false";
|
CONSOLE_JSON = "false";
|
||||||
ALLOW_REGISTRATION = "true";
|
DEBUG_LOGGING = "true";
|
||||||
ALLOW_EMAIL_LOGIN = "true";
|
DEBUG_CONSOLE = "false";
|
||||||
|
AGENT_DEBUG_LOGGING = "false";
|
||||||
|
DEBUG_OPENAI = "false";
|
||||||
|
|
||||||
|
# Node
|
||||||
|
NODE_MAX_OLD_SPACE_SIZE = "6144";
|
||||||
|
|
||||||
|
# Search
|
||||||
SEARCH = "true";
|
SEARCH = "true";
|
||||||
MEILI_NO_ANALYTICS = "true";
|
MEILI_NO_ANALYTICS = "true";
|
||||||
|
|
||||||
|
# Moderation
|
||||||
|
OPENAI_MODERATION = "false";
|
||||||
|
BAN_VIOLATIONS = "true";
|
||||||
|
BAN_DURATION = "1000 * 60 * 60 * 2";
|
||||||
|
BAN_INTERVAL = "20";
|
||||||
|
LOGIN_VIOLATION_SCORE = "1";
|
||||||
|
REGISTRATION_VIOLATION_SCORE = "1";
|
||||||
|
CONCURRENT_VIOLATION_SCORE = "1";
|
||||||
|
MESSAGE_VIOLATION_SCORE = "1";
|
||||||
|
NON_BROWSER_VIOLATION_SCORE = "20";
|
||||||
|
TTS_VIOLATION_SCORE = "0";
|
||||||
|
STT_VIOLATION_SCORE = "0";
|
||||||
|
FORK_VIOLATION_SCORE = "0";
|
||||||
|
IMPORT_VIOLATION_SCORE = "0";
|
||||||
|
FILE_UPLOAD_VIOLATION_SCORE = "0";
|
||||||
|
LOGIN_MAX = "7";
|
||||||
|
LOGIN_WINDOW = "5";
|
||||||
|
REGISTER_MAX = "5";
|
||||||
|
REGISTER_WINDOW = "60";
|
||||||
|
LIMIT_CONCURRENT_MESSAGES = "true";
|
||||||
|
CONCURRENT_MESSAGE_MAX = "2";
|
||||||
|
LIMIT_MESSAGE_IP = "true";
|
||||||
|
MESSAGE_IP_MAX = "40";
|
||||||
|
MESSAGE_IP_WINDOW = "1";
|
||||||
|
LIMIT_MESSAGE_USER = "false";
|
||||||
|
MESSAGE_USER_MAX = "40";
|
||||||
|
MESSAGE_USER_WINDOW = "1";
|
||||||
|
ILLEGAL_MODEL_REQ_SCORE = "5";
|
||||||
|
|
||||||
|
# Registration and login
|
||||||
|
ALLOW_EMAIL_LOGIN = "true";
|
||||||
|
ALLOW_REGISTRATION = "false";
|
||||||
|
ALLOW_SOCIAL_LOGIN = "false";
|
||||||
|
ALLOW_SOCIAL_REGISTRATION = "false";
|
||||||
|
ALLOW_PASSWORD_RESET = "false";
|
||||||
|
ALLOW_UNVERIFIED_EMAIL_LOGIN = "true";
|
||||||
|
SESSION_EXPIRY = "1000 * 60 * 15";
|
||||||
|
REFRESH_TOKEN_EXPIRY = "(1000 * 60 * 60 * 24) * 7";
|
||||||
|
|
||||||
|
# OpenID
|
||||||
|
OPENID_SCOPE = "openid profile email";
|
||||||
|
OPENID_CALLBACK_URL = "/oauth/openid/callback";
|
||||||
|
OPENID_AUTO_REDIRECT = "false";
|
||||||
|
OPENID_USE_PKCE = "false";
|
||||||
|
OPENID_ON_BEHALF_FLOW_USERINFO_SCOPE = "user.read";
|
||||||
|
|
||||||
|
# OAuth callback URLs
|
||||||
|
DISCORD_CALLBACK_URL = "/oauth/discord/callback";
|
||||||
|
FACEBOOK_CALLBACK_URL = "/oauth/facebook/callback";
|
||||||
|
GITHUB_CALLBACK_URL = "/oauth/github/callback";
|
||||||
|
GOOGLE_CALLBACK_URL = "/oauth/google/callback";
|
||||||
|
APPLE_CALLBACK_URL = "/oauth/apple/callback";
|
||||||
|
SAML_CALLBACK_URL = "/oauth/saml/callback";
|
||||||
|
|
||||||
|
# Entra ID
|
||||||
|
USE_ENTRA_ID_FOR_PEOPLE_SEARCH = "false";
|
||||||
|
ENTRA_ID_INCLUDE_OWNERS_AS_MEMBERS = "false";
|
||||||
|
OPENID_GRAPH_SCOPES = "User.Read,People.Read,GroupMember.Read.All";
|
||||||
|
|
||||||
|
# Shared links
|
||||||
|
ALLOW_SHARED_LINKS = "true";
|
||||||
|
ALLOW_SHARED_LINKS_PUBLIC = "false";
|
||||||
|
|
||||||
|
# UI
|
||||||
|
APP_TITLE = "LibreChat";
|
||||||
|
HELP_AND_FAQ_URL = "https://librechat.ai";
|
||||||
|
|
||||||
|
# Flux
|
||||||
|
FLUX_API_BASE_URL = "https://api.us1.bfl.ai";
|
||||||
|
|
||||||
|
# Email
|
||||||
|
EMAIL_PORT = "25";
|
||||||
|
EMAIL_FROM = "noreply@librechat.ai";
|
||||||
|
|
||||||
|
# Azure Blob Storage
|
||||||
|
AZURE_STORAGE_PUBLIC_ACCESS = "false";
|
||||||
|
AZURE_CONTAINER_NAME = "files";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mkImageOption =
|
||||||
|
name: description:
|
||||||
|
mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = defaultImages.${name};
|
||||||
|
description = description;
|
||||||
|
};
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
literalExpression
|
literalExpression
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkIf
|
mkIf
|
||||||
mkOption
|
mkOption
|
||||||
mkOverride
|
mkOverride
|
||||||
|
optional
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.librechat-oci = {
|
options.services.librechat-oci = {
|
||||||
enable = mkEnableOption "LibreChat container with Podman.";
|
enable = mkEnableOption "LibreChat container with Podman.";
|
||||||
image = mkOption {
|
|
||||||
type = types.package;
|
images = {
|
||||||
default = image;
|
librechat = mkImageOption "librechat" "The LibreChat Docker image (`pkgs.dockerTools.pullImage`).";
|
||||||
description = "The Docker image to use (`pkgs.dockerTools.pullImage`).";
|
meilisearch = mkImageOption "meilisearch" "The Meilisearch Docker image (`pkgs.dockerTools.pullImage`).";
|
||||||
|
mongodb = mkImageOption "mongodb" "The MongoDB Docker image (`pkgs.dockerTools.pullImage`).";
|
||||||
|
vectordb = mkImageOption "vectordb" "The pgvector Docker image (`pkgs.dockerTools.pullImage`).";
|
||||||
|
ragApi = mkImageOption "ragApi" "The LibreChat RAG API Docker image (`pkgs.dockerTools.pullImage`).";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
configFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = literalExpression "./librechat.yaml";
|
||||||
|
description = "Path to the `librechat.yaml` configuration file.";
|
||||||
|
};
|
||||||
|
|
||||||
externalUrl = mkOption {
|
externalUrl = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = literalExpression "http://${config.networking.domain}";
|
example = literalExpression ''"https://chat.example.com"'';
|
||||||
description = "Public URL to configure for LibreChat.";
|
description = "Public URL to configure for LibreChat (sets DOMAIN_CLIENT and DOMAIN_SERVER).";
|
||||||
};
|
};
|
||||||
|
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 3080;
|
default = 3080;
|
||||||
description = "Which port the LibreChat server listens to.";
|
description = "Which port the LibreChat server listens on.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
meiliPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 7700;
|
||||||
|
description = "Which port Meilisearch listens on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
ragPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 8000;
|
||||||
|
description = "Which port the RAG API listens on.";
|
||||||
|
};
|
||||||
|
|
||||||
environment = mkOption {
|
environment = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.str;
|
||||||
description = ''
|
description = ''
|
||||||
Extra environment variables for LibreChat.
|
Extra environment variables for LibreChat.
|
||||||
For more details see <https://docs.librechat.ai/docs/configuration/dotenv>
|
These are merged on top of the defaults and can override them.
|
||||||
|
For secrets use <option>environmentFile</option> instead.
|
||||||
|
See <https://docs.librechat.ai/docs/configuration/dotenv>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
environmentFile = mkOption {
|
environmentFile = mkOption {
|
||||||
description = "Environment file to be passed to the LibreChat container.";
|
|
||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
default = null;
|
default = null;
|
||||||
example = "config.sops.templates.librechat-env.path";
|
example = literalExpression "config.sops.templates.librechat-env.path";
|
||||||
|
description = ''
|
||||||
|
Environment file passed to the LibreChat, Meilisearch, and RAG API
|
||||||
|
containers. Use this for secrets such as JWT_SECRET, CREDS_KEY,
|
||||||
|
MEILI_MASTER_KEY, and API keys.
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -89,158 +252,275 @@ in
|
||||||
|
|
||||||
virtualisation.oci-containers.backend = "podman";
|
virtualisation.oci-containers.backend = "podman";
|
||||||
|
|
||||||
virtualisation.oci-containers.containers."librechat-mongodb" = {
|
virtualisation.oci-containers.containers.librechat-mongodb = {
|
||||||
image = "mongo:7.0";
|
image = with cfg.images.mongodb; "${imageName}:${imageTag}";
|
||||||
environment = {
|
imageFile = cfg.images.mongodb;
|
||||||
MONGO_INITDB_ROOT_USERNAME = "root";
|
cmd = [
|
||||||
MONGO_INITDB_ROOT_PASSWORD = "librechat";
|
"mongod"
|
||||||
MONGO_INITDB_DATABASE = "LibreChat";
|
"--noauth"
|
||||||
};
|
];
|
||||||
volumes = [
|
volumes = [
|
||||||
"librechat_mongodb_data:/data/db:rw"
|
"librechat_mongodb_data:/data/db:rw"
|
||||||
];
|
];
|
||||||
log-driver = "journald";
|
log-driver = "journald";
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--network=host"
|
"--network-alias=mongodb"
|
||||||
|
"--network=librechat_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers.librechat-meilisearch = {
|
||||||
|
image = with cfg.images.meilisearch; "${imageName}:${imageTag}";
|
||||||
|
imageFile = cfg.images.meilisearch;
|
||||||
|
environment = {
|
||||||
|
MEILI_NO_ANALYTICS = "true";
|
||||||
|
MEILI_HOST = "http://meilisearch:${toString cfg.meiliPort}";
|
||||||
|
};
|
||||||
|
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||||
|
volumes = [
|
||||||
|
"librechat_meili_data:/meili_data:rw"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=meilisearch"
|
||||||
|
"--network=librechat_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers.librechat-vectordb = {
|
||||||
|
image = with cfg.images.vectordb; "${imageName}:${imageTag}";
|
||||||
|
imageFile = cfg.images.vectordb;
|
||||||
|
environment = {
|
||||||
|
POSTGRES_DB = "mydatabase";
|
||||||
|
POSTGRES_USER = "myuser";
|
||||||
|
POSTGRES_PASSWORD = "mypassword";
|
||||||
|
};
|
||||||
|
volumes = [
|
||||||
|
"librechat_pgdata:/var/lib/postgresql/data:rw"
|
||||||
|
];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=vectordb"
|
||||||
|
"--network=librechat_default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers.librechat-rag-api = {
|
||||||
|
image = with cfg.images.ragApi; "${imageName}:${imageTag}";
|
||||||
|
imageFile = cfg.images.ragApi;
|
||||||
|
environment = {
|
||||||
|
DB_HOST = "vectordb";
|
||||||
|
RAG_PORT = toString cfg.ragPort;
|
||||||
|
};
|
||||||
|
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||||
|
dependsOn = [ "librechat-vectordb" ];
|
||||||
|
log-driver = "journald";
|
||||||
|
extraOptions = [
|
||||||
|
"--network-alias=rag_api"
|
||||||
|
"--network=librechat_default"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualisation.oci-containers.containers.librechat = {
|
virtualisation.oci-containers.containers.librechat = {
|
||||||
image = toString cfg.image;
|
image = with cfg.images.librechat; "${imageName}:${imageTag}";
|
||||||
|
imageFile = cfg.images.librechat;
|
||||||
environment =
|
environment =
|
||||||
defaultEnv
|
defaultEnv
|
||||||
// {
|
// {
|
||||||
MONGO_URI = "mongodb://root:librechat@localhost:27017/LibreChat?authSource=admin";
|
MONGO_URI = "mongodb://mongodb:27017/LibreChat";
|
||||||
|
MEILI_HOST = "http://meilisearch:${toString cfg.meiliPort}";
|
||||||
|
RAG_PORT = toString cfg.ragPort;
|
||||||
|
RAG_API_URL = "http://rag_api:${toString cfg.ragPort}";
|
||||||
|
DOMAIN_CLIENT =
|
||||||
|
if cfg.externalUrl != null then cfg.externalUrl else "http://localhost:${toString cfg.port}";
|
||||||
|
DOMAIN_SERVER =
|
||||||
|
if cfg.externalUrl != null then cfg.externalUrl else "http://localhost:${toString cfg.port}";
|
||||||
}
|
}
|
||||||
// cfg.environment;
|
// cfg.environment;
|
||||||
|
environmentFiles = optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||||
volumes = [
|
volumes = [
|
||||||
"librechat_data:/app/client/data:rw"
|
|
||||||
"librechat_images:/app/client/public/images:rw"
|
"librechat_images:/app/client/public/images:rw"
|
||||||
"librechat_uploads:/app/api/server/files/uploads:rw"
|
"librechat_uploads:/app/uploads:rw"
|
||||||
"librechat_logs:/app/logs:rw"
|
"librechat_logs:/app/logs:rw"
|
||||||
];
|
]
|
||||||
|
++ optional (cfg.configFile != null) "${cfg.configFile}:/app/librechat.yaml:ro";
|
||||||
|
|
||||||
ports = [
|
ports = [
|
||||||
"${toString cfg.port}:${toString cfg.port}"
|
"0.0.0.0:${toString cfg.port}:${toString cfg.port}/tcp"
|
||||||
|
];
|
||||||
|
dependsOn = [
|
||||||
|
"librechat-mongodb"
|
||||||
|
"librechat-rag-api"
|
||||||
];
|
];
|
||||||
log-driver = "journald";
|
log-driver = "journald";
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--network=host"
|
"--network-alias=api"
|
||||||
|
"--network=librechat_default"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-librechat-mongodb" = {
|
systemd.services.podman-librechat-mongodb = {
|
||||||
serviceConfig = {
|
serviceConfig.Restart = mkOverride 90 "always";
|
||||||
Restart = mkOverride 90 "always";
|
|
||||||
};
|
|
||||||
after = [
|
after = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
"podman-volume-librechat_mongodb_data.service"
|
"podman-volume-librechat_mongodb_data.service"
|
||||||
];
|
];
|
||||||
requires = [
|
requires = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
"podman-volume-librechat_mongodb_data.service"
|
"podman-volume-librechat_mongodb_data.service"
|
||||||
];
|
];
|
||||||
partOf = [
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
"podman-compose-librechat-root.target"
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
];
|
|
||||||
wantedBy = [
|
|
||||||
"podman-compose-librechat-root.target"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-librechat" = {
|
systemd.services.podman-librechat-meilisearch = {
|
||||||
serviceConfig = {
|
serviceConfig.Restart = mkOverride 90 "always";
|
||||||
Restart = mkOverride 90 "always";
|
|
||||||
};
|
|
||||||
after = [
|
after = [
|
||||||
"podman-volume-librechat_data.service"
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-volume-librechat_meili_data.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-volume-librechat_meili_data.service"
|
||||||
|
];
|
||||||
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.podman-librechat-vectordb = {
|
||||||
|
serviceConfig.Restart = mkOverride 90 "always";
|
||||||
|
after = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-volume-librechat_pgdata.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-volume-librechat_pgdata.service"
|
||||||
|
];
|
||||||
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.podman-librechat-rag-api = {
|
||||||
|
serviceConfig.Restart = mkOverride 90 "always";
|
||||||
|
after = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-librechat-vectordb.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
|
"podman-librechat-vectordb.service"
|
||||||
|
];
|
||||||
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.podman-librechat = {
|
||||||
|
serviceConfig.Restart = mkOverride 90 "always";
|
||||||
|
after = [
|
||||||
|
"podman-network-librechat_default.service"
|
||||||
"podman-volume-librechat_images.service"
|
"podman-volume-librechat_images.service"
|
||||||
"podman-volume-librechat_uploads.service"
|
"podman-volume-librechat_uploads.service"
|
||||||
"podman-volume-librechat_logs.service"
|
"podman-volume-librechat_logs.service"
|
||||||
"podman-librechat-mongodb.service"
|
"podman-librechat-mongodb.service"
|
||||||
|
"podman-librechat-meilisearch.service"
|
||||||
|
"podman-librechat-rag-api.service"
|
||||||
];
|
];
|
||||||
requires = [
|
requires = [
|
||||||
"podman-volume-librechat_data.service"
|
"podman-network-librechat_default.service"
|
||||||
"podman-volume-librechat_images.service"
|
"podman-volume-librechat_images.service"
|
||||||
"podman-volume-librechat_uploads.service"
|
"podman-volume-librechat_uploads.service"
|
||||||
"podman-volume-librechat_logs.service"
|
"podman-volume-librechat_logs.service"
|
||||||
"podman-librechat-mongodb.service"
|
"podman-librechat-mongodb.service"
|
||||||
|
"podman-librechat-meilisearch.service"
|
||||||
|
"podman-librechat-rag-api.service"
|
||||||
];
|
];
|
||||||
partOf = [
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
"podman-compose-librechat-root.target"
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
];
|
|
||||||
wantedBy = [
|
|
||||||
"podman-compose-librechat-root.target"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-volume-librechat_data" = {
|
systemd.services.podman-network-librechat_default = {
|
||||||
path = [ pkgs.podman ];
|
path = [ pkgs.podman ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
|
ExecStop = "podman network rm -f librechat_default";
|
||||||
};
|
};
|
||||||
script = ''
|
script = ''
|
||||||
podman volume inspect librechat_data || podman volume create librechat_data
|
podman network inspect librechat_default || podman network create librechat_default
|
||||||
'';
|
'';
|
||||||
partOf = [ "podman-compose-librechat-root.target" ];
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-volume-librechat_images" = {
|
systemd.services.podman-volume-librechat_mongodb_data = {
|
||||||
path = [ pkgs.podman ];
|
path = [ pkgs.podman ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
script = ''
|
script = "podman volume inspect librechat_mongodb_data || podman volume create librechat_mongodb_data";
|
||||||
podman volume inspect librechat_images || podman volume create librechat_images
|
|
||||||
'';
|
|
||||||
partOf = [ "podman-compose-librechat-root.target" ];
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-volume-librechat_uploads" = {
|
systemd.services.podman-volume-librechat_meili_data = {
|
||||||
path = [ pkgs.podman ];
|
path = [ pkgs.podman ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
script = ''
|
script = "podman volume inspect librechat_meili_data || podman volume create librechat_meili_data";
|
||||||
podman volume inspect librechat_uploads || podman volume create librechat_uploads
|
|
||||||
'';
|
|
||||||
partOf = [ "podman-compose-librechat-root.target" ];
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-volume-librechat_logs" = {
|
systemd.services.podman-volume-librechat_pgdata = {
|
||||||
path = [ pkgs.podman ];
|
path = [ pkgs.podman ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
script = ''
|
script = "podman volume inspect librechat_pgdata || podman volume create librechat_pgdata";
|
||||||
podman volume inspect librechat_logs || podman volume create librechat_logs
|
|
||||||
'';
|
|
||||||
partOf = [ "podman-compose-librechat-root.target" ];
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services."podman-volume-librechat_mongodb_data" = {
|
systemd.services.podman-volume-librechat_images = {
|
||||||
path = [ pkgs.podman ];
|
path = [ pkgs.podman ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
script = ''
|
script = "podman volume inspect librechat_images || podman volume create librechat_images";
|
||||||
podman volume inspect librechat_mongodb_data || podman volume create librechat_mongodb_data
|
|
||||||
'';
|
|
||||||
partOf = [ "podman-compose-librechat-root.target" ];
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
wantedBy = [ "podman-compose-librechat-root.target" ];
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.targets."podman-compose-librechat-root" = {
|
systemd.services.podman-volume-librechat_uploads = {
|
||||||
unitConfig = {
|
path = [ pkgs.podman ];
|
||||||
Description = "Root target generated by compose2nix.";
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
|
script = "podman volume inspect librechat_uploads || podman volume create librechat_uploads";
|
||||||
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.podman-volume-librechat_logs = {
|
||||||
|
path = [ pkgs.podman ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = "podman volume inspect librechat_logs || podman volume create librechat_logs";
|
||||||
|
partOf = [ "podman-compose-librechat-root.target" ];
|
||||||
|
wantedBy = [ "podman-compose-librechat-root.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.targets.podman-compose-librechat-root = {
|
||||||
|
unitConfig.Description = "Root target generated by compose2nix.";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ in
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 8000;
|
||||||
|
description = "Port on which the mcpo service should listen.";
|
||||||
|
};
|
||||||
|
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "The user the mcpo service will run as.";
|
description = "The user the mcpo service will run as.";
|
||||||
|
|
@ -100,7 +106,7 @@ in
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${getExe cfg.package} --config ${configFile}";
|
ExecStart = "${getExe cfg.package} --port ${toString cfg.port} --config ${configFile}";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
jirafeau-cli = pkgs.callPackage ./jirafeau-cli { };
|
jirafeau-cli = pkgs.callPackage ./jirafeau-cli { };
|
||||||
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
kicad-mcp = pkgs.callPackage ./kicad-mcp { };
|
||||||
mcpo = pkgs.callPackage ./mcpo { };
|
mcpo = pkgs.callPackage ./mcpo { };
|
||||||
|
nerdlog = pkgs.callPackage ./nerdlog { };
|
||||||
pass2bw = pkgs.callPackage ./pass2bw { };
|
pass2bw = pkgs.callPackage ./pass2bw { };
|
||||||
pyman = pkgs.callPackage ./pyman { };
|
pyman = pkgs.callPackage ./pyman { };
|
||||||
quicknote = pkgs.callPackage ./quicknote { };
|
quicknote = pkgs.callPackage ./quicknote { };
|
||||||
|
|
|
||||||
83
pkgs/nerdlog/default.nix
Normal file
83
pkgs/nerdlog/default.nix
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
buildGoModule,
|
||||||
|
fetchFromGitHub,
|
||||||
|
stdenv,
|
||||||
|
darwin,
|
||||||
|
xorg,
|
||||||
|
pkg-config,
|
||||||
|
wayland,
|
||||||
|
libGL,
|
||||||
|
libxkbcommon,
|
||||||
|
makeWrapper,
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildGoModule rec {
|
||||||
|
pname = "nerdlog";
|
||||||
|
version = "1.10.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "dimonomid";
|
||||||
|
repo = "nerdlog";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-XlzWNeyd+Ar4ArFcN1wkQ0aod6ckAiIb12odK7cf4+s=";
|
||||||
|
};
|
||||||
|
|
||||||
|
vendorHash = "sha256-hvv0dsE1yz85VLaBOE7RWbux8L8kVTihcA1HyyHRYAM=";
|
||||||
|
|
||||||
|
subPackages = [
|
||||||
|
"cmd/nerdlog"
|
||||||
|
"cmd/generate_syslog"
|
||||||
|
];
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkg-config
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs =
|
||||||
|
lib.optionals stdenv.isDarwin [
|
||||||
|
darwin.apple_sdk.frameworks.Cocoa
|
||||||
|
]
|
||||||
|
++ lib.optionals stdenv.isLinux [
|
||||||
|
xorg.libX11
|
||||||
|
xorg.libXext
|
||||||
|
xorg.libXfixes
|
||||||
|
wayland
|
||||||
|
libGL
|
||||||
|
libxkbcommon
|
||||||
|
];
|
||||||
|
|
||||||
|
postInstall = lib.optionalString stdenv.isLinux ''
|
||||||
|
wrapProgram $out/bin/nerdlog \
|
||||||
|
--prefix LD_LIBRARY_PATH : ${
|
||||||
|
lib.makeLibraryPath [
|
||||||
|
xorg.libX11
|
||||||
|
xorg.libXext
|
||||||
|
xorg.libXfixes
|
||||||
|
wayland
|
||||||
|
libGL
|
||||||
|
libxkbcommon
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
"-s"
|
||||||
|
"-w"
|
||||||
|
"-X=github.com/dimonomid/nerdlog/version.version=${version}"
|
||||||
|
"-X=github.com/dimonomid/nerdlog/version.commit=${src.rev}"
|
||||||
|
"-X=github.com/dimonomid/nerdlog/version.date=1970-01-01T00:00:00Z"
|
||||||
|
"-X=github.com/dimonomid/nerdlog/version.builtBy=goreleaser"
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Nerdlog: fast, remote-first, multi-host TUI log viewer with timeline histogram and no central server";
|
||||||
|
homepage = "https://github.com/dimonomid/nerdlog";
|
||||||
|
changelog = "https://github.com/dimonomid/nerdlog/blob/${src.rev}/CHANGELOG.md";
|
||||||
|
license = lib.licenses.bsd2;
|
||||||
|
mainProgram = "nerdlog";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -43,13 +43,20 @@ def process_csv(input_file, output_file):
|
||||||
if col not in new_row:
|
if col not in new_row:
|
||||||
new_row[col] = default_val
|
new_row[col] = default_val
|
||||||
|
|
||||||
|
folder = new_row.get('folder', '')
|
||||||
|
name = new_row.get('name', '')
|
||||||
|
if folder.startswith('www') and name:
|
||||||
|
if not name.startswith('http://') and not name.startswith('https://'):
|
||||||
|
new_row['login_uri'] = f'https://{name}'
|
||||||
|
else:
|
||||||
|
new_row['login_uri'] = name
|
||||||
|
|
||||||
if new_row['notes']:
|
if new_row['notes']:
|
||||||
new_row['notes'] = new_row['notes'].replace('\n', ' ').replace('\r', ' ')
|
new_row['notes'] = new_row['notes'].replace('\n', ' ').replace('\r', ' ')
|
||||||
new_row['notes'] = re.sub(r'\s+', ' ', new_row['notes']).strip()
|
new_row['notes'] = re.sub(r'\s+', ' ', new_row['notes']).strip()
|
||||||
|
|
||||||
notes = new_row['notes']
|
notes = new_row['notes']
|
||||||
if notes:
|
if notes:
|
||||||
# Look for pattern: "login: USERNAME"
|
|
||||||
match = re.search(r'login:\s*(\S+)', notes, re.IGNORECASE)
|
match = re.search(r'login:\s*(\S+)', notes, re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
username = match.group(1)
|
username = match.group(1)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
stdenv,
|
stdenv,
|
||||||
lib,
|
lib,
|
||||||
makeWrapper,
|
makeWrapper,
|
||||||
|
pass,
|
||||||
|
pass2csv,
|
||||||
python3,
|
python3,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
@ -20,13 +22,18 @@ stdenv.mkDerivation rec {
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
|
|
||||||
sed -e "s|python ./convert_csvs.py|python $out/bin/convert_csvs.py|" \
|
cp ${src}/pass2bw.sh $out/bin/${pname}
|
||||||
${src}/${pname}.sh > $out/bin/${pname}
|
|
||||||
chmod +x $out/bin/${pname}
|
chmod +x $out/bin/${pname}
|
||||||
|
|
||||||
cp ${src}/convert_csvs.py $out/bin/
|
cp ${src}/convert_csvs.py $out/bin/
|
||||||
|
|
||||||
wrapProgram $out/bin/${pname} \
|
wrapProgram $out/bin/${pname} \
|
||||||
--prefix PATH : ${lib.makeBinPath [ python3 ]}
|
--prefix PATH : ${
|
||||||
|
lib.makeBinPath [
|
||||||
|
pass
|
||||||
|
pass2csv
|
||||||
|
python3
|
||||||
|
]
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ if [ "$#" -ne 2 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pass2csv "$1" /tmp/pass.csv
|
pass2csv "$1" /tmp/pass.csv
|
||||||
python ./convert_csvs.py /tmp/pass.csv "$2"
|
python3 "$(dirname "$0")/convert_csvs.py" /tmp/pass.csv "$2"
|
||||||
rm /tmp/pass.csv
|
rm /tmp/pass.csv
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue