@lobehub/lobehub 2.0.13 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v2.json +18 -0
  3. package/docker-compose/deploy/.env.example +35 -0
  4. package/docker-compose/deploy/.env.zh-CN.example +31 -0
  5. package/docker-compose/deploy/bucket.config.json +18 -0
  6. package/docker-compose/deploy/docker-compose.yml +148 -0
  7. package/docker-compose/deploy/searxng-settings.yml +2582 -0
  8. package/docker-compose/setup.sh +37 -88
  9. package/docs/self-hosting/advanced/auth/providers/casdoor.mdx +110 -0
  10. package/docs/self-hosting/advanced/auth/providers/casdoor.zh-CN.mdx +165 -0
  11. package/docs/self-hosting/platform/docker-compose.mdx +43 -561
  12. package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +40 -537
  13. package/locales/en-US/setting.json +16 -0
  14. package/locales/zh-CN/setting.json +16 -0
  15. package/package.json +1 -1
  16. package/packages/const/src/url.ts +1 -1
  17. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/index.tsx +4 -2
  18. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobContentEditor.tsx +39 -44
  19. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobHeader.tsx +27 -20
  20. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +4 -2
  21. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +183 -145
  22. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/hooks/useAgentCronJobs.ts +3 -4
  23. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/index.tsx +4 -3
  24. package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +4 -3
  25. package/src/features/Conversation/Messages/AssistantGroup/components/MessageContent.tsx +6 -1
  26. package/src/locales/default/setting.ts +16 -0
  27. package/src/store/agent/slices/cron/action.ts +6 -4
@@ -263,10 +263,10 @@ show_message() {
263
263
  tips_allow_ports)
264
264
  case $LANGUAGE in
265
265
  zh_CN)
266
- echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001, 8000"
266
+ echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001"
267
267
  ;;
268
268
  *)
269
- echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001, 8000"
269
+ echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001"
270
270
  ;;
271
271
  esac
272
272
  ;;
@@ -315,12 +315,10 @@ show_message() {
315
315
  tips_init_database_failed)
316
316
  case $LANGUAGE in
317
317
  zh_CN)
318
- echo "无法初始化数据库,为了避免你的数据重复初始化,请在首次成功启动时运行以下指令清空 Casdoor 初始配置文件:"
319
- echo "echo '{}' > init_data.json"
318
+ echo "无法初始化数据库"
320
319
  ;;
321
320
  *)
322
- echo "Failed to initialize the database. To avoid your data being initialized repeatedly, run the following command to unmount the initial configuration file of Casdoor when you first start successfully:"
323
- echo "echo '{}' > init_data.json"
321
+ echo "Failed to initialize the database."
324
322
  ;;
325
323
  esac
326
324
  ;;
@@ -338,7 +336,7 @@ show_message() {
338
336
  case $LANGUAGE in
339
337
  zh_CN)
340
338
  echo "请选择部署模式:"
341
- echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS, Casdoor ,并分别分配一个域名;"
339
+ echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS,并分别分配一个域名;"
342
340
  echo "(1) 端口模式(访问时需要指明端口,如使用IP访问,或域名+端口访问),需要放开指定端口;"
343
341
  echo "(2) 本地模式(仅供本地测试使用)"
344
342
  echo "如果你对这些内容疑惑,可以先选择使用本地模式进行部署,稍后根据文档指引再进行修改。"
@@ -346,7 +344,7 @@ show_message() {
346
344
  ;;
347
345
  *)
348
346
  echo "Please select the deployment mode:"
349
- echo "(0) Domain mode (no need to specify the port when accessing), you need to use the reverse proxy service LobeHub, RustFS, Casdoor, and assign a domain name respectively;"
347
+ echo "(0) Domain mode (no need to specify the port when accessing), you need to use the reverse proxy service LobeHub, RustFS, and assign a domain name respectively;"
350
348
  echo "(1) Port mode (need to specify the port when accessing, such as using IP access, or domain name + port access), you need to open the specified port;"
351
349
  echo "(2) Local mode (for local testing only)"
352
350
  echo "If you are confused about these contents, you can choose to deploy in local mode first, and then modify according to the document guide later."
@@ -408,31 +406,33 @@ download_file() {
408
406
  }
409
407
 
410
408
  print_centered() {
411
- # Define colors
412
- declare -A colors
413
- colors=(
414
- [black]="\e[30m"
415
- [red]="\e[31m"
416
- [green]="\e[32m"
417
- [yellow]="\e[33m"
418
- [blue]="\e[34m"
419
- [magenta]="\e[35m"
420
- [cyan]="\e[36m"
421
- [white]="\e[37m"
422
- [reset]="\e[0m"
423
- )
424
409
  local text="$1" # Get input texts
425
410
  local color="${2:-reset}" # Get color, default to reset
426
411
  local term_width=$(tput cols) # Get terminal width
427
412
  local text_length=${#text} # Get text length
428
413
  local padding=$(((term_width - text_length) / 2)) # Get padding
429
- # Check if the color is valid
430
- if [[ -z "${colors[$color]}" ]]; then
431
- echo "Invalid color specified. Available colors: ${!colors[@]}"
432
- return 1
433
- fi
414
+
415
+ # Get color code (compatible with bash 3.x)
416
+ local color_code=""
417
+ local reset_code="\e[0m"
418
+ case "$color" in
419
+ black) color_code="\e[30m" ;;
420
+ red) color_code="\e[31m" ;;
421
+ green) color_code="\e[32m" ;;
422
+ yellow) color_code="\e[33m" ;;
423
+ blue) color_code="\e[34m" ;;
424
+ magenta) color_code="\e[35m" ;;
425
+ cyan) color_code="\e[36m" ;;
426
+ white) color_code="\e[37m" ;;
427
+ reset) color_code="\e[0m" ;;
428
+ *)
429
+ echo "Invalid color specified. Available colors: black red green yellow blue magenta cyan white reset"
430
+ return 1
431
+ ;;
432
+ esac
433
+
434
434
  # Print the text with padding
435
- printf "%*s${colors[$color]}%s${colors[reset]}\n" $padding "" "$text"
435
+ printf "%*s${color_code}%s${reset_code}\n" $padding "" "$text"
436
436
  }
437
437
 
438
438
  # Usage:
@@ -469,10 +469,9 @@ ask() {
469
469
  # == Variables ==
470
470
  # ===============
471
471
  # File list
472
- SUB_DIR="docker-compose/local"
472
+ SUB_DIR="docker-compose/deploy"
473
473
  FILES=(
474
474
  "$SUB_DIR/docker-compose.yml"
475
- "$SUB_DIR/init_data.json"
476
475
  "$SUB_DIR/searxng-settings.yml"
477
476
  "$SUB_DIR/bucket.config.json"
478
477
  )
@@ -481,10 +480,7 @@ ENV_EXAMPLES=(
481
480
  "$SUB_DIR/.env.example"
482
481
  )
483
482
  # Default values
484
- CASDOOR_PASSWORD="pswd123"
485
- CASDOOR_SECRET="CASDOOR_SECRET"
486
483
  RUSTFS_SECRET_KEY="YOUR_RUSTFS_PASSWORD"
487
- CASDOOR_HOST="localhost:8000"
488
484
  RUSTFS_HOST="localhost:9000"
489
485
  PROTOCOL="http"
490
486
 
@@ -514,9 +510,8 @@ section_download_files(){
514
510
  fi
515
511
 
516
512
  download_file "$SOURCE_URL/${FILES[0]}" "docker-compose.yml"
517
- download_file "$SOURCE_URL/${FILES[1]}" "init_data.json"
518
- download_file "$SOURCE_URL/${FILES[2]}" "searxng-settings.yml"
519
- download_file "$SOURCE_URL/${FILES[3]}" "bucket.config.json"
513
+ download_file "$SOURCE_URL/${FILES[1]}" "searxng-settings.yml"
514
+ download_file "$SOURCE_URL/${FILES[2]}" "bucket.config.json"
520
515
  # Download .env.example with the specified language
521
516
  if [ "$LANGUAGE" = "zh_CN" ]; then
522
517
  download_file "$SOURCE_URL/${ENV_EXAMPLES[0]}" ".env"
@@ -576,15 +571,10 @@ section_configurate_host() {
576
571
  echo "LobeHub" $(show_message "ask_domain" "example.com")
577
572
  ask "(example.com)"
578
573
  LOBE_HOST="$ask_result"
579
- # If user use domain mode, ask for the domain of RustFS and Casdoor
574
+ # If user use domain mode, ask for the domain of RustFS
580
575
  echo "RustFS S3 API" $(show_message "ask_domain" "s3.example.com")
581
576
  ask "(s3.example.com)"
582
577
  RUSTFS_HOST="$ask_result"
583
- echo "Casdoor API" $(show_message "ask_domain" "auth.example.com")
584
- ask "(auth.example.com)"
585
- CASDOOR_HOST="$ask_result"
586
- # Setup callback url for Casdoor
587
- sed "${SED_INPLACE_ARGS[@]}" "s/"example.com"/${LOBE_HOST}/" init_data.json
588
578
  ;;
589
579
  1)
590
580
  DEPLOY_MODE="ip"
@@ -595,21 +585,15 @@ section_configurate_host() {
595
585
  # If user use ip mode, append the port to the host
596
586
  LOBE_HOST="${HOST}:3210"
597
587
  RUSTFS_HOST="${HOST}:9000"
598
- CASDOOR_HOST="${HOST}:8000"
599
- # Setup callback url for Casdoor
600
- sed "${SED_INPLACE_ARGS[@]}" "s/"localhost:3210"/${LOBE_HOST}/" init_data.json
601
588
  ;;
602
589
  *)
603
590
  echo "Invalid deploy mode: $ask_result"
604
591
  exit 1
605
592
  ;;
606
593
  esac
607
-
594
+
608
595
  # lobe host
609
596
  sed "${SED_INPLACE_ARGS[@]}" "s#^APP_URL=.*#APP_URL=$PROTOCOL://$LOBE_HOST#" .env
610
- # auth related
611
- sed "${SED_INPLACE_ARGS[@]}" "s#^AUTH_CASDOOR_ISSUER=.*#AUTH_CASDOOR_ISSUER=$PROTOCOL://$CASDOOR_HOST#" .env
612
- sed "${SED_INPLACE_ARGS[@]}" "s#^origin=.*#origin=$PROTOCOL://$CASDOOR_HOST#" .env
613
597
  # s3 related
614
598
  sed "${SED_INPLACE_ARGS[@]}" "s#^S3_PUBLIC_DOMAIN=.*#S3_PUBLIC_DOMAIN=$PROTOCOL://$RUSTFS_HOST#" .env
615
599
  sed "${SED_INPLACE_ARGS[@]}" "s#^S3_ENDPOINT=.*#S3_ENDPOINT=$PROTOCOL://$RUSTFS_HOST#" .env
@@ -664,37 +648,7 @@ section_regenerate_secrets() {
664
648
  exit 1
665
649
  fi
666
650
  echo $(show_message "security_secrect_regenerate")
667
-
668
- # Generate CASDOOR_SECRET
669
- CASDOOR_SECRET=$(generate_key 32)
670
- if [ $? -ne 0 ]; then
671
- echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_SECRET"
672
- else
673
- # Search and replace the value of CASDOOR_SECRET in .env
674
- sed "${SED_INPLACE_ARGS[@]}" "s#^AUTH_CASDOOR_SECRET=.*#AUTH_CASDOOR_SECRET=${CASDOOR_SECRET}#" .env
675
- if [ $? -ne 0 ]; then
676
- echo $(show_message "security_secrect_regenerate_failed") "AUTH_CASDOOR_SECRET in \`.env\`"
677
- fi
678
- # replace `clientSecrect` in init_data.json
679
- sed "${SED_INPLACE_ARGS[@]}" "s#dbf205949d704de81b0b5b3603174e23fbecc354#${CASDOOR_SECRET}#" init_data.json
680
- if [ $? -ne 0 ]; then
681
- echo $(show_message "security_secrect_regenerate_failed") "AUTH_CASDOOR_SECRET in \`init_data.json\`"
682
- fi
683
- fi
684
-
685
- # Generate Casdoor User
686
- CASDOOR_USER="admin"
687
- CASDOOR_PASSWORD=$(generate_key 10)
688
- if [ $? -ne 0 ]; then
689
- echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_PASSWORD"
690
- CASDOOR_PASSWORD="pswd123"
691
- else
692
- # replace `password` in init_data.json
693
- sed "${SED_INPLACE_ARGS[@]}" "s/"pswd123"/${CASDOOR_PASSWORD}/" init_data.json
694
- if [ $? -ne 0 ]; then
695
- echo $(show_message "security_secrect_regenerate_failed") "CASDOOR_PASSWORD in \`init_data.json\`"
696
- fi
697
- fi
651
+
698
652
  # Generate RUSTFS S3 User Password
699
653
  RUSTFS_SECRET_KEY=$(generate_key 8)
700
654
  if [ $? -ne 0 ]; then
@@ -735,13 +689,10 @@ section_init_database() {
735
689
  fi
736
690
 
737
691
  docker compose pull
738
- docker compose up --detach postgresql casdoor
692
+ docker compose up --detach postgresql
739
693
  # hopefully enough time for even the slower systems
740
694
  sleep 15
741
695
  docker compose stop
742
-
743
- # Init finished, remove init mount
744
- echo '{}' > init_data.json
745
696
  }
746
697
 
747
698
  show_message "ask_init_database"
@@ -759,16 +710,14 @@ fi
759
710
  section_display_configurated_report() {
760
711
  # Display configuration reports
761
712
  echo $(show_message "security_secrect_regenerate_report")
762
-
763
- echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST \n - Username: user \n - Password: ${CASDOOR_PASSWORD} "
764
- echo -e "Casdoor: \n - URL: $PROTOCOL://$CASDOOR_HOST \n - Username: admin \n - Password: ${CASDOOR_PASSWORD}\n"
713
+
714
+ echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST"
765
715
  echo -e "RustFS: \n - URL: $PROTOCOL://$RUSTFS_HOST \n - Username: admin\n - Password: ${RUSTFS_SECRET_KEY}\n"
766
-
716
+
767
717
  # if user run in domain mode, diplay reverse proxy configuration
768
718
  if [[ "$DEPLOY_MODE" == "domain" ]]; then
769
719
  echo $(show_message "tips_add_reverse_proxy")
770
720
  printf "\n%s\t->\t%s\n" "$LOBE_HOST" "127.0.0.1:3210"
771
- printf "%s\t->\t%s\n" "$CASDOOR_HOST" "127.0.0.1:8000"
772
721
  printf "%s\t->\t%s\n" "$RUSTFS_HOST" "127.0.0.1:9000"
773
722
  fi
774
723
 
@@ -81,6 +81,116 @@ tags:
81
81
  After successful deployment, users will be able to authenticate with Casdoor and use LobeChat.
82
82
  </Callout>
83
83
 
84
+ ## Docker Compose Deployment with Casdoor
85
+
86
+ If you're deploying LobeHub using Docker Compose, refer to the following configuration to integrate Casdoor as an authentication service.
87
+
88
+ ### Reverse Proxy Configuration
89
+
90
+ In domain mode, you need to configure a reverse proxy to ensure Casdoor is accessible:
91
+
92
+ | Domain | Proxy Port | Description |
93
+ | ------------------ | ---------- | --------------- |
94
+ | `auth.example.com` | `8000` | Casdoor service |
95
+
96
+ <Callout type="important">
97
+ If you're using panel software like [aaPanel](https://www.bt.cn/) for reverse proxy configuration,
98
+ ensure it does not intercept requests to the `.well-known` path to facilitate the proper functioning of Casdoor's OAuth2 configuration.
99
+ Below is a whitelist configuration for the Nginx server block concerning paths for Casdoor reverse proxy:
100
+
101
+ ```nginx
102
+ location /.well-known/openid-configuration {
103
+ proxy_pass http://localhost:8000; # Forward to localhost:8000
104
+ proxy_set_header Host $host; # Keep the original host header
105
+ proxy_set_header X-Real-IP $remote_addr; # Keep the client's real IP
106
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Keep the forwarded IP
107
+ proxy_set_header X-Forwarded-Proto $scheme; # Keep the request protocol
108
+ }
109
+ ```
110
+
111
+ ⚠️ Please do not enable any form of caching in the reverse proxy settings of such panel software to avoid affecting the normal operation of the service.
112
+ See [https://github.com/lobehub/lobe-chat/discussions/5986](https://github.com/lobehub/lobe-chat/discussions/5986)
113
+ </Callout>
114
+
115
+ ### Required Configuration
116
+
117
+ 1. LobeHub needs to communicate with Casdoor, so you need to configure Casdoor's Issuer:
118
+
119
+ ```env
120
+ AUTH_CASDOOR_ISSUER=https://auth.example.com
121
+ ```
122
+
123
+ This configuration affects LobeHub's login authentication service. Ensure the Casdoor service URL is correct.
124
+
125
+ 2. Allow callback URL in Casdoor to point to LobeHub:
126
+
127
+ In Casdoor's Web panel under `Authentication -> Applications` -> `<Application ID, default is app-built-in>` -> `Redirect URLs`, add:
128
+
129
+ ```
130
+ https://lobe.example.com/api/auth/callback/casdoor
131
+ ```
132
+
133
+ 3. Casdoor needs Origin information in environment variables:
134
+
135
+ ```env
136
+ origin=https://auth.example.com
137
+ ```
138
+
139
+ ### Troubleshooting
140
+
141
+ #### Cannot Login Properly
142
+
143
+ Check container logs for the following errors:
144
+
145
+ ```sh
146
+ docker logs -f lobehub
147
+ ```
148
+
149
+ **r3: "response" is not a conform Authorization Server Metadata response**
150
+
151
+ ```log
152
+ lobehub | [auth][error] r3: "response" is not a conform Authorization Server Metadata response (unexpected HTTP status code)
153
+ ```
154
+
155
+ Cause: This issue is typically caused by improper reverse proxy configuration. Ensure your reverse proxy doesn't intercept Casdoor's OAuth2 configuration requests.
156
+
157
+ Solution:
158
+
159
+ - Refer to the reverse proxy configuration notes above.
160
+
161
+ - Direct troubleshooting: Access `https://auth.example.com/.well-known/openid-configuration`:
162
+ - If non-JSON data is returned, your reverse proxy configuration is incorrect.
163
+ - If the returned JSON's `"issuer": "URL"` field doesn't match `https://auth.example.com`, your environment variable configuration is incorrect.
164
+
165
+ **TypeError: fetch failed**
166
+
167
+ ```log
168
+ lobehub | [auth][error] TypeError: fetch failed
169
+ ```
170
+
171
+ Cause: LobeHub cannot access the authentication service.
172
+
173
+ Solution:
174
+
175
+ - Check if your authentication service is running properly and if LobeHub's network can reach it.
176
+
177
+ - Direct troubleshooting: Use `curl` in the LobeHub container terminal to access `https://auth.example.com/.well-known/openid-configuration`. If JSON data is returned, your authentication service is working correctly.
178
+
179
+ #### OAuth Token Exchange Failures with Reverse Proxy
180
+
181
+ If OAuth authentication fails during the token exchange phase when using Docker behind a reverse proxy, this is typically caused by the default `MIDDLEWARE_REWRITE_THROUGH_LOCAL=1` setting.
182
+
183
+ **Solution**: Set `MIDDLEWARE_REWRITE_THROUGH_LOCAL=0` in your `.env` file and restart Docker containers:
184
+
185
+ ```bash
186
+ docker compose down
187
+ docker compose up -d
188
+ ```
189
+
190
+ ### Docker Compose Configuration Files
191
+
192
+ Casdoor Docker Compose configuration files can be found in the [docker-compose/local/casdoor](https://github.com/lobehub/lobe-chat/tree/main/docker-compose/local/casdoor) directory.
193
+
84
194
  ## Related Resources
85
195
 
86
196
  - [Casdoor Documentation](https://casdoor.org/docs/overview)
@@ -77,6 +77,171 @@ tags:
77
77
 
78
78
  <Callout type={'info'}>部署成功后,用户将可以通过 Casdoor 身份认证并使用 LobeChat。</Callout>
79
79
 
80
+ ## Docker Compose 部署 Casdoor
81
+
82
+ 如果你使用 Docker Compose 部署 LobeHub,可以参考以下配置来集成 Casdoor 作为鉴权服务。
83
+
84
+ ### 反向代理配置
85
+
86
+ 在域名模式中,你需要完成反向代理配置,并确保局域网 / 公网能访问到 Casdoor 服务:
87
+
88
+ | 域名 | 反代端口 | 说明 |
89
+ | ------------------ | ------ | ---------- |
90
+ | `auth.example.com` | `8000` | Casdoor 服务 |
91
+
92
+ <Callout type="important">
93
+ 如果你使用如 [宝塔面板](https://www.bt.cn/) 等面板软件进行反向代理配置,
94
+ 你需要确保其对 `.well-known` 路径的请求不进行拦截,以确保 Casdoor 的 OAuth2 配置能够正常工作。
95
+ 这里提供一份针对 Casdoor 服务的 Nginx server 块的路径白名单配置:
96
+
97
+ ```nginx
98
+ location /.well-known/openid-configuration {
99
+ proxy_pass http://localhost:8000; # 转发到 localhost:8000
100
+ proxy_set_header Host $host; # 保留原始主机头
101
+ proxy_set_header X-Real-IP $remote_addr; # 保留客户端真实IP
102
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保留转发的IP
103
+ proxy_set_header X-Forwarded-Proto $scheme; # 保留请求协议
104
+ }
105
+ ```
106
+
107
+ ⚠️ 请不要在此类面板软件的反向代理设置中开启任何形式的缓存,以免影响服务的正常运行。
108
+ 详情请见 [https://github.com/lobehub/lobe-chat/discussions/5986](https://github.com/lobehub/lobe-chat/discussions/5986)
109
+ </Callout>
110
+
111
+ ### 必要配置
112
+
113
+ 1. LobeHub 需要与 Casdoor 通讯,因此你需要配置 Casdoor 的 Issuer:
114
+
115
+ ```env
116
+ AUTH_CASDOOR_ISSUER=https://auth.example.com
117
+ ```
118
+
119
+ 该配置会影响 LobeHub 的登录鉴权服务,你需要确保 Casdoor 服务的地址正确。
120
+
121
+ 2. 在 Casdoor 中允许回调地址为 LobeHub 的地址:
122
+
123
+ 请在 Casdoor 的 Web 面板的 `身份认证 -> 应用` -> `<应用ID,默认为 app-built-in>` -> `重定向URL` 中添加一行:
124
+
125
+ ```
126
+ https://lobe.example.com/api/auth/callback/casdoor
127
+ ```
128
+
129
+ 3. Casdoor 需要在环境变量中提供访问的 Origin 信息:
130
+
131
+ ```env
132
+ origin=https://auth.example.com
133
+ ```
134
+
135
+ ### 使用 MinIO 存储 Casdoor 头像
136
+
137
+ 允许用户在 Casdoor 中更换头像:
138
+
139
+ 1. 你需要首先在 `buckets` 中创建一个名为 `casdoor` 的桶,选择自定义策略,复制并粘贴如下内容:
140
+
141
+ ```json
142
+ {
143
+ "Statement": [
144
+ {
145
+ "Effect": "Allow",
146
+ "Principal": {
147
+ "AWS": ["*"]
148
+ },
149
+ "Action": ["s3:GetBucketLocation"],
150
+ "Resource": ["arn:aws:s3:::casdoor"]
151
+ },
152
+ {
153
+ "Effect": "Allow",
154
+ "Principal": {
155
+ "AWS": ["*"]
156
+ },
157
+ "Action": ["s3:ListBucket"],
158
+ "Resource": ["arn:aws:s3:::casdoor"],
159
+ "Condition": {
160
+ "StringEquals": {
161
+ "s3:prefix": ["files/*"]
162
+ }
163
+ }
164
+ },
165
+ {
166
+ "Effect": "Allow",
167
+ "Principal": {
168
+ "AWS": ["*"]
169
+ },
170
+ "Action": ["s3:PutObject", "s3:DeleteObject", "s3:GetObject"],
171
+ "Resource": ["arn:aws:s3:::casdoor/**"]
172
+ }
173
+ ],
174
+ "Version": "2012-10-17"
175
+ }
176
+ ```
177
+
178
+ 2. 创建一个新的访问密钥,将生成的 `Access Key` 和 `Secret Key` 存储之
179
+
180
+ 3. 在 Casdoor 的 `身份认证 -> 提供商` 中关联 MinIO S3 服务,以下是一个示例配置:
181
+
182
+ ![casdoor](/blog/assets18bb134dbc5792d6a624199cca8bf7d3.webp)
183
+
184
+ 其中,客户端 ID、客户端密钥为上一步创建的访问密钥中的 `Access Key` 和 `Secret Key`,`192.168.31.251` 应当被替换为 `your_server_ip`。
185
+
186
+ 4. 在 Casdoor 的 `身份认证 -> 应用` 中,对 `app-built-in` 应用添加提供商,选择 `minio`,保存并退出
187
+
188
+ 5. 你可以在 Casdoor 的 `身份认证 -> 资源` 中,尝试上传文件以测试配置是否正确
189
+
190
+ ### 常见问题
191
+
192
+ #### 无法正常登陆
193
+
194
+ 请根据容器日志检查是否存在以下错误:
195
+
196
+ ```sh
197
+ docker logs -f lobe-chat
198
+ ```
199
+
200
+ **r3: "response" is not a conform Authorization Server Metadata response**
201
+
202
+ ```log
203
+ lobe-chat | [auth][error] r3: "response" is not a conform Authorization Server Metadata response (unexpected HTTP status code)
204
+ ```
205
+
206
+ 成因:该问题一般是由于你的反向代理配置不正确导致的,你需要确保你的反向代理配置不会拦截 Casdoor 的 OAuth2 配置请求。
207
+
208
+ 解决方案:
209
+
210
+ - 请参考上方的反向代理配置注意事项。
211
+
212
+ - 一个直接的排查方式,你可以直接访问 `https://auth.example.com/.well-known/openid-configuration`,如果:
213
+ - 返回了非 JSON 格式的数据,则说明你的反向代理配置错误。
214
+ - 如果返回的 JSON 格式数据中的 `"issuer": "URL"` 字段不是你配置的 `https://auth.example.com`,则说明你的环境变量配置错误。
215
+
216
+ **TypeError: fetch failed**
217
+
218
+ ```log
219
+ lobe-chat | [auth][error] TypeError: fetch failed
220
+ ```
221
+
222
+ 成因:LobeHub 无法访问鉴权服务。
223
+
224
+ 解决方案:
225
+
226
+ - 请检查你的鉴权服务是否正常运行,以及 LobeHub 所在的网络是否能够访问到鉴权服务。
227
+
228
+ - 一个直接的排查方式,你可以在 LobeHub 容器的终端中,使用 `curl` 命令访问你的鉴权服务 `https://auth.example.com/.well-known/openid-configuration`,如果返回了 JSON 格式的数据,则说明你的鉴权服务正常运行。
229
+
230
+ #### 反向代理下 OAuth 令牌交换失败
231
+
232
+ 如果在反向代理后使用 Docker 时 OAuth 认证在令牌交换阶段失败,这通常是由默认的 `MIDDLEWARE_REWRITE_THROUGH_LOCAL=1` 设置引起的,该设置会将 URL 重写为 `127.0.0.1:3210`。
233
+
234
+ **解决方案**: 在 `.env` 文件中设置 `MIDDLEWARE_REWRITE_THROUGH_LOCAL=0` 并重启 Docker 容器:
235
+
236
+ ```bash
237
+ docker compose down
238
+ docker compose up -d
239
+ ```
240
+
241
+ ### Docker Compose 配置文件
242
+
243
+ Casdoor 的 Docker Compose 配置文件可以在 [docker-compose/local/casdoor](https://github.com/lobehub/lobe-chat/tree/main/docker-compose/local/casdoor) 目录中找到。
244
+
80
245
  ## 相关资源
81
246
 
82
247
  - [Casdoor 文档](https://casdoor.org/docs/overview)