170 lines
5.3 KiB
Nix
170 lines
5.3 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}: let
|
|
serviceName = "librechat";
|
|
portUtils = import ../../../../lib/port-utils.nix {inherit lib;};
|
|
servicePort = portUtils.getPort serviceName "AZ-CLD-1";
|
|
ragApiPort = portUtils.getPort "rag-api" "AZ-CLD-1";
|
|
envFileProd = config.age.secrets.librechat-env-prod.path;
|
|
envFileCommon = config.age.secrets.librechat.path;
|
|
in {
|
|
virtualisation.oci-containers = {
|
|
containers.meilisearch = {
|
|
image = "getmeili/meilisearch:v1.12.3";
|
|
autoStart = true;
|
|
volumes = ["librechat_meili:/meili_data"];
|
|
environment = {
|
|
MEILI_HTTP_ADDR = "0.0.0.0:7700";
|
|
MEILI_NO_ANALYTICS = "true";
|
|
};
|
|
environmentFiles = [envFileCommon envFileProd];
|
|
extraOptions = ["--ip=10.89.0.20" "--network=web"];
|
|
};
|
|
|
|
containers.rag_api = {
|
|
image = "ghcr.io/danny-avila/librechat-rag-api-dev-lite:latest";
|
|
autoStart = true;
|
|
environment = {
|
|
RAG_PORT = "8000";
|
|
DB_HOST = "10.89.0.1";
|
|
DB_PORT = "5432";
|
|
};
|
|
environmentFiles = [envFileCommon envFileProd];
|
|
dependsOn = ["meilisearch"];
|
|
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.21" "--network=web"];
|
|
ports = ["127.0.0.1:${toString ragApiPort}:8000"];
|
|
};
|
|
|
|
containers.mongodb = {
|
|
image = "mongo:7";
|
|
autoStart = true;
|
|
volumes = [
|
|
"librechat_mongo:/data/db"
|
|
"/var/backup/mongodb:/data/backups"
|
|
];
|
|
# Enable auth once users exist; see Mongo auth doc.
|
|
# command = [ "mongod", "--auth" ];
|
|
extraOptions = ["--ip=10.89.0.22" "--network=web"];
|
|
};
|
|
|
|
containers.${serviceName} = {
|
|
image = "ghcr.io/danny-avila/librechat-dev-api:latest";
|
|
autoStart = true;
|
|
ports = ["127.0.0.1:${toString servicePort}:3080"];
|
|
dependsOn = ["mongodb" "rag_api" "meilisearch"];
|
|
environment = {
|
|
HOST = "0.0.0.0";
|
|
NODE_ENV = "production";
|
|
# Mongo URI (start without auth; switch to mongodb://user:pass@mongodb:27017/LibreChat after Step 4)
|
|
MONGO_URI = "mongodb://mongodb:27017/LibreChat";
|
|
MEILI_HOST = "http://meilisearch:7700";
|
|
RAG_PORT = "8000";
|
|
RAG_API_URL = "http://rag_api:8000";
|
|
};
|
|
environmentFiles = [envFileCommon envFileProd];
|
|
volumes = [
|
|
# Config file still needs to be a bind mount for host management
|
|
"/var/lib/librechat/librechat.yaml:/app/librechat.yaml:ro"
|
|
# Use named volumes for application data
|
|
"librechat_images:/app/client/public/images"
|
|
"librechat_uploads:/app/uploads"
|
|
"librechat_logs:/app/api/logs"
|
|
];
|
|
extraOptions = ["--ip=10.89.0.23" "--network=web"];
|
|
};
|
|
};
|
|
|
|
systemd.services."mongo-backup" = {
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
User = "root";
|
|
Group = "root";
|
|
};
|
|
script = ''
|
|
set -euo pipefail
|
|
|
|
BACKUP_DIR="/var/backup/mongodb"
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
TEMP_BACKUP="mongodb_backup_$TIMESTAMP"
|
|
ARCHIVE_NAME="mongodb_backup_$TIMESTAMP.tar.gz"
|
|
|
|
# Ensure backup directory exists with proper permissions
|
|
mkdir -p "$BACKUP_DIR"
|
|
chown root:root "$BACKUP_DIR"
|
|
chmod 750 "$BACKUP_DIR"
|
|
|
|
echo "Starting MongoDB backup at $(date)"
|
|
|
|
# Create the backup dump in container
|
|
if ${pkgs.podman}/bin/podman exec mongodb mongodump --out "/data/backups/$TEMP_BACKUP"; then
|
|
echo "MongoDB dump completed successfully"
|
|
|
|
# Create compressed archive from the backup
|
|
cd "$BACKUP_DIR"
|
|
if [ -d "$TEMP_BACKUP" ]; then
|
|
echo "Creating compressed archive: $ARCHIVE_NAME"
|
|
${pkgs.gnutar}/bin/tar --use-compress-program=${pkgs.gzip}/bin/gzip -cf "$ARCHIVE_NAME" -C . "$TEMP_BACKUP"
|
|
|
|
# Remove the uncompressed backup directory
|
|
rm -rf "$TEMP_BACKUP"
|
|
|
|
# Verify archive was created
|
|
if [ -f "$ARCHIVE_NAME" ]; then
|
|
ARCHIVE_SIZE=$(${pkgs.coreutils}/bin/du -sh "$ARCHIVE_NAME" | cut -f1)
|
|
echo "Compressed backup created: $ARCHIVE_NAME (Size: $ARCHIVE_SIZE)"
|
|
|
|
# Keep only the 2 most recent backup archives
|
|
ls -1t mongodb_backup_*.tar.gz | tail -n +3 | xargs -r rm -f
|
|
echo "Old backup archives cleaned up, keeping 2 most recent"
|
|
|
|
# List current backups
|
|
echo "Current backups:"
|
|
ls -lah mongodb_backup_*.tar.gz 2>/dev/null || echo "No previous backups found"
|
|
else
|
|
echo "ERROR: Failed to create compressed archive" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "ERROR: Backup directory not found at $BACKUP_DIR/$TEMP_BACKUP" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "ERROR: MongoDB backup failed" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "MongoDB backup completed successfully at $(date)"
|
|
'';
|
|
};
|
|
|
|
systemd.timers."mongo-backup" = {
|
|
wantedBy = ["timers.target"];
|
|
timerConfig = {
|
|
OnCalendar = "*-*-* 02:00:00";
|
|
RandomizedDelaySec = "30m";
|
|
Persistent = true;
|
|
};
|
|
};
|
|
|
|
# Traefik configuration
|
|
services.traefik.dynamicConfigOptions.http = {
|
|
services.${serviceName}.loadBalancer.servers = [
|
|
{
|
|
url = "http://localhost:${toString servicePort}/";
|
|
}
|
|
];
|
|
|
|
routers.${serviceName} = {
|
|
rule = "Host(`chat.az-gruppe.com`)";
|
|
tls = {
|
|
certResolver = "ionos";
|
|
};
|
|
service = serviceName;
|
|
entrypoints = "websecure";
|
|
};
|
|
};
|
|
}
|