From e35d5589b60a1d0b8ba7a310f7cc0a0582a672f0 Mon Sep 17 00:00:00 2001 From: alexz Date: Mon, 20 Jul 2026 06:17:06 -0700 Subject: [PATCH] ragflow: add RAGFlow v0.26.4 RAG platform (ES engine, models via ollama) --- apps/ragflow/config.json | 69 ++++++++++ apps/ragflow/docker-compose.json | 196 +++++++++++++++++++++++++++ apps/ragflow/metadata/description.md | 80 +++++++++++ apps/ragflow/metadata/logo.jpg | Bin 0 -> 22474 bytes 4 files changed, 345 insertions(+) create mode 100644 apps/ragflow/config.json create mode 100644 apps/ragflow/docker-compose.json create mode 100644 apps/ragflow/metadata/description.md create mode 100644 apps/ragflow/metadata/logo.jpg diff --git a/apps/ragflow/config.json b/apps/ragflow/config.json new file mode 100644 index 0000000..c5e569b --- /dev/null +++ b/apps/ragflow/config.json @@ -0,0 +1,69 @@ +{ + "$schema": "../app-info-schema.json", + "name": "RAGFlow", + "id": "ragflow", + "available": true, + "short_desc": "Open-source RAG engine with deep document understanding", + "author": "alexz", + "port": 9380, + "categories": ["ai"], + "tipi_version": 1, + "version": "0.26.4", + "source": "https://github.com/infiniflow/ragflow", + "website": "https://ragflow.io", + "exposable": true, + "dynamic_config": true, + "supported_architectures": ["amd64"], + "min_tipi_version": "4.0.0", + "form_fields": [ + { + "type": "random", + "label": "MySQL Root Password", + "hint": "Root password for the bundled MySQL 8.0 database that stores RAGFlow's metadata", + "env_variable": "RAGFLOW_MYSQL_ROOT_PASSWORD", + "min": 24, + "encoding": "hex" + }, + { + "type": "random", + "label": "Elasticsearch Password", + "hint": "Password for the built-in 'elastic' user on the Elasticsearch 8.11.3 document engine", + "env_variable": "RAGFLOW_ELASTIC_PASSWORD", + "min": 24, + "encoding": "hex" + }, + { + "type": "random", + "label": "MinIO Root Password", + "hint": "Root password for the bundled MinIO object storage service (file/blob storage)", + "env_variable": "RAGFLOW_MINIO_ROOT_PASSWORD", + "min": 24, + "encoding": "hex" + }, + { + "type": "random", + "label": "Redis Password", + "hint": "Password (requirepass) for the bundled Valkey/Redis cache and task queue", + "env_variable": "RAGFLOW_REDIS_PASSWORD", + "min": 24, + "encoding": "hex" + }, + { + "type": "random", + "label": "Session/JWT Signing Secret", + "hint": "Signs RAGFlow's session cookies and API JWTs (RAGFLOW_SECRET_KEY). Without this, the image auto-generates and persists a secret in Redis on first boot, but a per-install random value here is stronger and survives a Redis data wipe.", + "env_variable": "RAGFLOW_SECRET_KEY", + "min": 32, + "encoding": "hex" + }, + { + "type": "boolean", + "label": "Enable Self-Registration", + "hint": "Leave ON while this app is LAN-only so you can create the first admin account. Once the admin account exists, turn this OFF (re-save this form) BEFORE exposing the app on a public domain — see description for the full bootstrap sequence.", + "env_variable": "RAGFLOW_REGISTER_ENABLED", + "default": true + } + ], + "created_at": 1784530800000, + "updated_at": 1784553280814 +} diff --git a/apps/ragflow/docker-compose.json b/apps/ragflow/docker-compose.json new file mode 100644 index 0000000..8370a41 --- /dev/null +++ b/apps/ragflow/docker-compose.json @@ -0,0 +1,196 @@ +{ + "schemaVersion": 2, + "$schema": "https://schemas.runtipi.io/v2/dynamic-compose.json", + "services": [ + { + "name": "ragflow-es-init", + "image": "busybox:1.36", + "isMain": false, + "restart": "no", + "user": "root", + "command": ["chown", "-R", "1000:0", "/usr/share/elasticsearch/data"], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/es", + "containerPath": "/usr/share/elasticsearch/data", + "readOnly": false + } + ] + }, + { + "name": "ragflow-es01", + "image": "elasticsearch:8.11.3", + "environment": [ + { "key": "node.name", "value": "es01" }, + { "key": "ELASTIC_PASSWORD", "value": "${RAGFLOW_ELASTIC_PASSWORD}" }, + { "key": "bootstrap.memory_lock", "value": "false" }, + { "key": "discovery.type", "value": "single-node" }, + { "key": "xpack.security.enabled", "value": "true" }, + { "key": "xpack.security.http.ssl.enabled", "value": "false" }, + { "key": "xpack.security.transport.ssl.enabled", "value": "false" }, + { "key": "cluster.routing.allocation.disk.watermark.low", "value": "5gb" }, + { "key": "cluster.routing.allocation.disk.watermark.high", "value": "3gb" }, + { "key": "cluster.routing.allocation.disk.watermark.flood_stage", "value": "2gb" }, + { "key": "ES_JAVA_OPTS", "value": "-Xms2g -Xmx4g" } + ], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/es", + "containerPath": "/usr/share/elasticsearch/data", + "readOnly": false + } + ], + "ulimits": { + "memlock": { "soft": -1, "hard": -1 } + }, + "deploy": { + "resources": { + "limits": { + "memory": "8000M" + } + } + }, + "dependsOn": { + "ragflow-es-init": { "condition": "service_completed_successfully" } + }, + "healthCheck": { + "test": "curl http://127.0.0.1:9200 || exit 1", + "interval": "10s", + "timeout": "10s", + "retries": 120, + "startPeriod": "120s" + } + }, + { + "name": "ragflow-mysql", + "image": "mysql:8.0.39", + "environment": [ + { "key": "MYSQL_ROOT_PASSWORD", "value": "${RAGFLOW_MYSQL_ROOT_PASSWORD}" }, + { "key": "MYSQL_DATABASE", "value": "rag_flow" } + ], + "command": [ + "mysqld", + "--max_connections=1000", + "--character-set-server=utf8mb4", + "--collation-server=utf8mb4_unicode_ci", + "--default-authentication-plugin=mysql_native_password", + "--tls_version=TLSv1.2,TLSv1.3", + "--binlog_expire_logs_seconds=604800" + ], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/mysql", + "containerPath": "/var/lib/mysql", + "readOnly": false + } + ], + "healthCheck": { + "test": "mysqladmin ping -uroot -p${RAGFLOW_MYSQL_ROOT_PASSWORD}", + "interval": "10s", + "timeout": "10s", + "retries": 60, + "startPeriod": "30s" + } + }, + { + "name": "ragflow-minio", + "image": "pgsty/minio:RELEASE.2026-03-25T00-00-00Z", + "command": ["server", "--console-address", ":9001", "/data"], + "environment": [ + { "key": "MINIO_ROOT_USER", "value": "rag_flow" }, + { "key": "MINIO_ROOT_PASSWORD", "value": "${RAGFLOW_MINIO_ROOT_PASSWORD}" } + ], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/minio", + "containerPath": "/data", + "readOnly": false + } + ], + "healthCheck": { + "test": "curl -f http://127.0.0.1:9000/minio/health/live || exit 1", + "interval": "10s", + "timeout": "10s", + "retries": 60, + "startPeriod": "30s" + } + }, + { + "name": "ragflow-redis", + "image": "valkey/valkey:8.0.2", + "command": [ + "redis-server", + "--requirepass", "${RAGFLOW_REDIS_PASSWORD}", + "--maxmemory", "128mb", + "--maxmemory-policy", "allkeys-lru" + ], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/redis", + "containerPath": "/data", + "readOnly": false + } + ], + "healthCheck": { + "test": "redis-cli -a ${RAGFLOW_REDIS_PASSWORD} ping", + "interval": "10s", + "timeout": "10s", + "retries": 30, + "startPeriod": "15s" + } + }, + { + "name": "ragflow-server", + "image": "infiniflow/ragflow:v0.26.4", + "isMain": true, + "internalPort": 80, + "entrypoint": [ + "/bin/bash", + "-c", + "if [ \"$RAGFLOW_REGISTER_ENABLED\" = \"false\" ]; then export REGISTER_ENABLED=0; else export REGISTER_ENABLED=1; fi; exec ./entrypoint.sh \"$@\"", + "bash" + ], + "command": ["--enable-adminserver", "--init-model-provider-tables"], + "environment": [ + { "key": "TZ", "value": "${TZ}" }, + { "key": "DOC_ENGINE", "value": "elasticsearch" }, + { "key": "ES_HOST", "value": "ragflow-es01" }, + { "key": "ELASTIC_PASSWORD", "value": "${RAGFLOW_ELASTIC_PASSWORD}" }, + { "key": "MYSQL_HOST", "value": "ragflow-mysql" }, + { "key": "MYSQL_PORT", "value": "3306" }, + { "key": "MYSQL_DBNAME", "value": "rag_flow" }, + { "key": "MYSQL_PASSWORD", "value": "${RAGFLOW_MYSQL_ROOT_PASSWORD}" }, + { "key": "MINIO_HOST", "value": "ragflow-minio" }, + { "key": "MINIO_USER", "value": "rag_flow" }, + { "key": "MINIO_PASSWORD", "value": "${RAGFLOW_MINIO_ROOT_PASSWORD}" }, + { "key": "REDIS_HOST", "value": "ragflow-redis" }, + { "key": "REDIS_PASSWORD", "value": "${RAGFLOW_REDIS_PASSWORD}" }, + { "key": "RAGFLOW_SECRET_KEY", "value": "${RAGFLOW_SECRET_KEY}" }, + { "key": "RAGFLOW_REGISTER_ENABLED", "value": "${RAGFLOW_REGISTER_ENABLED}" }, + { "key": "API_PROXY_SCHEME", "value": "python" }, + { "key": "USE_DOCLING", "value": "false" }, + { "key": "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "value": "1" } + ], + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data/logs", + "containerPath": "/ragflow/logs", + "readOnly": false + } + ], + "dependsOn": { + "ragflow-es01": { "condition": "service_healthy" }, + "ragflow-mysql": { "condition": "service_healthy" }, + "ragflow-minio": { "condition": "service_healthy" }, + "ragflow-redis": { "condition": "service_healthy" } + }, + "healthCheck": { + "test": "curl -f http://127.0.0.1:80/ || exit 1", + "interval": "30s", + "timeout": "10s", + "retries": 10, + "startPeriod": "180s" + } + } + ] +} diff --git a/apps/ragflow/metadata/description.md b/apps/ragflow/metadata/description.md new file mode 100644 index 0000000..b7faf44 --- /dev/null +++ b/apps/ragflow/metadata/description.md @@ -0,0 +1,80 @@ +# RAGFlow + +RAGFlow is an open-source Retrieval-Augmented Generation (RAG) engine built on +deep document understanding. It combines robust document layout parsing (PDF, +Word, spreadsheets, slides, images, and more) with a configurable retrieval +pipeline so you can ground LLM answers in your own knowledge base with +traceable citations. + +## What's included + +This app deploys the full self-hosted RAGFlow stack in one shot: + +- **RAGFlow server** (`infiniflow/ragflow:v0.26.4`) — the web UI, HTTP API, + admin server, and task executor. This is the version-pinned image RAGFlow + ships as the lightweight variant since v0.22 (no bundled embedding models). +- **Elasticsearch 8.11.3** — the document/vector engine used for full-text and + hybrid search over parsed document chunks. A one-shot `ragflow-es-init` + helper container runs before it to fix ownership of the data directory + (Elasticsearch's image runs as uid 1000, but Docker auto-creates bind-mount + directories as root; without this step Elasticsearch crash-loops on first + install and the whole stack never comes up). +- **MySQL 8.0** — relational metadata store (users, datasets, chat sessions, + configuration). The `rag_flow` database is created automatically via + `MYSQL_DATABASE` on first boot. +- **MinIO** — S3-compatible object storage for uploaded documents and + generated artifacts. +- **Valkey (Redis-compatible) 8.0.2** — cache and task queue for the ingestion + pipeline. + +## Models + +No LLM or embedding model is bundled or hard-coded into this deployment. +After installing, open **Settings → Model Providers** in the RAGFlow UI and +add an **Ollama** provider pointing at your existing Ollama server on this +instance: + +- Base URL: `http://ollama-nvidia:11434` +- Fallback (if the container-name route doesn't resolve): `http://172.18.0.1:11434` + +## Admin bootstrap and public-exposure sequence (read before exposing) + +This app installs with **self-registration ON** by default so you can create +the first (admin) account. Follow this sequence exactly: + +1. Install and wait for `ragflow-server` to report healthy. +2. Visit the app on the LAN (`http://`), register the + first account — this becomes the admin account — and confirm you can sign + in and reach the dashboard. +3. Open this app's settings in the Runtipi dashboard and turn **Enable + Self-Registration** OFF, then save. This re-applies the app config with + `RAGFLOW_REGISTER_ENABLED=false`, which is translated internally to + RAGFlow's `REGISTER_ENABLED=0`. +4. Only after step 3 is confirmed, assign a public domain + (`ragflow.alexzaw.dev`) and enable Traefik exposure from the dashboard. + +Do not skip step 3 before going public — leaving self-registration on for an +internet-facing instance lets anyone create an account. + +## Session/JWT signing secret + +A random 32-byte hex value is generated at install time and passed as +`RAGFLOW_SECRET_KEY`, which RAGFlow uses directly (`common/settings.py: +init_secret_key()`) to sign session cookies and JWTs, as long as it's at +least 32 characters — ours is 64 hex characters. If this field were ever +left empty, RAGFlow's own fallback still applies: it auto-generates a secret +and persists it in Redis (`ragflow:system:secret_key`), so sessions survive +container restarts either way. The explicit field is stronger because it +doesn't depend on Redis data surviving a wipe/reset. + +## Residual public-exposure risk + +RAGFlow has no built-in 2FA and its own auth surface has not been +independently audited by this deployment. Before assigning the public +domain, put this app behind Cloudflare Access or an authentik forward-auth +gate at the network layer, in addition to the registration lockdown above. + +## Links + +- Source: https://github.com/infiniflow/ragflow +- Docs: https://ragflow.io/docs diff --git a/apps/ragflow/metadata/logo.jpg b/apps/ragflow/metadata/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b210edb4c8ba7d2e0e95d87008fe5d789c0c2e8e GIT binary patch literal 22474 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 G`hN!1_9;LB literal 0 HcmV?d00001