Multi-Backend Object Storage#
RAGFlow abstracts all binary blob storage (uploaded documents, parsed chunks, images, etc.) behind a single global STORAGE_IMPL object in common/settings.py. Callers throughout the application call settings.STORAGE_IMPL.put(...), .get(...), and .rm(...) without knowing which cloud backend is active.
Supported Backends#
Seven backends are registered in the Storage enum (defined in common/constants.py) and wired up in StorageFactory (common/settings.py):
| Enum value | Class | Implementation file |
|---|---|---|
MINIO | RAGFlowMinio | rag/utils/minio_conn.py |
AWS_S3 | RAGFlowS3 | rag/utils/s3_conn.py |
AZURE_SPN | RAGFlowAzureSpnBlob | rag/utils/azure_spn_conn.py |
AZURE_SAS | RAGFlowAzureSasBlob | rag/utils/azure_sas_conn.py |
OSS | RAGFlowOSS | rag/utils/oss_conn.py |
GCS | RAGFlowGCS | rag/utils/gcs_conn.py |
OPENDAL | OpenDALStorage | rag/utils/opendal_conn.py |
Consistent Interface (Duck Typing)#
There is no formal abstract base class. All implementations share the same five required method signatures, enforced at runtime by EncryptedStorageWrapper:
put(bucket, fnm, binary, tenant_id=None)— upload objectget(bucket, fnm, tenant_id=None)— download objectrm(bucket, fnm, tenant_id=None)— delete objectobj_exist(bucket, fnm, tenant_id=None)— existence checkhealth()— liveness check
Optional methods (get_presigned_url, copy, move, bucket_exists, remove_bucket) are available on some backends but not all.
Selection and Initialization#
The active backend is controlled by the STORAGE_IMPL environment variable (string name of the Storage enum member, defaulting to "MINIO") . During init_settings(), the backend-specific config block is loaded from the service YAML (minio, s3, azure, oss, or gcs section), then StorageFactory.create(Storage[STORAGE_IMPL_TYPE]) instantiates the singleton .
Each backend class is decorated with @singleton (e.g., RAGFlowMinio), so only one instance exists for the lifetime of the process.
Encryption Layer#
An optional EncryptedStorageWrapper wraps any backend to add transparent AES-256-CBC encryption. It is activated when RAGFLOW_CRYPTO_ENABLED=true, with the key supplied via RAGFLOW_CRYPTO_KEY . The wrapper delegates all calls to the underlying backend after encrypting (on put) or decrypting (on get) the payload.
MinIO-Specific: Single-Bucket Mode#
RAGFlowMinio supports an optional bucket + prefix_path config that collapses all logical buckets into a single physical MinIO bucket, with the original bucket name used as a path prefix . This is useful for MinIO deployments with bucket-count limits.
Adding a New Backend#
- Implement the five required methods (see interface above).
- Decorate the class with
@singleton. - Add an entry to the
Storageenum incommon/constants.py. - Register the mapping in
StorageFactory.storage_mapping. - Add a config-loading branch in
init_settings().