ragflow Documentation

RAGFlow is a leading open-source Retrieval-Augmented Generation (RAG) engine that fuses cutting-edge RAG with Agent capabilities to create a superior...

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy ragflow on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name ragflow -p 2881:2881 --restart always infiniflow/infinity:v0.7.4-x64-v3
Configured Services & Ports
โš™๏ธ es01
image: elasticsearch:${STACK_VERSION}
๐Ÿ”Œ Ports: ${ES_PORT}:9200
โš™๏ธ opensearch01
image: opensearchproject/opensearch:2.19.1
๐Ÿ”Œ Ports: ${OS_PORT}:9201
โš™๏ธ infinity
image: infiniflow/infinity:v0.7.4-x64-v3
๐Ÿ”Œ Ports: ${INFINITY_THRIFT_PORT}:23817, ${INFINITY_HTTP_PORT}:23820, ${INFINITY_PSQL_PORT}:5432
โš™๏ธ serenedb
image: serenedb/serenedb:26.07.5
๐Ÿ”Œ Ports: ${SERENEDB_PORT}:7890
โš™๏ธ oceanbase
image: oceanbase/oceanbase-ce:4.4.1.0-100000032025101610
๐Ÿ”Œ Ports: ${OCEANBASE_PORT:-2881}:2881
โš™๏ธ seekdb
image: oceanbase/seekdb:latest
๐Ÿ”Œ Ports: ${SEEKDB_PORT:-2881}:2881
โš™๏ธ vastbase
image: ${VB_IMAGE:-vastbase-g100-single-v1.4-3.0.9.31338-linux-x86_64:20260513112809}
๐Ÿ”Œ Ports: ${VB_BIND_ADDR:-127.0.0.1}:${EXPOSE_VB_PORT:-5432}:5432
โš™๏ธ sandbox-executor-manager
image: ${SANDBOX_EXECUTOR_MANAGER_IMAGE-infiniflow/sandbox-executor-manager:latest}
๐Ÿ”Œ Ports: 127.0.0.1:${SANDBOX_EXECUTOR_MANAGER_PORT:-9385}:9385
โš™๏ธ mysql
image: mysql:8.0.40
๐Ÿ”Œ Ports: ${EXPOSE_MYSQL_PORT}:3306
โš™๏ธ minio
image: pgsty/silo:RELEASE.2026-08-06T00-00-00Z
๐Ÿ”Œ Ports: ${MINIO_PORT}:9000, ${MINIO_CONSOLE_PORT}:9001
โš™๏ธ kvrocks
image: apache/kvrocks:2.16.0
๐Ÿ”Œ Ports: ${KVROCKS_PORT:-6379}:6379
โš™๏ธ jaeger
image: jaegertracing/jaeger:${JAEGER_VERSION:-2.19.0}
๐Ÿ”Œ Ports: ${JAEGER_OTLP_GRPC_PORT:-4317}:4317, ${JAEGER_OTLP_HTTP_PORT:-4318}:4318, ${JAEGER_UI_PORT:-16686}:16686
โš™๏ธ nats
image: nats:2.14.2
๐Ÿ”Œ Ports: ${EXPOSE_NATS_PORT:-4222}:4222, ${EXPOSE_NATS_MONITORING_PORT:-8222}:8222
โš™๏ธ tei-cpu
image: ${TEI_IMAGE_CPU}
๐Ÿ”Œ Ports: ${TEI_PORT-6380}:80
โš™๏ธ tei-gpu
image: ${TEI_IMAGE_GPU}
๐Ÿ”Œ Ports: ${TEI_PORT-6380}:80
โš™๏ธ kibana
image: kibana:${STACK_VERSION}
๐Ÿ”Œ Ports: ${KIBANA_PORT-5601}:5601
โš™๏ธ clickhouse
image: clickhouse/clickhouse-server:26.5.5.8
๐Ÿ”Œ Ports: ${EXPOSE_CLICKHOUSE_TCP_PORT:-9900}:9000, ${CLICKHOUSE_HTTP_PORT:-8123}:8123
docker-compose.yml
yaml (docker-compose.yml)
services:
  es01:
    profiles:
      - elasticsearch
    image: elasticsearch:${STACK_VERSION}
    volumes:
      - esdata01:/usr/share/elasticsearch/data
    # Official ES image ACL on /tmp denies writes for user elasticsearch (r-x only).
    # entrypoint.sh needs a writable temp dir for bash here-documents.
    tmpfs:
      - /tmp:mode=1777,size=512m
    ports:
      - ${ES_PORT}:9200
    env_file: .env
    environment:
      - node.name=es01
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=false
      - discovery.type=single-node
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
      - cluster.routing.allocation.disk.watermark.low=5gb
      - cluster.routing.allocation.disk.watermark.high=3gb
      - cluster.routing.allocation.disk.watermark.flood_stage=2gb
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test: ["CMD-SHELL", "curl http://localhost:9200"]
      interval: 10s
      timeout: 10s
      retries: 120
    networks:
      - ragflow
    restart: unless-stopped


  opensearch01:
    profiles:
      - opensearch
    image: opensearchproject/opensearch:2.19.1
    volumes:
      - osdata01:/usr/share/opensearch/data
    ports:
      - ${OS_PORT}:9201
    env_file: .env
    environment:
      - node.name=opensearch01
      - OPENSEARCH_PASSWORD=${OPENSEARCH_PASSWORD}
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD}
      - bootstrap.memory_lock=false
      - discovery.type=single-node
      - plugins.security.disabled=false
      - plugins.security.ssl.http.enabled=false
      - plugins.security.ssl.transport.enabled=true
      - cluster.routing.allocation.disk.watermark.low=5gb
      - cluster.routing.allocation.disk.watermark.high=3gb
      - cluster.routing.allocation.disk.watermark.flood_stage=2gb
      - http.port=9201
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test: ["CMD-SHELL", "curl http://localhost:9201"]
      interval: 10s
      timeout: 10s
      retries: 120
    networks:
      - ragflow
    restart: unless-stopped


  infinity:
    profiles:
      - infinity
    image: infiniflow/infinity:v0.7.4-x64-v3
    volumes:
      - infinity_data:/var/infinity
      - ./infinity_conf.toml:/infinity_conf.toml
    command: ["-f", "/infinity_conf.toml"]
    ports:
      - ${INFINITY_THRIFT_PORT}:23817
      - ${INFINITY_HTTP_PORT}:23820
      - ${INFINITY_PSQL_PORT}:5432
    env_file: .env
    mem_limit: ${MEM_LIMIT}
    ulimits:
      nofile:
        soft: 500000
        hard: 500000
    networks:
      - ragflow
    healthcheck:
      test: ["CMD", "curl", "http://localhost:23820/admin/node/current"]
      interval: 10s
      timeout: 10s
      retries: 120
    restart: unless-stopped


  serenedb:
    profiles:
      - serenedb
    image: serenedb/serenedb:26.07.5
    env_file: .env
    environment:
      - POSTGRES_PASSWORD=${SERENEDB_PASSWORD}
    ports:
      - ${SERENEDB_PORT}:7890
    volumes:
      - serenedb_data:/var/lib/serenedb
    mem_limit: ${MEM_LIMIT}
    networks:
      - ragflow
    healthcheck:
      test: ["CMD", "pg_isready", "-h", "127.0.0.1", "-p", "7890", "-U", "postgres"]
      interval: 10s
      timeout: 10s
      retries: 120
    restart: unless-stopped


  oceanbase:
    profiles:
      - oceanbase
    image: oceanbase/oceanbase-ce:4.4.1.0-100000032025101610
    entrypoint: ["bash", "/root/boot/ragflow-oceanbase-entrypoint.sh"]
    ulimits:
      nofile:
        soft: 655350
        hard: 655350
    volumes:
      - ./oceanbase/data:/root/ob
      - ./oceanbase/conf:/root/.obd/cluster
      - ./oceanbase/init.d:/root/boot/init.d
      - ./oceanbase-entrypoint.sh:/root/boot/ragflow-oceanbase-entrypoint.sh:ro
    ports:
      - ${OCEANBASE_PORT:-2881}:2881
    env_file: .env
    environment:
      - MODE=normal
      - OB_SERVER_IP=127.0.0.1
    mem_limit: ${MEM_LIMIT}
    healthcheck:
      test: [ 'CMD-SHELL', 'obclient -h127.0.0.1 -P2881 -uroot@${OB_TENANT_NAME:-ragflow} -p${OB_TENANT_PASSWORD:-infini_rag_flow} -e "CREATE DATABASE IF NOT EXISTS ${OCEANBASE_DOC_DBNAME:-ragflow_doc};"' ]
      interval: 10s
      retries: 30
      start_period: 30s
      timeout: 10s
    networks:
      - ragflow
    restart: unless-stopped


  seekdb:
    profiles:
      - seekdb
    image: oceanbase/seekdb:latest
    container_name: seekdb
    volumes:
      # SeekDB 1.4+ stores data in /var/lib/seekdb.
      # For older 1.3.x images, change the container path to /var/lib/oceanbase.
      - ./seekdb:/var/lib/seekdb
    ports:
      - ${SEEKDB_PORT:-2881}:2881
    env_file: .env
    environment:
      - ROOT_PASSWORD=${SEEKDB_PASSWORD:-infini_rag_flow}
      - MEMORY_LIMIT=${SEEKDB_MEMORY_LIMIT:-2G}
      - REPORTER=ragflow-seekdb
    mem_limit: ${MEM_LIMIT}
    healthcheck:
      test: ['CMD-SHELL', 'mysql -h127.0.0.1 -P2881 -uroot -p${SEEKDB_PASSWORD:-infini_rag_flow} -e "CREATE DATABASE IF NOT EXISTS ${SEEKDB_DOC_DBNAME:-ragflow_doc};"']
      interval: 5s
      retries: 60
      timeout: 5s
    networks:
      - ragflow
    restart: unless-stopped


  vastbase:
    profiles:
      - vastbase
    image: ${VB_IMAGE:-vastbase-g100-single-v1.4-3.0.9.31338-linux-x86_64:20260513112809}
    env_file: .env
    environment:
      - VB_PASSWORD=${VB_PASSWORD}
      - VB_USERNAME=${VB_USERNAME}
      - VB_VEC_DBNAME=${VB_VEC_DBNAME:-ragflow}
      - VB_DBCOMPATIBILITY=${VB_DBCOMPATIBILITY:-B}
    # Bind the published port to loopback by default: the database ships
    # default credentials, and RAGFlow reaches it over the shared `ragflow`
    # network. Remote access is an explicit opt-in through VB_BIND_ADDR
    # (e.g. 0.0.0.0 or a specific interface IP) in docker/.env.
    ports:
      - ${VB_BIND_ADDR:-127.0.0.1}:${EXPOSE_VB_PORT:-5432}:5432
    volumes:
      - vastbase_data:/home/vastbase/data
      - ./vastbase/init:/docker-entrypoint-initdb.d
      - ./vastbase/license:/home/vastbase/vastbase/lic
    mem_limit: ${MEM_LIMIT}
    networks:
      - ragflow
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "vsql -c 'SELECT 1'"]
      interval: 10s
      timeout: 10s
      retries: 120


  sandbox-executor-manager:
    profiles:
      - sandbox
    image: ${SANDBOX_EXECUTOR_MANAGER_IMAGE-infiniflow/sandbox-executor-manager:latest}
    privileged: true
    # Bind to loopback only: the /run endpoint executes arbitrary sandboxed
    # code. RAGFlow reaches this service over the shared `ragflow` network.
    ports:
      - 127.0.0.1:${SANDBOX_EXECUTOR_MANAGER_PORT:-9385}:9385
    env_file: .env
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - ragflow
    security_opt:
      - no-new-privileges:true
    environment:
      - SANDBOX_EXECUTOR_MANAGER_POOL_SIZE=${SANDBOX_EXECUTOR_MANAGER_POOL_SIZE:-3}
      - SANDBOX_BASE_PYTHON_IMAGE=${SANDBOX_BASE_PYTHON_IMAGE:-infiniflow/sandbox-base-python:latest}
      - SANDBOX_BASE_NODEJS_IMAGE=${SANDBOX_BASE_NODEJS_IMAGE:-infiniflow/sandbox-base-nodejs:latest}
      - SANDBOX_ENABLE_SECCOMP=${SANDBOX_ENABLE_SECCOMP:-false}
      - SANDBOX_MAX_MEMORY=${SANDBOX_MAX_MEMORY:-256m}
      - SANDBOX_TIMEOUT=${SANDBOX_TIMEOUT:-10s}
      # Shared secret for the /run API. Set it in .env (same value is passed
      # to the ragflow service). Current Sandbox source rejects unconfigured
      # authentication; verify the behavior of the deployed image version.
      - SANDBOX_EXECUTOR_MANAGER_API_TOKEN=${SANDBOX_EXECUTOR_MANAGER_API_TOKEN:-}
      # Sandbox runner containers get no external network by default.
      - SANDBOX_CONTAINER_NETWORK=${SANDBOX_CONTAINER_NETWORK:-none}
    healthcheck:
      test: ["CMD", "curl", "http://localhost:9385/healthz"]
      interval: 10s
      timeout: 10s
      retries: 120
    restart: unless-stopped


  mysql:
    profiles:
      - mysql
      - metadata-mysql
      - metadata-MySQL
      - metadata-MYSQL
    # mysql:5.7 linux/arm64 image is unavailable.
    image: mysql:8.0.40
    env_file: .env
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
    # Ingestion throughput tuning, OPT-IN. The ingestion sink commits per progress
    # event, so MySQL's own defaults (innodb_flush_log_at_trx_commit=1 +
    # sync_binlog=1 on a 128MB buffer pool) spent 68ms of CPU and two fsyncs on
    # every commit: 211k commits had burned 14.4k seconds of MySQL CPU and capped
    # ingestion at ~23 documents/minute, with mysqld the busiest process on the
    # box. Relaxing the two settings brings the same commit down to 1.6ms and
    # ingestion to ~56 documents/minute (measured, same load).
    #
    # They are NOT the default because they apply to every write in this instance,
    # not only to the ingestion bookkeeping they were measured for: after a
    # host-level crash (not a mysqld restart) a client can lose transactions it
    # already observed as committed. A deployment that treats the whole database as
    # rebuildable opts in through docker/.env:
    #   MYSQL_FLUSH_LOG_AT_TRX_COMMIT=2
    #   MYSQL_SYNC_BINLOG=0
    command:
      - --max_connections=1000
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-authentication-plugin=mysql_native_password
      - --tls_version=TLSv1.2,TLSv1.3
      - --init-file=/data/application/init.sql
      - --binlog_expire_logs_seconds=604800
      - --innodb-flush-log-at-trx-commit=${MYSQL_FLUSH_LOG_AT_TRX_COMMIT:-1}
      - --sync-binlog=${MYSQL_SYNC_BINLOG:-1}
      # 1G, not 4G. The database is 3.6G but its hot working set is under 1G
      # (document/file/file2document/ingestion_task_log sum to ~880M), and 2.66G
      # of the 3.6G is pipeline_operation_log, a log table that is written but
      # not re-read. Ingestion is embedding-bound, not database-bound: the
      # per-stage database cost is 0.03-0.10s, unchanged when the pool was
      # shrunk from 4G to 1G online. The 4G pool simply wasted 3G of a box with
      # no swap. Restart mysqld after changing this (an online shrink returns
      # only part of the memory to the OS).
      - --innodb-buffer-pool-size=1G
      - --innodb-io-capacity=2000
      - --innodb-io-capacity-max=4000
      - --innodb-redo-log-capacity=1G
    ports:
      - ${EXPOSE_MYSQL_PORT}:3306
    volumes:
      - mysql_data:/var/lib/mysql
      - ./init.sql:/data/application/init.sql
    networks:
      - ragflow
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-uroot", "-p${MYSQL_PASSWORD}"]
      interval: 1s
      timeout: 2s
      retries: 60
      start_period: 30s
    restart: unless-stopped


  minio:
    image: pgsty/silo:RELEASE.2026-08-06T00-00-00Z
    command: ["server", "--console-address", ":9001", "/data"]
    ports:
      - ${MINIO_PORT}:9000
      - ${MINIO_CONSOLE_PORT}:9001
    env_file: .env
    environment:
      - MINIO_ROOT_USER=${MINIO_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
    volumes:
      - minio_data:/data
    networks:
      - ragflow
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 10s
      timeout: 10s
      retries: 120


  kvrocks:
    # Apache Kvrocks: a RocksDB-backed, Redis-protocol-compatible store used
    # ONLY by the Go services (ragflow-cpu / ragflow-gpu), which override
    # REDIS_HOST=kvrocks in docker-compose-go.yml. The Python services keep
    # using the `redis` (Valkey) service above, so this is a dual-backend setup.
    # Pinned to 2.16.0+ on purpose (see docker/kvrocks-entrypoint.sh): older
    # tags such as kvrocks/kvrocks:latest (== 2.0.6) carry a TTL contract bug
    # that breaks the RunTracker CAS lease, and they reject the Redis-style
    # maxmemory/maxmemory-policy settings.
    image: apache/kvrocks:2.16.0
    # Kvrocks' config file does not expand ${ENV} and its CLI rejects
    # `--requirepass` as a flag, so the entrypoint renders the config (including
    # the password from REDIS_PASSWORD) at startup. `user: "0"` lets it write the
    # config and the RocksDB data dir regardless of the mounted volume ownership.
    entrypoint: ["/bin/sh", "/etc/kvrocks/entrypoint.sh"]
    user: "0:0"
    env_file: .env
    # Publish the Kvrocks port so a host-run Go binary (e.g. ./bin/ragflow_server
    # --ingestor) can reach it. The host-facing port uses KVROCKS_PORT (default 6379
    # locally, so a local host binary connects to localhost:6379). In CI the port is
    # offset per job (KVROCKS_PORT = 6381 + PORT_OFFSET, reserved alongside the other
    # CI ports) so concurrent test runs on a shared runner do not clash, and it stays
    # distinct from REDIS_PORT (used by the Valkey `redis` service that the Python
    # deployment still runs next to Kvrocks). The container port (right side) stays
    # 6379, and the Go services reach `kvrocks:6379` inside the docker network
    # regardless of the host mapping (KVROCKS_PORT stays 6379, set by the Go overlay).
    ports:
      - "${KVROCKS_PORT:-6379}:6379"
    volumes:
      - kvrocks_data:/var/lib/kvrocks
      - ./kvrocks-entrypoint.sh:/etc/kvrocks/entrypoint.sh:ro
    networks:
      - ragflow
    restart: unless-stopped
    healthcheck:
      # The Kvrocks image ships redis-cli and requirepass is enforced, so ping
      # with the password. (The image has no nc, so a raw-tcp probe is wrong.)
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 10s
      retries: 120


  jaeger:
    profiles:
      - jaeger
    image: jaegertracing/jaeger:${JAEGER_VERSION:-2.19.0}
    ports:
      - ${JAEGER_OTLP_GRPC_PORT:-4317}:4317
      - ${JAEGER_OTLP_HTTP_PORT:-4318}:4318
      - ${JAEGER_UI_PORT:-16686}:16686
    env_file: .env
    environment:
      - COLLECTOR_OTLP_ENABLED=true
    networks:
      - ragflow
    restart: unless-stopped


  nats:
    image: nats:2.14.2
    ports:
      - ${EXPOSE_NATS_PORT:-4222}:4222
      - ${EXPOSE_NATS_MONITORING_PORT:-8222}:8222
    volumes:
      - nats_data:/data
    command: -js -sd /data --http_port 8222
    env_file: .env
    networks:
      - ragflow
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "nats-server", "--health-check"]
      interval: 10s
      timeout: 10s
      retries: 30


  tei-cpu:
    profiles:
      - tei-cpu
    image: ${TEI_IMAGE_CPU}
    hostname: tei
    ports:
      - ${TEI_PORT-6380}:80
    env_file: .env
    networks:
      - ragflow
    command: ["--model-id", "/data/${TEI_MODEL}", "--auto-truncate"]
    restart: unless-stopped


  tei-gpu:
    profiles:
      - tei-gpu
    image: ${TEI_IMAGE_GPU}
    hostname: tei
    ports:
      - ${TEI_PORT-6380}:80
    env_file: .env
    networks:
      - ragflow
    command: ["--model-id", "/data/${TEI_MODEL}", "--auto-truncate"]
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    restart: unless-stopped


  kibana:
    profiles:
      - kibana
    image: kibana:${STACK_VERSION}
    ports:
      - ${KIBANA_PORT-5601}:5601
    env_file: .env
    volumes:
      - kibana_data:/usr/share/kibana/data
    depends_on:
      es01:
        condition: service_started
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5601/api/status"]
      interval: 10s
      timeout: 10s
      retries: 120
    networks:
      - ragflow
    restart: unless-stopped


  clickhouse:
    profiles:
      - clickhouse
    image: clickhouse/clickhouse-server:26.5.5.8
    volumes:
      - clickhouse_data:/var/lib/clickhouse
      - ./init-clickhouse.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - ${EXPOSE_CLICKHOUSE_TCP_PORT:-9900}:9000
      - ${CLICKHOUSE_HTTP_PORT:-8123}:8123
    env_file: .env
    environment:
      - CLICKHOUSE_USER=${CLICKHOUSE_USER:-ragflow}
      - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-infini_rag_flow}
      - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
    mem_limit: ${MEM_LIMIT}
    ulimits:
      nofile:
        soft: 655350
        hard: 655350
    healthcheck:
      test: ["CMD", "clickhouse-client", "--user", "${CLICKHOUSE_USER:-ragflow}", "--password", "${CLICKHOUSE_PASSWORD:-infini_rag_flow}", "-q", "SELECT 1"]
      interval: 10s
      timeout: 10s
      retries: 30
      start_period: 30s
    networks:
      - ragflow
    restart: unless-stopped


volumes:
  esdata01:
    driver: local
  osdata01:
    driver: local
  infinity_data:
    driver: local
  serenedb_data:
    driver: local
  ob_data:
    driver: local
  seekdb_data:
    driver: local
  vastbase_data:
    driver: local
  mysql_data:
    driver: local
  minio_data:
    driver: local
  redis_data:
    driver: local
  kvrocks_data:
    driver: local
  tei_data:
    driver: local
  kibana_data:
    driver: local
  nats_data:
    driver: local
  clickhouse_data:
    driver: local

networks:
  ragflow:
    driver: bridge

[Cloud](https://cloud.ragflow.io) | [Documentation](https://ragflow.io/docs/dev/) | [Roadmap](https://github.com/infiniflow/ragflow/issues/12241) | [Discord](https://discord.gg/NjYzJD3GM3)

๐Ÿ“• Table of Contents

๐Ÿ’ก What is RAGFlow?

RAGFlow is a leading open-source Retrieval-Augmented Generation (RAG) engine that fuses cutting-edge RAG with Agent capabilities to create a superior context layer for LLMs. It offers a streamlined RAG workflow adaptable to enterprises of any scale. Powered by a converged context engine and pre-built agent templates, RAGFlow enables developers to transform complex data into high-fidelity, production-ready AI systems with exceptional efficiency and precision.

๐ŸŽฎ Get Started

Try our cloud service at https://cloud.ragflow.io.

For local deployment, see Local Deployment.

๐Ÿ”ฅ Latest Updates

  • 2026-09-29 RAGFlow 1.0.0-rc1 released.
  • 2026-09-10 Added website content ingestion through sitemaps.
  • 2026-08-19 Introduced Knowledge Compilation to generate Wikis, Graphs, Trees, PageIndex, Mind Maps, Timelines, and Skills at the document and dataset levels.
  • 2026-08-19 Introduced Agentic RAG with Low, Medium, High, and Ultra thinking modes.
  • 2026-07-02 Added Google BigQuery data source ingestion and incremental synchronization.

See the full release notes for more updates.

๐ŸŽ‰ Stay Tuned

โญ๏ธ Star our repository to stay up-to-date with exciting new features and improvements! Get instant notifications for new
releases! ๐ŸŒŸ

๐ŸŒŸ Key Features

๐Ÿญ **"Quality in, quality out"**

  • Deep document understanding-based knowledge extraction from unstructured data with complicated
    formats.
  • Finds "needle in a data haystack" of literally unlimited tokens.

๐Ÿฑ **Template-based chunking**

  • Intelligent and explainable.
  • Plenty of template options to choose from.

๐Ÿงฉ **Knowledge Compilation**

  • Compile content at the document and dataset levels into structured knowledge artifacts.
  • Use compilation templates to generate Wikis, Graphs, Trees, PageIndex, Mind Maps, Timelines, and Skills for different knowledge organization and reuse needs.
  • Configure compilation models and processing rules, and view, update, and regenerate knowledge artifacts.

๐Ÿง  **Agentic Retrieval**

  • Perform multi-step retrieval for complex questions: the model analyzes the question and, when needed, breaks it down, retrieves knowledge, and verifies evidence.
  • Gather more complete context through multiple rounds of retrieval and reasoning to help generate well-grounded answers.
  • Choose Low, Medium, High, or Ultra thinking modes to control retrieval and reasoning depth according to question complexity.

โš™๏ธ **Go-native service architecture**

  • API, Admin, Ingestor, and Syncer are provided by a unified Go service.
  • DeepDoc runs within the Go process and handles layout analysis, OCR, and table recognition.
  • Go services use CGO to call native document parsing libraries and ONNX Runtime.
  • MCP and Sandbox Executor are optional capabilities that can be enabled as needed.

๐ŸŒฑ **Grounded citations with reduced hallucinations**

  • Visualization of text chunking to allow human intervention.
  • Quick view of the key references and traceable citations to support grounded answers.

๐Ÿ” **Compatibility with heterogeneous data sources**

  • Supports Word, Slides, Excel, TXT, images, scanned copies, structured data, web pages, and more.

๐Ÿ›€ **Automated and effortless RAG workflow**

  • Streamlined RAG orchestration catered to both personal and large businesses.
  • Configurable LLMs as well as embedding models.
  • Multiple recall paired with fused re-ranking.
  • Intuitive APIs for seamless integration with business.

๐Ÿ”Ž System Architecture

๐Ÿ  Local Deployment

๐Ÿณ Docker Deployment

๐Ÿ“ Docker Deployment Prerequisites

  • Recommended starting configuration: 4 CPU cores, 16 GB RAM, and 50 GB of available disk space. Actual requirements depend on the document engine, data volume, parsing tasks, and concurrency. Local models and other optional components may require additional resources.
  • Docker >= 24.0.0 & Docker Compose >= v2.26.1
  • gVisor: Required only when using the Self-Managed container Sandbox.

Docker deployment does not require Go on the host. Self-Managed container Sandbox requires gVisor; other Sandbox providers do not require gVisor on the RAGFlow host.

[!TIP]
If you have not installed Docker on your local machine (Windows, Mac, or Linux), see Install Docker Engine.

๐Ÿš€ Start up the server

  1. If using Elasticsearch, set vm.max_map_count on the Docker host to at least 262144. This step is usually unnecessary with Infinity:

    To check the value of vm.max_map_count:

    bash
    sysctl vm.max_map_count

    If you use Elasticsearch and the value is below 262144, reset it:

    bash
    # In this case, we set it to 262144:
    sudo sysctl -w vm.max_map_count=262144

    This change will be reset after a system reboot. To ensure your change remains permanent, add or update the
    vm.max_map_count value in /etc/sysctl.conf accordingly:

    bash
    vm.max_map_count=262144
  2. Clone the repository:

    bash
    git clone https://github.com/infiniflow/ragflow.git
  3. Check out the Go release tag and start the prebuilt Go image with Docker Compose:

    [!NOTE]
    The v1.0.0-rc1 tag and later release tags use the Go implementation. See the Go Docker image build and platform support guide only if you need to build an image locally.

    bash
    # Enter the Docker deployment directory.
    cd ragflow/docker
    # Check out the Go v1.0.0-rc1 release tag.
    git checkout v1.0.0-rc1
    # Start the Go services and their dependencies in the background.
    docker compose -f docker-compose.yml up -d

    In the default MySQL configuration, the Go image entrypoint runs database migrations before starting Syncer, Admin, API, and Ingestor through bin/ragflow_server.

    In the RAGFlow open-source 1.0 release, DeepDoc uses CPU inference for layout analysis, OCR, and table recognition.

  4. Check service status and API readiness after startup:

    bash
    docker ps

    The command above displays dependency status. RAGFlow itself does not define a Compose healthcheck; confirm readiness through its API:

    bash
    curl -f http://localhost/api/v1/system/healthz

    An HTTP 200 response indicates readiness. If you changed SVR_WEB_HTTP_PORT, use that port in the health-check URL. If startup fails, inspect the relevant service logs with docker logs --tail 50 <service>.

  5. In your web browser, enter the IP address of your server and log in to RAGFlow.

    With the default settings, you only need to enter http://IP_OF_YOUR_MACHINE (sans port number) as the default
    HTTP serving port 80 can be omitted when using the default configurations.

  6. After signing in, add an LLM, embedding, and reranker on the model provider page, including the model name, service address, and API key.

โš™๏ธ Docker Configuration and Adjustment

Go Docker deployment uses docker/.env and docker/docker-compose.yml, uses Kvrocks for cache and Checkpoint storage, and uses NATS JetStream as the message queue. Configure the image, ports, passwords, document engine, and model image source as described in the Docker configuration guide. For platform limitations and macOS requirements, see the Go Docker image build and platform support guide.

For document-engine changes, configuration updates, restarting services, and retaining or removing existing data, follow the Docker configuration guide.

๐Ÿ”จ Launch Go Services from Source

๐Ÿ“ Source Build Prerequisites

Install the Go version specified in go.mod (currently Go 1.27), Clang 20, LLD 20, CMake โ‰ฅ 4.0, PCRE2 development files, and the native libraries required by CGO. Node.js and npm are required only when developing the React frontend.

  1. Clone the repository and install the Go version specified in go.mod (currently Go 1.27), Clang 20, LLD 20, CMake โ‰ฅ 4.0, and PCRE2 development files. Go services depend on CGO and native static libraries; build.sh sets the required build parameters.

    bash
    git clone https://github.com/infiniflow/ragflow.git
    cd ragflow
  2. Prepare native libraries, model files, and tokenizer assets with the Go dependency download script, then build the Go services:

    bash
    python3 -m venv /tmp/ragflow-go-download-venv
    /tmp/ragflow-go-download-venv/bin/python -m pip install requests huggingface-hub
    /tmp/ragflow-go-download-venv/bin/python ragflow_deps/download_deps.py
    bash build.sh --all

    The script prepares native libraries and model resources required for the Go build and needs requests and huggingface-hub. Skip this step if you have prepared the same resources by other means. When started from the repository root, Go services automatically find internal/rag/res/deepdoc; to start from another directory, set DEEPDOC_MODEL_DIR to its absolute path.

  3. Start the local dependencies and make sure the hosts and ports in conf/service_conf.yaml point to addresses accessible from the host. Go source services connect to Compose-exposed Kvrocks at localhost:6379, while Go Docker services connect to Kvrocks on the container network. If using the default Elasticsearch engine, set vm.max_map_count on the Docker host to at least 262144 first.

    bash
    sudo sysctl -w vm.max_map_count=262144
    docker compose --env-file docker/.env -f docker/docker-compose-base.yml \
      up -d --wait es01 mysql minio nats kvrocks clickhouse
  4. Migrate the database first, then start the Go services in order in five separate terminals. Run each command below from the repository root. Keep the four service terminals running. The migration command does not need RAGFLOW_DEV_MODE; set RAGFLOW_DEV_MODE=true for Admin, Ingestor, Syncer, and API in a development environment. Close the migration terminal after the migration completes.

    Terminal 1: migrate the database.

    bash
    ./bin/ragflow_server --migrate

    Terminal 2: start Admin (target port 9381).

    bash
    RAGFLOW_DEV_MODE=true ./bin/ragflow_server --admin

    Terminal 3: start Ingestor.

    bash
    RAGFLOW_DEV_MODE=true ./bin/ragflow_server --ingestor

    Terminal 4: start Syncer.

    bash
    RAGFLOW_DEV_MODE=true ./bin/ragflow_server --syncer

    Terminal 5: start API (target port 9380).

    bash
    RAGFLOW_DEV_MODE=true ./bin/ragflow_server --api

    The startup modes work as follows:

    • --migrate: Runs database migrations and exits when complete.
    • --admin: Starts the Admin service for management and initialization operations.
    • --ingestor: Starts the Ingestor service for data ingestion and parsing tasks.
    • --syncer: Starts the Syncer service for data synchronization tasks.
    • --api: Starts the API service for the Web UI, SDKs, and external clients.

    RAGFLOW_DEV_MODE=true is only for development; it disables the downgrade check between code and database migration versions, but does not run migrations or change the database schema. Do not set it in production. Start Admin before the other services. After database migration, RAGFLOW_DEV_MODE=true bash build.sh --run can conveniently start Admin, Ingestor, and API. It does not start Syncer; start it separately with RAGFLOW_DEV_MODE=true ./bin/ragflow_server --syncer for the complete service chain.

  5. Only when developing the frontend, install Node.js and npm, then start the React frontend:

    bash
    cd web
    npm install
    API_PROXY_SCHEME=go npm run dev

    In another terminal, confirm that the Go API is ready:

    bash
    curl -f http://127.0.0.1:9380/api/v1/system/healthz

    An HTTP 200 response indicates that the API is responding. See Launch Service from Source for complete frontend, ClickHouse, and DeepDoc verification steps.

    When development is complete, press Ctrl+C in each service terminal to stop the processes. To stop dependencies but keep the containers for next time, run docker compose --env-file docker/.env -f docker/docker-compose-base.yml stop es01 mysql minio nats kvrocks clickhouse. To remove the dependency containers and Compose network while keeping named data volumes, run docker compose --env-file docker/.env -f docker/docker-compose-base.yml down.

See Launch Service from Source for details.

๐Ÿ“š Documentation

๐Ÿ“œ Roadmap

See the RAGFlow Roadmap 2026

๐Ÿ„ Community

๐Ÿ™Œ Contributing

RAGFlow flourishes via open-source collaboration. In this spirit, we embrace diverse contributions from the community.
If you would like to be a part, review our Contribution Guidelines first.