This document covers LobeChat's file storage architecture and S3/MinIO integration, including upload flows, deduplication strategies, and deployment configurations. For information about the RAG pipeline that processes these files, see 5.2 Chunking and Embedding Pipeline. For database models related to files, see 6.2 Core Data Models.
LobeChat uses S3-compatible object storage for persisting uploaded files and documents. The system supports self-hosted RustFS deployments (default in Docker Compose) and cloud-based S3 services (AWS S3, Cloudflare R2, etc.).
Diagram: File Storage System Architecture
Sources: docker-compose/local/docker-compose.yml56-94 packages/database/src/models/file.ts19-40 docs/development/database-schema.dbml354-395
LobeChat requires the following S3-related environment variables:
| Variable | Required | Description | Example |
|---|---|---|---|
S3_ENDPOINT | Yes | S3 API endpoint URL | http://localhost:9000 |
S3_PUBLIC_DOMAIN | Yes | Public URL for file access | http://localhost:9000 |
S3_BUCKET | Yes | Bucket name for file storage | lobe |
S3_ACCESS_KEY_ID / S3_ACCESS_KEY | Yes | S3 access key | admin |
S3_SECRET_ACCESS_KEY | Yes | S3 secret key | YOUR_RUSTFS_PASSWORD |
S3_ENABLE_PATH_STYLE | No | Use path-style URLs (for RustFS) | 1 |
S3_SET_ACL | No | Set object ACL on upload | 0 |
LLM_VISION_IMAGE_USE_BASE64 | No | Use base64 for vision models | 1 |
When using the default RustFS deployment in Docker Compose:
| Variable | Required | Description | Example |
|---|---|---|---|
RUSTFS_ACCESS_KEY | Yes | RustFS access key | admin |
RUSTFS_SECRET_KEY | Yes | RustFS secret key | YOUR_RUSTFS_PASSWORD |
RUSTFS_PORT | No | RustFS API port | 9000 |
RUSTFS_LOBE_BUCKET | Yes | Bucket name in RustFS | lobe |
Sources: docker-compose/local/.env.example16-43 docker-compose/local/docker-compose.yml56-71
LobeChat implements a two-tier file storage strategy to optimize storage and enable deduplication:
The global_files table stores the actual file metadata and S3 references. Files are deduplicated by their SHA-256 hash.
Key fields:
hash_id: SHA-256 hash of file content (primary key)url: S3 object URLsize: File size in bytesfile_type: MIME typemetadata: Additional file metadata (JSONB)creator: User ID who first uploaded the filecreated_at: Creation timestampaccessed_at: Last access timestampThe files table contains user-specific references to global files, enabling:
Key fields:
id: Unique file reference ID (text)user_id: Owner of this file referencefile_hash: Reference to global_files.hash_idname: User-defined file nameurl: S3 object URL (denormalized for performance)size: File size in bytes (denormalized)file_type: MIME type (denormalized)source: Source path or identifierparent_id: Optional parent file for hierarchymetadata: Custom metadata (JSONB)chunk_task_id: Reference to async chunking taskembedding_task_id: Reference to async embedding taskSources: docs/development/database-schema.dbml354-395 packages/database/src/schemas/file.ts26-44
The frontend uses a unified ResourceItem interface for both files and documents:
Sources: src/types/resource.ts6-55 src/store/file/slices/resource/initialState.ts1-67
Files are accessed through public URLs configured via S3_PUBLIC_DOMAIN. This allows:
LobeChat uses Redis to cache presigned URLs and improve file access performance:
Redis configuration for LobeChat:
REDIS_URL=redis://redis:6379REDIS_PREFIX=lobechatREDIS_TLS=0 (disable TLS for internal network)Sources: docker-compose/local/docker-compose.yml38-53 docker-compose/local/docker-compose.yml160-162
LobeChat supports both S3 URL styles:
Path-Style (recommended for RustFS):
http://localhost:9000/lobe/object-key
Enable with: S3_ENABLE_PATH_STYLE=1
Virtual-Hosted Style:
https://bucket-name.s3.amazonaws.com/object-key
Sources: docker-compose/local/docker-compose.yml153
Diagram: RustFS Docker Compose Architecture
Sources: docker-compose/local/docker-compose.yml56-94
The RustFS service is configured with the following settings:
Key features:
/health endpoint for monitoringnetwork-service containerrustfs-data volumeSources: docker-compose/local/docker-compose.yml56-71
The rustfs-init service uses MinIO Client (mc) to initialize the bucket on startup:
This initialization script:
mc alias pointing to RustFSlobe bucket if it doesn't existbucket.config.jsonSources: docker-compose/local/docker-compose.yml73-94 docker-compose/local/bucket.config.json1-23
The bucket.config.json file defines the public access policy for the bucket:
This policy allows:
Sources: docker-compose/local/bucket.config.json1-23
LobeChat implements content-addressable storage using SHA-256 hashing:
Deduplication provides:
When a user deletes a file:
files table reference is deletedglobal_files entry remains (other users may reference it)global_files entriesSources: README.md406-414
After upload, files proceed through the RAG pipeline:
Files have processing status fields tracked through the ResourceItem interface:
chunkingStatus: Status of document chunkingchunkTaskId: Async task ID for chunkingchunkingError: Error details if chunking failedembeddingStatus: Status of embedding generationembeddingTaskId: Async task ID for embeddingembeddingError: Error details if embedding failedThe frontend polls for status updates during processing:
Sources: src/features/ResourceManager/components/Explorer/useCheckTaskStatus.ts1-29 src/types/resource.ts20-30
For AWS S3, configure:
For Cloudflare R2:
LobeChat's S3 integration is compatible with any S3-compatible storage provider:
Diagram: S3 Provider Options
Sources: docker-compose/local/.env.example35-43 docker-compose/local/docker-compose.yml56-71
The Docker Compose setup automatically creates the bucket on first run using MinIO Client (mc) in the rustfs-init service:
The initialization process:
mc to connect to RustFSlobe bucket (skips if exists)bucket.config.jsonSources: docker-compose/local/docker-compose.yml82-90
The bucket policy is defined in bucket.config.json and allows:
s3:GetBucketLocation - Read bucket locations3:ListBucket - List objects in buckets3:GetObject - Download objectss3:PutObject - Upload objectss3:DeleteObject - Delete objectsFor production deployments, restrict write operations to authenticated users only:
Sources: docker-compose/local/bucket.config.json1-23
The LobeChat container performs health checks on startup to verify S3 connectivity:
Sources: docker-compose/local/docker-compose.yml194-203
| Issue | Cause | Solution |
|---|---|---|
| Files not accessible | Wrong S3_PUBLIC_DOMAIN | Ensure matches reverse proxy config and RustFS endpoint |
| Upload fails | Bucket doesn't exist | Check rustfs-init service logs, verify bucket creation |
| 403 Forbidden | Incorrect access keys | Verify RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY match in all services |
| Connection refused | RustFS not started | Check RustFS health: docker logs lobe-rustfs |
| Redis connection failed | Redis not running | Verify Redis service: docker logs lobe-redis |
| Bucket policy not applied | rustfs-init failed | Check init logs: docker logs lobe-rustfs-init |
Sources: docker-compose/local/docker-compose.yml194-203 docker-compose/local/docker-compose.yml73-94
files table provides user-level access control.env file (not committed to git)Refresh this wiki