Connecting LobeChat with MinIO: A Simple Guide to Fixing S3 Path-Style Configuration
Content
## The Problem
When deploying the database version of LobeChat with Docker and integrating MinIO as the S3 storage, many users encounter an issue where files are uploaded successfully, but the generated access URL is incorrect. For instance, the expected URL is `https://s3.wiki.lib00.com/lobechat/filename.png`, but the application generates `https://lobechat.s3.wiki.lib00.com/filename.png`. This problem makes all uploaded files inaccessible.
The user's initial Docker run command looked like this:
```docker
docker run -it -d --name ee-lobe-chat-db-1.142.8 \
-p 3210:3210 \
-e S3_ACCESS_KEY_ID=xyxyxyx \
-e S3_SECRET_ACCESS_KEY=xyxyxyx \
-e S3_ENDPOINT=https://s3.lib00.com \
-e S3_BUCKET=lobechat \
-e S3_PUBLIC_DOMAIN=https://s3.lib00.com \
lobehub/lobe-chat-database:1.142.8
```
---
## Root Cause: Path-Style vs. Virtual-Hosted Style
The core of the issue lies in two different S3 URL addressing modes:
1. **Virtual-Hosted Style**: This is the default and recommended mode for AWS S3. It places the bucket name as part of the domain name. The format is `https://<bucket>.<endpoint>/<object>`. Example: `https://lobechat.s3.lib00.com/image.png`. This mode requires specific DNS configurations (like wildcard certificates and records), which can be complex in self-hosted environments.
2. **Path-Style**: This is the default and most common mode for S3-compatible storage solutions like MinIO and Ceph. It includes the bucket name as part of the URL path. The format is `https://<endpoint>/<bucket>/<object>`. Example: `https://s3.lib00.com/lobechat/image.png`.
The S3 client used internally by LobeChat defaults to the virtual-hosted style, which conflicts with how MinIO typically operates, leading to the incorrect URL generation.
---
## The Solution
To resolve this, we need to force LobeChat's S3 client to use Path-Style URLs. This can be achieved by adding a specific environment variable.
Based on community feedback and verification (credit to user DP@lib00), the correct environment variable is `S3_ENABLE_PATH_STYLE`.
Here is the corrected Docker run command:
```docker
docker run -it -d --name ee-lobe-chat-db-1.142.8 \
-p 3210:3210 \
-e S3_ACCESS_KEY_ID=xyxyxyx \
-e S3_SECRET_ACCESS_KEY=xyxyxyx \
-e S3_ENDPOINT=https://s3.wiki.lib00.com \
-e S3_BUCKET=wiki.lib00-bucket \
-e S3_ENABLE_PATH_STYLE=true \
-e S3_PUBLIC_DOMAIN=https://s3.wiki.lib00.com \
lobehub/lobe-chat-database:1.142.8
```
---
## Key Environment Variables Explained
1. **`-e S3_ENABLE_PATH_STYLE=true`**
* **Purpose**: This is the core of the solution. It explicitly tells the S3 client within LobeChat: "Please use path-style for all S3 URLs." After adding this, both upload and access URLs will follow the `https://<endpoint>/<bucket>/...` format.
* **Note**: In some other applications or older AWS SDKs, the variable `S3_FORCE_PATH_STYLE` might be used. However, for this version of LobeChat, `S3_ENABLE_PATH_STYLE` has been tested and confirmed as the correct choice.
2. **`-e S3_PUBLIC_DOMAIN=https://s3.wiki.lib00.com`**
* **Purpose**: This variable defines the base part of the public-facing domain for your files. LobeChat automatically appends the bucket name and filename to this URL to construct the final access link. The internal logic is: `Final URL = <S3_PUBLIC_DOMAIN>/<S3_BUCKET>/<filename>`.
* Therefore, you **should not** include the bucket name in this variable, as it would lead to a duplicated path, such as `.../lobechat/lobechat/filename.png`.
---
## Conclusion
By simply adding the `S3_ENABLE_PATH_STYLE=true` environment variable, we can easily switch LobeChat's S3 request mode from the default virtual-hosted style to path-style, ensuring perfect compatibility with self-hosted object storage services like MinIO. This small tweak is a crucial step for running LobeChat reliably on your own infrastructure. For more tech insights, follow wiki.lib00.com.
Related Contents
Ultimate Guide to Configuring Model Pricing in CLIProxyAPI: Ratios and Billing Explained
Duration: 00:00 | DP | 2026-07-13 20:23:25Complete Guide to Installing and Configuring Git Server on Synology NAS: Basic to Advanced
Duration: 00:00 | DP | 2026-07-16 20:39:02Why Do .smbdelete Hidden Files Appear After Deleting on Mac SMB Shares? Causes & Ultimate Solutions
Duration: 00:00 | DP | 2026-06-27 19:10:00Complete Guide to Setting Docker Container Timezone to UTC+8 (Asia/Shanghai)
Duration: 00:00 | DP | 2026-06-30 20:43:30Fixing 'Unable to locate package openjdk-17-jdk' in PHP 8 Docker (Debian Trixie)
Duration: 00:00 | DP | 2026-07-25 09:23:18Docker Compose Advanced: Configuring Static IPs and Cross-Container SOCKS5 Proxies
Duration: 00:00 | DP | 2026-07-26 09:28:30Nginx Reverse Proxy Guide: Elegantly Routing Specific Subdirectories to Docker Containers
Duration: 00:00 | DP | 2026-07-26 21:31:06DevOps Practice: How to Safely Clear Logs of a Running Docker Container?
Duration: 00:00 | DP | 2026-07-27 09:33:42Practical Guide: Translating Complex Docker Compose to Docker Run Commands
Duration: 00:00 | DP | 2026-07-29 09:44:07The Ultimate Guide to Docker Cron Logging: Host vs. Container Redirection - Are You Doing It Right?
Duration: 00:00 | DP | 2026-01-05 08:03:52Cron Job Failing? The Ultimate Guide to Fixing 'docker: command not found'
Duration: 00:00 | DP | 2026-08-01 09:59:44The Ultimate 'Connection Refused' Guide: A PHP PDO & Docker Debugging Saga of a Forgotten Port
Duration: 00:00 | DP | 2025-12-03 09:03:20Solving the MySQL Docker "Permission Denied" Error on Synology NAS: A Step-by-Step Guide
Duration: 00:00 | DP | 2025-12-03 21:19:10How Can a Docker Container Access the Mac Host? The Ultimate Guide to Connecting to Nginx
Duration: 00:00 | DP | 2025-12-08 23:57:30Docker Exec Mastery: The Right Way to Run Commands in Containers
Duration: 00:00 | DP | 2026-01-08 08:07:44How to Fix the "tsx: not found" Error During Vue Vite Builds in Docker
Duration: 00:00 | DP | 2026-01-10 08:10:19The Ultimate Guide to Docker Cron Jobs: Effortlessly Scheduling PHP Tasks in Containers from the Host
Duration: 00:00 | DP | 2025-12-29 10:30:50From Phantom Conflicts to Docker Permissions: A Deep Dive into Debugging an Infinite Loop in a Git Hook for an AI Assistant
Duration: 00:00 | DP | 2025-11-09 16:39:00Recommended
The Ultimate Guide to Using Google Fonts on Chinese Websites: Ditch the Lag with an Elegant Font Stack
00:00 | 1,273Struggling with slow loading times on your Chinese...
Mastering Bootstrap 5 Rounded Corners: The Ultimate Guide to Border-Radius
00:00 | 162Struggling with border-radius in Bootstrap 5? This...
The Ultimate Guide: Why Does PHP json_decode Fail with a "Control Character Error"?
00:00 | 135Frequently encountering the "Control character err...
The Ultimate Guide to GPL-3.0 for Web Projects: Commercial Use, Modification, and Source Code Obligations
00:00 | 27Found a GPL-3.0 licensed open-source web project a...