@lobehub/chat 1.20.3 → 1.20.5

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 (26) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/Dockerfile +37 -49
  3. package/Dockerfile.database +37 -53
  4. package/docker-compose/local/zitadel/.env.example +33 -0
  5. package/docker-compose/local/zitadel/.env.zh-CN.example +32 -0
  6. package/docker-compose/local/zitadel/docker-compose.yml +86 -0
  7. package/docker-compose/local/zitadel/zitadel-config.yaml +26 -0
  8. package/docker-compose/local/zitadel/zitadel-init-steps.yaml +11 -0
  9. package/docker-compose/production/zitadel/.env.example +53 -0
  10. package/docker-compose/production/zitadel/.env.zh-CN.example +48 -0
  11. package/docker-compose/production/zitadel/docker-compose.yml +69 -0
  12. package/docker-compose/production/zitadel/zitadel-config.yaml +25 -0
  13. package/docker-compose/production/zitadel/zitadel-init-steps.yaml +11 -0
  14. package/docs/self-hosting/server-database/docker-compose.mdx +9 -9
  15. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +9 -9
  16. package/package.json +2 -2
  17. package/scripts/serverLauncher/startServer.js +181 -0
  18. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/index.tsx +7 -1
  19. package/src/app/(main)/chat/(workspace)/_layout/Desktop/Portal.tsx +0 -2
  20. package/src/app/(main)/chat/(workspace)/_layout/Desktop/TopicPanel.tsx +0 -2
  21. package/src/app/(main)/chat/@session/features/SessionListContent/Modals/ConfigGroupModal/index.tsx +1 -2
  22. package/src/components/DragUpload/index.tsx +0 -1
  23. package/src/components/FunctionModal/style.tsx +0 -1
  24. package/src/components/GuideModal/index.tsx +0 -1
  25. package/src/features/Conversation/components/VirtualizedList/index.tsx +2 -7
  26. package/src/layout/AuthProvider/Clerk/useAppearance.ts +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.20.5](https://github.com/lobehub/lobe-chat/compare/v1.20.4...v1.20.5)
6
+
7
+ <sup>Released on **2024-09-29**</sup>
8
+
9
+ <br/>
10
+
11
+ <details>
12
+ <summary><kbd>Improvements and Fixes</kbd></summary>
13
+
14
+ </details>
15
+
16
+ <div align="right">
17
+
18
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
19
+
20
+ </div>
21
+
22
+ ### [Version 1.20.4](https://github.com/lobehub/lobe-chat/compare/v1.20.3...v1.20.4)
23
+
24
+ <sup>Released on **2024-09-28**</sup>
25
+
26
+ <br/>
27
+
28
+ <details>
29
+ <summary><kbd>Improvements and Fixes</kbd></summary>
30
+
31
+ </details>
32
+
33
+ <div align="right">
34
+
35
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
36
+
37
+ </div>
38
+
5
39
  ### [Version 1.20.3](https://github.com/lobehub/lobe-chat/compare/v1.20.2...v1.20.3)
6
40
 
7
41
  <sup>Released on **2024-09-28**</sup>
package/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- ## Base image for all the stages
1
+ ## Base image for all building stages
2
2
  FROM node:20-slim AS base
3
3
 
4
4
  ARG USE_CN_MIRROR
@@ -10,19 +10,22 @@ RUN \
10
10
  if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
11
11
  sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
12
12
  fi \
13
- # Add required package & update base package
13
+ # Add required package
14
14
  && apt update \
15
- && apt install busybox proxychains-ng -qy \
16
- && apt full-upgrade -qy \
17
- && apt autoremove -qy --purge \
18
- && apt clean -qy \
19
- # Configure BusyBox
20
- && busybox --install -s \
21
- # Add nextjs:nodejs to run the app
22
- && addgroup --system --gid 1001 nodejs \
23
- && adduser --system --home "/app" --gid 1001 -uid 1001 nextjs \
24
- # Set permission for nextjs:nodejs
25
- && chown -R nextjs:nodejs "/etc/proxychains4.conf" \
15
+ && apt install ca-certificates proxychains-ng -qy \
16
+ # Prepare required package to distroless
17
+ && mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib \
18
+ # Copy proxychains to distroless
19
+ && cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 \
20
+ && cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 \
21
+ && cp /usr/bin/proxychains4 /distroless/bin/proxychains \
22
+ && cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf \
23
+ # Copy node to distroless
24
+ && cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 \
25
+ && cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 \
26
+ && cp /usr/local/bin/node /distroless/bin/node \
27
+ # Copy CA certificates to distroless
28
+ && cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt \
26
29
  # Cleanup temp files
27
30
  && rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
28
31
 
@@ -61,6 +64,7 @@ RUN \
61
64
  if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
62
65
  export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"; \
63
66
  npm config set registry "https://registry.npmmirror.com/"; \
67
+ echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \
64
68
  fi \
65
69
  # Set the registry for corepack
66
70
  && export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//') \
@@ -80,7 +84,9 @@ COPY . .
80
84
  RUN npm run build:docker
81
85
 
82
86
  ## Application image, copy all the files for production
83
- FROM scratch AS app
87
+ FROM busybox:latest AS app
88
+
89
+ COPY --from=base /distroless/ /
84
90
 
85
91
  COPY --from=builder /app/public /app/public
86
92
 
@@ -90,13 +96,25 @@ COPY --from=builder /app/.next/standalone /app/
90
96
  COPY --from=builder /app/.next/static /app/.next/static
91
97
  COPY --from=builder /deps/node_modules/.pnpm /app/node_modules/.pnpm
92
98
 
99
+ # Copy server launcher
100
+ COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js
101
+
102
+ RUN \
103
+ # Add nextjs:nodejs to run the app
104
+ addgroup -S -g 1001 nodejs \
105
+ && adduser -D -G nodejs -H -S -h /app -u 1001 nextjs \
106
+ # Set permission for nextjs:nodejs
107
+ && chown -R nextjs:nodejs /app /etc/proxychains4.conf
108
+
93
109
  ## Production image, copy all the files and run next
94
- FROM base
110
+ FROM scratch
95
111
 
96
112
  # Copy all the files from app, set the correct permission for prerender cache
97
- COPY --from=app --chown=nextjs:nodejs /app /app
113
+ COPY --from=app / /
98
114
 
99
115
  ENV NODE_ENV="production" \
116
+ NODE_OPTIONS="--use-openssl-ca" \
117
+ NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt" \
100
118
  NODE_TLS_REJECT_UNAUTHORIZED=""
101
119
 
102
120
  # set hostname to localhost
@@ -176,36 +194,6 @@ USER nextjs
176
194
 
177
195
  EXPOSE 3210/tcp
178
196
 
179
- CMD \
180
- if [ -n "$PROXY_URL" ]; then \
181
- # Set regex for IPv4
182
- IP_REGEX="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$"; \
183
- # Set proxychains command
184
- PROXYCHAINS="proxychains -q"; \
185
- # Parse the proxy URL
186
- host_with_port="${PROXY_URL#*//}"; \
187
- host="${host_with_port%%:*}"; \
188
- port="${PROXY_URL##*:}"; \
189
- protocol="${PROXY_URL%%://*}"; \
190
- # Resolve to IP address if the host is a domain
191
- if ! [[ "$host" =~ "$IP_REGEX" ]]; then \
192
- nslookup=$(nslookup -q="A" "$host" | tail -n +3 | grep 'Address:'); \
193
- if [ -n "$nslookup" ]; then \
194
- host=$(echo "$nslookup" | tail -n 1 | awk '{print $2}'); \
195
- fi; \
196
- fi; \
197
- # Generate proxychains configuration file
198
- printf "%s\n" \
199
- 'localnet 127.0.0.0/255.0.0.0' \
200
- 'localnet ::1/128' \
201
- 'proxy_dns' \
202
- 'remote_dns_subnet 224' \
203
- 'strict_chain' \
204
- 'tcp_connect_time_out 8000' \
205
- 'tcp_read_time_out 15000' \
206
- '[ProxyList]' \
207
- "$protocol $host $port" \
208
- > "/etc/proxychains4.conf"; \
209
- fi; \
210
- # Run the server
211
- ${PROXYCHAINS} node "/app/server.js";
197
+ ENTRYPOINT ["/bin/node"]
198
+
199
+ CMD ["/app/startServer.js"]
@@ -1,4 +1,4 @@
1
- ## Base image for all the stages
1
+ ## Base image for all building stages
2
2
  FROM node:20-slim AS base
3
3
 
4
4
  ARG USE_CN_MIRROR
@@ -10,19 +10,22 @@ RUN \
10
10
  if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
11
11
  sed -i "s/deb.debian.org/mirrors.ustc.edu.cn/g" "/etc/apt/sources.list.d/debian.sources"; \
12
12
  fi \
13
- # Add required package & update base package
13
+ # Add required package
14
14
  && apt update \
15
- && apt install busybox proxychains-ng -qy \
16
- && apt full-upgrade -qy \
17
- && apt autoremove -qy --purge \
18
- && apt clean -qy \
19
- # Configure BusyBox
20
- && busybox --install -s \
21
- # Add nextjs:nodejs to run the app
22
- && addgroup --system --gid 1001 nodejs \
23
- && adduser --system --home "/app" --gid 1001 -uid 1001 nextjs \
24
- # Set permission for nextjs:nodejs
25
- && chown -R nextjs:nodejs "/etc/proxychains4.conf" \
15
+ && apt install ca-certificates proxychains-ng -qy \
16
+ # Prepare required package to distroless
17
+ && mkdir -p /distroless/bin /distroless/etc /distroless/etc/ssl/certs /distroless/lib \
18
+ # Copy proxychains to distroless
19
+ && cp /usr/lib/$(arch)-linux-gnu/libproxychains.so.4 /distroless/lib/libproxychains.so.4 \
20
+ && cp /usr/lib/$(arch)-linux-gnu/libdl.so.2 /distroless/lib/libdl.so.2 \
21
+ && cp /usr/bin/proxychains4 /distroless/bin/proxychains \
22
+ && cp /etc/proxychains4.conf /distroless/etc/proxychains4.conf \
23
+ # Copy node to distroless
24
+ && cp /usr/lib/$(arch)-linux-gnu/libstdc++.so.6 /distroless/lib/libstdc++.so.6 \
25
+ && cp /usr/lib/$(arch)-linux-gnu/libgcc_s.so.1 /distroless/lib/libgcc_s.so.1 \
26
+ && cp /usr/local/bin/node /distroless/bin/node \
27
+ # Copy CA certificates to distroless
28
+ && cp /etc/ssl/certs/ca-certificates.crt /distroless/etc/ssl/certs/ca-certificates.crt \
26
29
  # Cleanup temp files
27
30
  && rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/*
28
31
 
@@ -65,6 +68,7 @@ RUN \
65
68
  if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
66
69
  export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"; \
67
70
  npm config set registry "https://registry.npmmirror.com/"; \
71
+ echo 'canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas' >> .npmrc; \
68
72
  fi \
69
73
  # Set the registry for corepack
70
74
  && export COREPACK_NPM_REGISTRY=$(npm config get registry | sed 's/\/$//') \
@@ -84,7 +88,9 @@ COPY . .
84
88
  RUN npm run build:docker
85
89
 
86
90
  ## Application image, copy all the files for production
87
- FROM scratch AS app
91
+ FROM busybox:latest AS app
92
+
93
+ COPY --from=base /distroless/ /
88
94
 
89
95
  COPY --from=builder /app/public /app/public
90
96
 
@@ -103,13 +109,25 @@ COPY --from=builder /app/src/database/server/migrations /app/migrations
103
109
  COPY --from=builder /app/scripts/migrateServerDB/docker.cjs /app/docker.cjs
104
110
  COPY --from=builder /app/scripts/migrateServerDB/errorHint.js /app/errorHint.js
105
111
 
112
+ # Copy server launcher
113
+ COPY --from=builder /app/scripts/serverLauncher/startServer.js /app/startServer.js
114
+
115
+ RUN \
116
+ # Add nextjs:nodejs to run the app
117
+ addgroup -S -g 1001 nodejs \
118
+ && adduser -D -G nodejs -H -S -h /app -u 1001 nextjs \
119
+ # Set permission for nextjs:nodejs
120
+ && chown -R nextjs:nodejs /app /etc/proxychains4.conf
121
+
106
122
  ## Production image, copy all the files and run next
107
- FROM base
123
+ FROM scratch
108
124
 
109
125
  # Copy all the files from app, set the correct permission for prerender cache
110
- COPY --from=app --chown=nextjs:nodejs /app /app
126
+ COPY --from=app / /
111
127
 
112
128
  ENV NODE_ENV="production" \
129
+ NODE_OPTIONS="--use-openssl-ca" \
130
+ NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt" \
113
131
  NODE_TLS_REJECT_UNAUTHORIZED=""
114
132
 
115
133
  # set hostname to localhost
@@ -208,40 +226,6 @@ USER nextjs
208
226
 
209
227
  EXPOSE 3210/tcp
210
228
 
211
- CMD \
212
- if [ -n "$PROXY_URL" ]; then \
213
- # Set regex for IPv4
214
- IP_REGEX="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$"; \
215
- # Set proxychains command
216
- PROXYCHAINS="proxychains -q"; \
217
- # Parse the proxy URL
218
- host_with_port="${PROXY_URL#*//}"; \
219
- host="${host_with_port%%:*}"; \
220
- port="${PROXY_URL##*:}"; \
221
- protocol="${PROXY_URL%%://*}"; \
222
- # Resolve to IP address if the host is a domain
223
- if ! [[ "$host" =~ "$IP_REGEX" ]]; then \
224
- nslookup=$(nslookup -q="A" "$host" | tail -n +3 | grep 'Address:'); \
225
- if [ -n "$nslookup" ]; then \
226
- host=$(echo "$nslookup" | tail -n 1 | awk '{print $2}'); \
227
- fi; \
228
- fi; \
229
- # Generate proxychains configuration file
230
- printf "%s\n" \
231
- 'localnet 127.0.0.0/255.0.0.0' \
232
- 'localnet ::1/128' \
233
- 'proxy_dns' \
234
- 'remote_dns_subnet 224' \
235
- 'strict_chain' \
236
- 'tcp_connect_time_out 8000' \
237
- 'tcp_read_time_out 15000' \
238
- '[ProxyList]' \
239
- "$protocol $host $port" \
240
- > "/etc/proxychains4.conf"; \
241
- fi; \
242
- # Run migration
243
- node "/app/docker.cjs"; \
244
- if [ "$?" -eq "0" ]; then \
245
- # Run the server
246
- ${PROXYCHAINS} node "/app/server.js"; \
247
- fi;
229
+ ENTRYPOINT ["/bin/node"]
230
+
231
+ CMD ["/app/startServer.js"]
@@ -0,0 +1,33 @@
1
+ # Required: LobeChat domain for tRPC calls
2
+ # Ensure this domain is whitelisted in your NextAuth providers and S3 service CORS settings
3
+ APP_URL=http://localhost:3210
4
+
5
+ # Postgres related environment variables
6
+ # Required: Secret key for encrypting sensitive information. Generate with: openssl rand -base64 32
7
+ KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
8
+ # Required: Postgres database connection string
9
+ DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobechat
10
+
11
+ # NEXT_AUTH related environment variables
12
+ NEXTAUTH_URL=http://localhost:3210/api/auth
13
+ NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
14
+ NEXT_AUTH_SSO_PROVIDERS=zitadel
15
+ # ZiTADEL provider configuration
16
+ # Please refer to:https://lobehub.com/zh/docs/self-hosting/advanced/auth/next-auth/zitadel
17
+ AUTH_ZITADEL_ID=285945938244075523
18
+ AUTH_ZITADEL_SECRET=hkbtzHLaCEIeHeFThym14UcydpmQiEB5JtAX08HSqSoJxhAlVVkyovTuNUZ5TNrT
19
+ AUTH_ZITADEL_ISSUER=http://localhost:8080
20
+
21
+ # MinIO S3 configuration
22
+ S3_ACCESS_KEY_ID=
23
+ S3_SECRET_ACCESS_KEY=
24
+ S3_ENDPOINT=http://localhost:9000
25
+ S3_BUCKET=lobe
26
+ S3_PUBLIC_DOMAIN=http://localhost:9000
27
+ S3_ENABLE_PATH_STYLE=1
28
+ LLM_VISION_IMAGE_USE_BASE64=1
29
+
30
+ # Other environment variables, as needed. You can refer to the environment variables configuration for the client version, making sure not to have ACCESS_CODE.
31
+ # OPENAI_API_KEY=sk-xxxx
32
+ # OPENAI_PROXY_URL=https://api.openai.com/v1
33
+ # OPENAI_MODEL_LIST=...
@@ -0,0 +1,32 @@
1
+ # LobeChat 域名
2
+ APP_URL=http://localhost:3210
3
+
4
+ # Postgres 相关,也即 DB 必须的环境变量
5
+ # 用于加密敏感信息的密钥,可以使用 openssl rand -base64 32 生成
6
+ KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
7
+ # Postgres 数据库连接字符串
8
+ DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobechat
9
+
10
+ # NEXT_AUTH 相关
11
+ NEXTAUTH_URL=http://localhost:3210/api/auth
12
+ NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
13
+ NEXT_AUTH_SSO_PROVIDERS=zitadel
14
+ # ZiTADEL 鉴权服务提供商部分
15
+ # 请参考:https://lobehub.com/zh/docs/self-hosting/advanced/auth/next-auth/zitadel
16
+ AUTH_ZITADEL_ID=285945938244075523
17
+ AUTH_ZITADEL_SECRET=hkbtzHLaCEIeHeFThym14UcydpmQiEB5JtAX08HSqSoJxhAlVVkyovTuNUZ5TNrT
18
+ AUTH_ZITADEL_ISSUER=http://localhost:8080
19
+
20
+ # MinIO S3 配置
21
+ S3_ACCESS_KEY_ID=
22
+ S3_SECRET_ACCESS_KEY=
23
+ S3_ENDPOINT=http://localhost:9000
24
+ S3_BUCKET=lobe
25
+ S3_PUBLIC_DOMAIN=http://localhost:9000
26
+ S3_ENABLE_PATH_STYLE=1
27
+ LLM_VISION_IMAGE_USE_BASE64=1
28
+
29
+ # 其他环境变量,视需求而定,可以参照客户端版本的环境变量配置,注意不要有 ACCESS_CODE
30
+ # OPENAI_API_KEY=sk-xxxx
31
+ # OPENAI_PROXY_URL=https://api.openai.com/v1
32
+ # OPENAI_MODEL_LIST=...
@@ -0,0 +1,86 @@
1
+ services:
2
+ network-service:
3
+ image: alpine
4
+ container_name: lobe-network
5
+ ports:
6
+ - '9000:9000' # MinIO API
7
+ - '9001:9001' # MinIO Console
8
+ - '8080:8080' # Zitadel Console
9
+ - '3210:3210' # LobeChat
10
+ command: tail -f /dev/null
11
+ networks:
12
+ - lobe-network
13
+
14
+ postgresql:
15
+ image: pgvector/pgvector:pg16
16
+ container_name: lobe-postgres
17
+ ports:
18
+ - "5432:5432"
19
+ volumes:
20
+ - './data:/var/lib/postgresql/data'
21
+ environment:
22
+ - 'POSTGRES_DB=lobechat'
23
+ - 'POSTGRES_PASSWORD=uWNZugjBqixf8dxC'
24
+ healthcheck:
25
+ test: ['CMD-SHELL', 'pg_isready -U postgres']
26
+ interval: 5s
27
+ timeout: 5s
28
+ retries: 5
29
+ restart: always
30
+ networks:
31
+ - lobe-network
32
+
33
+ minio:
34
+ image: minio/minio
35
+ container_name: lobe-minio
36
+ network_mode: 'service:network-service'
37
+ volumes:
38
+ - './s3_data:/etc/minio/data'
39
+ environment:
40
+ - 'MINIO_ROOT_USER=YOUR_MINIO_USER'
41
+ - 'MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD'
42
+ - 'MINIO_API_CORS_ALLOW_ORIGIN=http://localhost:3210'
43
+ restart: always
44
+ command: >
45
+ server /etc/minio/data --address ":9000" --console-address ":9001"
46
+
47
+ zitadel:
48
+ restart: 'always'
49
+ image: 'ghcr.io/zitadel/zitadel:latest'
50
+ container_name: lobe-zitadel
51
+ network_mode: 'service:network-service'
52
+ command: start-from-init --config /zitadel-config.yaml --steps
53
+ /zitadel-init-steps.yaml --masterkey "cft3Tekr/rQBOqwoQSCPoncA9BHbn7QJ"
54
+ --tlsMode disabled #MasterkeyNeedsToHave32Characters
55
+ volumes:
56
+ - ./zitadel-config.yaml:/zitadel-config.yaml:ro
57
+ - ./zitadel-init-steps.yaml:/zitadel-init-steps.yaml:ro
58
+ depends_on:
59
+ postgresql:
60
+ condition: service_healthy
61
+
62
+ lobe:
63
+ image: lobehub/lobe-chat-database
64
+ container_name: lobe-database
65
+ network_mode: 'service:network-service'
66
+ depends_on:
67
+ postgresql:
68
+ condition: service_healthy
69
+ network-service:
70
+ condition: service_started
71
+ minio:
72
+ condition: service_started
73
+ zitadel:
74
+ condition: service_started
75
+ env_file:
76
+ - .env
77
+ restart: always
78
+
79
+ volumes:
80
+ data:
81
+ driver: local
82
+ s3_data:
83
+ driver: local
84
+ networks:
85
+ lobe-network:
86
+ driver: bridge
@@ -0,0 +1,26 @@
1
+ Log:
2
+ Level: 'info'
3
+
4
+ Port: 8080
5
+ ExternalPort: 8080
6
+ ExternalDomain: localhost
7
+ ExternalSecure: false
8
+ TLS:
9
+ Enabled: false
10
+
11
+ # If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
12
+ Database:
13
+ postgres:
14
+ Host: postgresql
15
+ Port: 5432
16
+ Database: zitadel
17
+ User:
18
+ Username: 'zitadel'
19
+ Password: 'zitadel'
20
+ SSL:
21
+ Mode: 'disable'
22
+ Admin:
23
+ Username: 'postgres'
24
+ Password: 'uWNZugjBqixf8dxC' #postgres password
25
+ SSL:
26
+ Mode: 'disable'
@@ -0,0 +1,11 @@
1
+ # All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
2
+ FirstInstance:
3
+ Org:
4
+ Human:
5
+ # use the loginname root@zitadel.localhost
6
+ Username: 'root'
7
+ # The password must be 8 characters or more and must contain uppercase letters, lowercase letters, symbols, and numbers. The first login will require a password change.
8
+ Password: 'Password1!'
9
+ Email:
10
+ # Optional, if set, can be used to log in with email.
11
+ Address: 'example@zitadel.com' # ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS
@@ -0,0 +1,53 @@
1
+ # Required: LobeChat domain for tRPC calls
2
+ # Ensure this domain is whitelisted in your NextAuth providers and S3 service CORS settings
3
+ APP_URL=https://lobe.example.com/
4
+
5
+ # Postgres related environment variables
6
+ # Required: Secret key for encrypting sensitive information. Generate with: openssl rand -base64 32
7
+ KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
8
+ # Required: Postgres database connection string
9
+ # Format: postgresql://username:password@host:port/dbname
10
+ # If using Docker, you can use the container name as the host
11
+ DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobe
12
+
13
+ # NEXT_AUTH related environment variables
14
+ # Required: NextAuth URL for callbacks
15
+ NEXTAUTH_URL=https://lobe.example.com/api/auth
16
+ # Required: NextAuth secret key. Generate with: openssl rand -base64 32
17
+ NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
18
+ # Required: Specify the authentication provider
19
+ NEXT_AUTH_SSO_PROVIDERS=zitadel
20
+
21
+ # ZiTADEL provider configuration
22
+ # Please refer to:https://lobehub.com/zh/docs/self-hosting/advanced/auth/next-auth/zitadel
23
+ AUTH_ZITADEL_ID=285934220675723622
24
+ AUTH_ZITADEL_SECRET=pe7Nh3lopXkZkfqh5YEDYI2xsbIz08eZKqInOUZxssd3refRia518Apbv3DZ
25
+ AUTH_ZITADEL_ISSUER=https://zitadel.example.com
26
+
27
+ # Proxy settings (if needed, e.g., when using GitHub as an auth provider)
28
+ # HTTP_PROXY=http://localhost:7890
29
+ # HTTPS_PROXY=http://localhost:7890
30
+
31
+ # S3 related environment variables (example using MinIO)
32
+ # Required: S3 Access Key ID (for MinIO, invalid until manually created in MinIO UI)
33
+ S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
34
+ # Required: S3 Secret Access Key (for MinIO, invalid until manually created in MinIO UI)
35
+ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
36
+ # Required: S3 Endpoint for server/client connections to S3 API
37
+ S3_ENDPOINT=https://lobe-s3-api.example.com
38
+ # Required: S3 Bucket (invalid until manually created in MinIO UI)
39
+ S3_BUCKET=lobe
40
+ # Required: S3 Public Domain for client access to unstructured data
41
+ S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
42
+ # Optional: S3 Enable Path Style
43
+ # Use 0 for mainstream S3 cloud providers; use 1 for self-hosted MinIO
44
+ # See: https://lobehub.com/docs/self-hosting/advanced/s3#s-3-enable-path-style
45
+ S3_ENABLE_PATH_STYLE=1
46
+
47
+ # Other basic environment variables (as needed)
48
+ # See: https://lobehub.com/docs/self-hosting/environment-variables/basic
49
+ # Note: For server versions, the API must support embedding models (OpenAI text-embedding-3-small) for file processing
50
+ # You don't need to specify this model in OPENAI_MODEL_LIST
51
+ # OPENAI_API_KEY=sk-xxxx
52
+ # OPENAI_PROXY_URL=https://api.openai.com/v1
53
+ # OPENAI_MODEL_LIST=...
@@ -0,0 +1,48 @@
1
+ # 必填,LobeChat 域名,用于 tRPC 调用
2
+ # 请保证此域名在你的 NextAuth 鉴权服务提供商、S3 服务商的 CORS 白名单中
3
+ APP_URL=https://lobe.example.com/
4
+
5
+ # Postgres 相关,也即 DB 必需的环境变量
6
+ # 必填,用于加密敏感信息的密钥,可以使用 openssl rand -base64 32 生成
7
+ KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
8
+ # 必填,Postgres 数据库连接字符串,用于连接到数据库
9
+ # 格式:postgresql://username:password@host:port/dbname,如果你的 pg 实例为 Docker 容器且位于同一 docker-compose 文件中,亦可使用容器名作为 host
10
+ DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobe
11
+
12
+ # NEXT_AUTH 相关,也即鉴权服务必需的环境变量
13
+ # 必填,NextAuth 的 URL,用于 NextAuth 的回调
14
+ NEXTAUTH_URL=https://lobe.example.com/api/auth
15
+ # 必填,用于 NextAuth 的密钥,可以使用 openssl rand -base64 32 生成
16
+ NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
17
+ # 必填,指定鉴权服务提供商
18
+ NEXT_AUTH_SSO_PROVIDERS=zitadel
19
+
20
+ # ZiTADEL 鉴权服务提供商部分
21
+ # 请参考:https://lobehub.com/zh/docs/self-hosting/advanced/auth/next-auth/zitadel
22
+ AUTH_ZITADEL_ID=285934220675723622
23
+ AUTH_ZITADEL_SECRET=pe7Nh3lopXkZkfqh5YEDYI2xsbIz08eZKqInOUZxssd3refRia518Apbv3DZ
24
+ AUTH_ZITADEL_ISSUER=https://zitadel.example.com
25
+
26
+ # S3 相关,也即非结构化数据(文件、图片等)存储必需的环境变量
27
+ # 这里以 MinIO 为例
28
+ # 必填,S3 的 Access Key ID,对于 MinIO 来说,直到在 MinIO UI 中手动创建之前都是无效的
29
+ S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
30
+ # 必填,S3 的 Secret Access Key,对于 MinIO 来说,直到在 MinIO UI 中手动创建之前都是无效的
31
+ S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
32
+ # 必填,S3 的 Endpoint,用于服务端/客户端连接到 S3 API
33
+ S3_ENDPOINT=https://lobe-s3-api.example.com
34
+ # 必填,S3 的 Bucket,直到在 MinIO UI 中手动创建之前都是无效的
35
+ S3_BUCKET=lobe
36
+ # 必填,S3 的 Public Domain,用于客户端通过公开连接访问非结构化数据
37
+ S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
38
+ # 选填,S3 的 Enable Path Style
39
+ # 对于主流 S3 Cloud 服务商,一般填 0 即可;对于自部署的 MinIO,请填 1
40
+ # 请参考:https://lobehub.com/zh/docs/self-hosting/advanced/s3#s-3-enable-path-style
41
+ S3_ENABLE_PATH_STYLE=1
42
+
43
+ # 其他基础环境变量,视需求而定。注意不要有 ACCESS_CODE
44
+ # 请参考:https://lobehub.com/zh/docs/self-hosting/environment-variables/basic
45
+ # 请注意,对于服务端版本,其 API 必须支持嵌入(即 OpenAI text-embedding-3-small)模型,否则无法对上传文件进行处理,但你无需在 OPENAI_MODEL_LIST 中指定此模型
46
+ # OPENAI_API_KEY=sk-xxxx
47
+ # OPENAI_PROXY_URL=https://api.openai.com/v1
48
+ # OPENAI_MODEL_LIST=...
@@ -0,0 +1,69 @@
1
+ services:
2
+ postgresql:
3
+ image: pgvector/pgvector:pg16
4
+ container_name: lobe-postgres
5
+ ports:
6
+ - '5432:5432'
7
+ volumes:
8
+ - './data:/var/lib/postgresql/data'
9
+ environment:
10
+ - 'POSTGRES_DB=lobe'
11
+ - 'POSTGRES_PASSWORD=uWNZugjBqixf8dxC'
12
+ healthcheck:
13
+ test: ['CMD-SHELL', 'pg_isready -U postgres']
14
+ interval: 5s
15
+ timeout: 5s
16
+ retries: 5
17
+ restart: always
18
+
19
+ minio:
20
+ image: minio/minio
21
+ container_name: lobe-minio
22
+ ports:
23
+ - '9000:9000'
24
+ - '9001:9001'
25
+ volumes:
26
+ - './s3_data:/etc/minio/data'
27
+ environment:
28
+ - 'MINIO_ROOT_USER=YOUR_MINIO_USER'
29
+ - 'MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD'
30
+ - 'MINIO_DOMAIN=lobe-s3-api.example.com'
31
+ - 'MINIO_API_CORS_ALLOW_ORIGIN=https://lobe.example.com' # Your LobeChat's domain name.
32
+ restart: always
33
+ command: >
34
+ server /etc/minio/data --address ":9000" --console-address ":9001"
35
+
36
+ zitadel:
37
+ restart: always
38
+ image: ghcr.io/zitadel/zitadel:latest
39
+ container_name: lobe-zitadel
40
+ command: start-from-init --config /zitadel-config.yaml --steps
41
+ /zitadel-init-steps.yaml --masterkey "cft3Tekr/rQBOqwoQSCPoncA9BHbn7QJ"
42
+ --tlsMode external #MasterkeyNeedsToHave32Characters
43
+ ports:
44
+ - 8080:8080
45
+ volumes:
46
+ - ./zitadel-config.yaml:/zitadel-config.yaml:ro
47
+ - ./zitadel-init-steps.yaml:/zitadel-init-steps.yaml:ro
48
+ depends_on:
49
+ postgresql:
50
+ condition: service_healthy
51
+
52
+ lobe:
53
+ image: lobehub/lobe-chat-database
54
+ container_name: lobe-database
55
+ ports:
56
+ - '3210:3210'
57
+ depends_on:
58
+ - postgresql
59
+ - minio
60
+ - zitadel
61
+ env_file:
62
+ - .env
63
+ restart: always
64
+
65
+ volumes:
66
+ data:
67
+ driver: local
68
+ s3_data:
69
+ driver: local
@@ -0,0 +1,25 @@
1
+ Log:
2
+ Level: 'info'
3
+
4
+ ExternalPort: 443
5
+ ExternalDomain: example.com #Your zitadel's domain name
6
+ ExternalSecure: true
7
+ TLS:
8
+ Enabled: false # ZITADEL_TLS_ENABLED
9
+
10
+ # If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL
11
+ Database:
12
+ postgres:
13
+ Host: postgresql
14
+ Port: 5432
15
+ Database: zitadel
16
+ User:
17
+ Username: 'zitadel'
18
+ Password: 'zitadel'
19
+ SSL:
20
+ Mode: 'disable'
21
+ Admin:
22
+ Username: 'postgres'
23
+ Password: 'uWNZugjBqixf8dxC' #postgres password
24
+ SSL:
25
+ Mode: 'disable'
@@ -0,0 +1,11 @@
1
+ # All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml
2
+ FirstInstance:
3
+ Org:
4
+ Human:
5
+ # use the loginname root@zitadel.localhost, replace localhost with your configured external domain
6
+ Username: 'root'
7
+ # The password must be 8 characters or more and must contain uppercase letters, lowercase letters, symbols, and numbers. The first login will require a password change.
8
+ Password: 'Password1!'
9
+ Email:
10
+ # Optional, if set, can be used to log in with email.
11
+ Address: 'example@zitadel.com' # ZITADEL_FIRSTINSTANCE_ORG_HUMAN_EMAIL_ADDRESS
@@ -88,7 +88,7 @@ docker compose up -d
88
88
  - `Redirect URI` should be `http://localhost:3210/api/auth/callback/logto`
89
89
  - `Post sign-out redirect URI` should be `http://localhost:3210/`
90
90
 
91
- 3. Obtain the `App ID` and `App secrets`, and fill them into your `.env` file corresponding to `LOGTO_CLIENT_ID` and `LOGTO_CLIENT_SECRET`.
91
+ 3. Obtain the `App ID` and `App secrets`, and fill them into your `.env` file corresponding to `AUTH_LOGTO_ID` and `AUTH_LOGTO_SECRET`.
92
92
 
93
93
  ### Configure MinIO S3
94
94
 
@@ -258,9 +258,9 @@ You need to first access the WebUI for configuration:
258
258
  src="https://github.com/user-attachments/assets/5b816379-c07b-40ea-bde4-df16e2e4e523"
259
259
  />
260
260
 
261
- 5. Obtain `App ID` and `App secrets`, and fill them into your `.env` file under `LOGTO_CLIENT_ID` and `LOGTO_CLIENT_SECRET`.
261
+ 5. Obtain `App ID` and `App secrets`, and fill them into your `.env` file under `AUTH_LOGTO_ID` and `AUTH_LOGTO_SECRET`.
262
262
 
263
- 6. Set `LOGTO_ISSUER` in your `.env` file to `https://lobe-auth-api.example.com/oidc`.
263
+ 6. Set `AUTH_LOGTO_ISSUER` in your `.env` file to `https://lobe-auth-api.example.com/oidc`.
264
264
 
265
265
  <Image
266
266
  alt="Configure environment variables"
@@ -349,8 +349,8 @@ To facilitate one-click copying, here are the example configuration files needed
349
349
 
350
350
  ```sh
351
351
  # Logto secret
352
- LOGTO_CLIENT_ID=
353
- LOGTO_CLIENT_SECRET=
352
+ AUTH_LOGTO_ID=
353
+ AUTH_LOGTO_SECRET=
354
354
 
355
355
  # MinIO S3 configuration
356
356
  MINIO_ROOT_USER=YOUR_MINIO_USER
@@ -467,7 +467,7 @@ services:
467
467
  - 'KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ='
468
468
  - 'NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg'
469
469
  - 'NEXTAUTH_URL=http://localhost:${LOBE_PORT}/api/auth'
470
- - 'LOGTO_ISSUER=http://localhost:${LOGTO_PORT}/oidc'
470
+ - 'AUTH_LOGTO_ISSUER=http://localhost:${LOGTO_PORT}/oidc'
471
471
  - 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
472
472
  - 'S3_ENDPOINT=http://localhost:${MINIO_PORT}'
473
473
  - 'S3_BUCKET=${MINIO_LOBE_BUCKET}'
@@ -519,9 +519,9 @@ NEXTAUTH_URL=https://lobe.example.com/api/auth
519
519
 
520
520
  # NextAuth providers configuration (example using Logto)
521
521
  # For other providers, see: https://lobehub.com/docs/self-hosting/environment-variables/auth
522
- LOGTO_CLIENT_ID=YOUR_LOGTO_CLIENT_ID
523
- LOGTO_CLIENT_SECRET=YOUR_LOGTO_CLIENT_SECRET
524
- LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc
522
+ AUTH_LOGTO_ID=YOUR_LOGTO_CLIENT_ID
523
+ AUTH_LOGTO_SECRET=YOUR_LOGTO_CLIENT_SECRET
524
+ AUTH_LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc
525
525
 
526
526
  # Proxy settings (if needed, e.g., when using GitHub as an auth provider)
527
527
  # HTTP_PROXY=http://localhost:7890
@@ -86,7 +86,7 @@ docker compose up -d
86
86
  - `Redirect URI` 为 `http://localhost:3210/api/auth/callback/logto`
87
87
  - `Post sign-out redirect URI` 为 `http://localhost:3210/`
88
88
 
89
- 3. 获取 `App ID` 和 `App secrets`,填入 `.env` 文件中对应的 `LOGTO_CLIENT_ID` 、 `LOGTO_CLIENT_SECRETT`
89
+ 3. 获取 `App ID` 和 `App secrets`,填入 `.env` 文件中对应的 `AUTH_LOGTO_ID` 、 `AUTH_LOGTO_SECRET`
90
90
 
91
91
  ### 配置 MinIO S3
92
92
 
@@ -256,9 +256,9 @@ docker compose up -d # 重新启动
256
256
  src="https://github.com/user-attachments/assets/5b816379-c07b-40ea-bde4-df16e2e4e523"
257
257
  />
258
258
 
259
- 5. 获取 `App ID` 和 `App secrets`,填入你的 `.env` 文件中的 `LOGTO_CLIENT_ID` 和 `LOGTO_CLIENT_SECRETT` 中
259
+ 5. 获取 `App ID` 和 `App secrets`,填入你的 `.env` 文件中的 `AUTH_LOGTO_ID` 和 `AUTH_LOGTO_SECRET` 中
260
260
 
261
- 6. 配置你的 `.env` 文件中 `LOGTO_ISSUER` 为 `https://lobe-auth-api.example.com/oidc`
261
+ 6. 配置你的 `.env` 文件中 `AUTH_LOGTO_ISSUER` 为 `https://lobe-auth-api.example.com/oidc`
262
262
 
263
263
  <Image
264
264
  alt="配置 Logto 环境变量"
@@ -346,8 +346,8 @@ docker compose up -d # 重新启动
346
346
 
347
347
  ```sh
348
348
  # Logto secret
349
- LOGTO_CLIENT_ID=
350
- LOGTO_CLIENT_SECRET=
349
+ AUTH_LOGTO_ID=
350
+ AUTH_LOGTO_SECRET=
351
351
 
352
352
  # MinIO S3 配置
353
353
  MINIO_ROOT_USER=YOUR_MINIO_USER
@@ -464,7 +464,7 @@ services:
464
464
  - 'KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ='
465
465
  - 'NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg'
466
466
  - 'NEXTAUTH_URL=http://localhost:${LOBE_PORT}/api/auth'
467
- - 'LOGTO_ISSUER=http://localhost:${LOGTO_PORT}/oidc'
467
+ - 'AUTH_LOGTO_ISSUER=http://localhost:${LOGTO_PORT}/oidc'
468
468
  - 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
469
469
  - 'S3_ENDPOINT=http://localhost:${MINIO_PORT}'
470
470
  - 'S3_BUCKET=${MINIO_LOBE_BUCKET}'
@@ -515,9 +515,9 @@ NEXTAUTH_URL=https://lobe.example.com/api/auth
515
515
 
516
516
  # NextAuth 鉴权服务提供商部分,以 Logto 为例
517
517
  # 其他鉴权服务提供商所需的环境变量,请参考:https://lobehub.com/zh/docs/self-hosting/environment-variables/auth
518
- LOGTO_CLIENT_ID=YOUR_LOGTO_CLIENT_ID
519
- LOGTO_CLIENT_SECRET=YOUR_LOGTO_CLIENT_SECRET
520
- LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc
518
+ AUTH_LOGTO_ID=YOUR_LOGTO_CLIENT_ID
519
+ AUTH_LOGTO_SECRET=YOUR_LOGTO_CLIENT_SECRET
520
+ AUTH_LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc
521
521
 
522
522
  # 代理相关,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
523
523
  # HTTP_PROXY=http://localhost:7890
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.20.3",
3
+ "version": "1.20.5",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -217,7 +217,7 @@
217
217
  "systemjs": "^6.15.1",
218
218
  "ts-md5": "^1.3.1",
219
219
  "ua-parser-js": "^1.0.38",
220
- "unstructured-client": "^0.16.0",
220
+ "unstructured-client": "^0.18.0",
221
221
  "url-join": "^5.0.0",
222
222
  "use-merge-value": "^1.2.0",
223
223
  "utility-types": "^3.11.0",
@@ -0,0 +1,181 @@
1
+ const dns = require('dns').promises;
2
+ const fs = require('fs');
3
+ const tls = require('tls');
4
+ const { spawn } = require('child_process');
5
+
6
+ // Set file paths
7
+ const DB_MIGRATION_SCRIPT_PATH = '/app/docker.cjs';
8
+ const SERVER_SCRIPT_PATH = '/app/server.js';
9
+ const PROXYCHAINS_CONF_PATH = '/etc/proxychains4.conf';
10
+
11
+ // Function to check if a string is a valid IP address
12
+ const isValidIP = (ip, version = 4) => {
13
+ const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/;
14
+ const ipv6Regex = /^(([0-9a-f]{1,4}:){7,7}[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,7}:|([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}|([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}|[0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|:((:[0-9a-f]{1,4}){1,7}|:)|fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-f]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
15
+
16
+ switch (version) {
17
+ case 4:
18
+ return ipv4Regex.test(ip);
19
+ case 6:
20
+ return ipv6Regex.test(ip);
21
+ default:
22
+ return ipv4Regex.test(ip) || ipv6Regex.test(ip);
23
+ }
24
+ };
25
+
26
+ // Function to check TLS validity of a URL
27
+ const isValidTLS = (url = '') => {
28
+ if (!url) {
29
+ console.log('⚠️ TLS Check: No URL provided. Skipping TLS check. Ensure correct setting ENV.');
30
+ console.log('-------------------------------------');
31
+ return Promise.resolve();
32
+ }
33
+
34
+ const { protocol, host, port } = parseUrl(url);
35
+ if (protocol !== 'https') {
36
+ console.log(`⚠️ TLS Check: Non-HTTPS protocol (${protocol}). Skipping TLS check for ${url}.`);
37
+ console.log('-------------------------------------');
38
+ return Promise.resolve();
39
+ }
40
+
41
+ const options = { host, port, servername: host };
42
+ return new Promise((resolve, reject) => {
43
+ const socket = tls.connect(options, () => {
44
+ if (socket.authorized) {
45
+ console.log(`✅ TLS Check: Valid certificate for ${host}:${port}.`);
46
+ console.log('-------------------------------------');
47
+ resolve();
48
+ }
49
+ socket.end();
50
+ });
51
+
52
+ socket.on('error', (err) => {
53
+ const errMsg = `❌ TLS Check: Error for ${host}:${port}. Details:`;
54
+ switch (err.code) {
55
+ case 'CERT_HAS_EXPIRED':
56
+ case 'DEPTH_ZERO_SELF_SIGNED_CERT':
57
+ console.error(`${errMsg} Certificate is not valid. Consider setting NODE_TLS_REJECT_UNAUTHORIZED="0" or mapping /etc/ssl/certs/ca-certificates.crt.`);
58
+ break;
59
+ case 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY':
60
+ console.error(`${errMsg} Unable to verify issuer. Ensure correct mapping of /etc/ssl/certs/ca-certificates.crt.`);
61
+ break;
62
+ default:
63
+ console.error(`${errMsg} Network issue. Check firewall or DNS.`);
64
+ break;
65
+ }
66
+ reject(err);
67
+ });
68
+ });
69
+ };
70
+
71
+ // Function to check TLS connections for OSS and Auth Issuer
72
+ const checkTLSConnections = async () => {
73
+ await Promise.all([
74
+ isValidTLS(process.env.S3_ENDPOINT),
75
+ isValidTLS(process.env.S3_PUBLIC_DOMAIN),
76
+ isValidTLS(getEnvVarsByKeyword('_ISSUER')),
77
+ ]);
78
+ };
79
+
80
+ // Function to get environment variable by keyword
81
+ const getEnvVarsByKeyword = (keyword) => {
82
+ return Object.entries(process.env)
83
+ .filter(([key, value]) => key.includes(keyword) && value)
84
+ .map(([, value]) => value)[0] || null;
85
+ };
86
+
87
+ // Function to parse protocol, host and port from a URL
88
+ const parseUrl = (url) => {
89
+ const { protocol, hostname: host, port } = new URL(url);
90
+ return { protocol: protocol.replace(':', ''), host, port: port || 443 };
91
+ };
92
+
93
+ // Function to resolve host IP via DNS
94
+ const resolveHostIP = async (host, version = 4) => {
95
+ try {
96
+ const { address } = await dns.lookup(host, { family: version });
97
+
98
+ if (!isValidIP(address, version)) {
99
+ console.error(`❌ DNS Error: Invalid resolved IP: ${address}. IP address must be IPv${version}.`);
100
+ process.exit(1);
101
+ }
102
+
103
+ return address;
104
+ } catch (err) {
105
+ console.error(`❌ DNS Error: Could not resolve ${host}. Check DNS server.`, err);
106
+ process.exit(1);
107
+ }
108
+ };
109
+
110
+ // Function to generate proxychains configuration
111
+ const runProxyChainsConfGenerator = async (url) => {
112
+ const { protocol, host, port } = parseUrl(url);
113
+
114
+ if (!['http', 'socks4', 'socks5'].includes(protocol)) {
115
+ console.error(`❌ ProxyChains: Invalid protocol (${protocol}). Protocol must be 'http', 'socks4' and 'socks5'.`);
116
+ process.exit(1);
117
+ }
118
+
119
+ const validPort = parseInt(port, 10);
120
+ if (isNaN(validPort) || validPort <= 0 || validPort > 65535) {
121
+ console.error(`❌ ProxyChains: Invalid port (${port}). Port must be a number between 1 and 65535.`);
122
+ process.exit(1);
123
+ }
124
+
125
+ let ip = isValidIP(host, 4) ? host : await resolveHostIP(host, 4);
126
+
127
+ const configContent = `
128
+ localnet 127.0.0.0/255.0.0.0
129
+ localnet ::1/128
130
+ proxy_dns
131
+ remote_dns_subnet 224
132
+ strict_chain
133
+ tcp_connect_time_out 8000
134
+ tcp_read_time_out 15000
135
+ [ProxyList]
136
+ ${protocol} ${ip} ${port}
137
+ `.trim();
138
+
139
+ fs.writeFileSync(PROXYCHAINS_CONF_PATH, configContent);
140
+ console.log(`✅ ProxyChains: All outgoing traffic routed via ${protocol}://${ip}:${port}.`);
141
+ console.log('-------------------------------------');
142
+ };
143
+
144
+ // Function to execute a script with child process spawn
145
+ const runScript = (scriptPath, useProxy = false) => {
146
+ const command = useProxy ? ['/bin/proxychains', '-q', '/bin/node', scriptPath] : ['/bin/node', scriptPath];
147
+ return new Promise((resolve, reject) => {
148
+ const process = spawn(command.shift(), command, { stdio: 'inherit' });
149
+ process.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`🔴 Process exited with code ${code}`))));
150
+ });
151
+ };
152
+
153
+ // Main function to run the server with optional proxy
154
+ const runServer = async () => {
155
+ const PROXY_URL = process.env.PROXY_URL || ''; // Default empty string to avoid undefined errors
156
+
157
+ if (PROXY_URL) {
158
+ await runProxyChainsConfGenerator(PROXY_URL);
159
+ return runScript(SERVER_SCRIPT_PATH, true);
160
+ }
161
+ return runScript(SERVER_SCRIPT_PATH);
162
+ };
163
+
164
+ // Main execution block
165
+ (async () => {
166
+ console.log('🌐 DNS Server:', dns.getServers());
167
+ console.log('-------------------------------------');
168
+
169
+ if (process.env.DATABASE_DRIVER) {
170
+ try {
171
+ await runScript(DB_MIGRATION_SCRIPT_PATH);
172
+ await checkTLSConnections();
173
+ } catch (err) {
174
+ console.error('❌ Error during DB migration or TLS connection check:', err);
175
+ process.exit(1);
176
+ }
177
+ }
178
+
179
+ // Run the server in either database or non-database mode
180
+ await runServer();
181
+ })();
@@ -3,6 +3,12 @@ import { ChatHeader } from '@lobehub/ui';
3
3
  import HeaderAction from './HeaderAction';
4
4
  import Main from './Main';
5
5
 
6
- const Header = () => <ChatHeader left={<Main />} right={<HeaderAction />} style={{ zIndex: 11 }} />;
6
+ const Header = () => (
7
+ <ChatHeader
8
+ left={<Main />}
9
+ right={<HeaderAction />}
10
+ style={{ minHeight: 64, position: 'initial', zIndex: 11 }}
11
+ />
12
+ );
7
13
 
8
14
  export default Header;
@@ -6,7 +6,6 @@ import { rgba } from 'polished';
6
6
  import { PropsWithChildren, memo } from 'react';
7
7
  import { Flexbox } from 'react-layout-kit';
8
8
 
9
- import SafeSpacing from '@/components/SafeSpacing';
10
9
  import { CHAT_DOCK_TOOL_UI_WIDTH, CHAT_DOCK_WIDTH, MAX_WIDTH } from '@/const/layoutTokens';
11
10
  import { useChatStore } from '@/store/chat';
12
11
  import { chatPortalSelectors } from '@/store/chat/slices/portal/selectors';
@@ -69,7 +68,6 @@ const PortalPanel = memo(({ children }: PropsWithChildren) => {
69
68
  minWidth: CHAT_DOCK_WIDTH,
70
69
  }}
71
70
  >
72
- <SafeSpacing />
73
71
  <Flexbox className={styles.panel}>{children}</Flexbox>
74
72
  </DraggablePanelContainer>
75
73
  </DraggablePanel>
@@ -5,7 +5,6 @@ import { createStyles, useResponsive } from 'antd-style';
5
5
  import isEqual from 'fast-deep-equal';
6
6
  import { PropsWithChildren, memo, useEffect, useState } from 'react';
7
7
 
8
- import SafeSpacing from '@/components/SafeSpacing';
9
8
  import { CHAT_SIDEBAR_WIDTH } from '@/const/layoutTokens';
10
9
  import { useChatStore } from '@/store/chat';
11
10
  import { chatPortalSelectors } from '@/store/chat/slices/portal/selectors';
@@ -71,7 +70,6 @@ const TopicPanel = memo(({ children }: PropsWithChildren) => {
71
70
  minWidth: CHAT_SIDEBAR_WIDTH,
72
71
  }}
73
72
  >
74
- <SafeSpacing />
75
73
  {children}
76
74
  </DraggablePanelContainer>
77
75
  </DraggablePanel>
@@ -13,7 +13,7 @@ import { SessionGroupItem } from '@/types/session';
13
13
 
14
14
  import GroupItem from './GroupItem';
15
15
 
16
- const useStyles = createStyles(({ css, token, stylish }) => ({
16
+ const useStyles = createStyles(({ css, token }) => ({
17
17
  container: css`
18
18
  height: 36px;
19
19
  padding-inline: 8px;
@@ -21,7 +21,6 @@ const useStyles = createStyles(({ css, token, stylish }) => ({
21
21
  transition: background 0.2s ease-in-out;
22
22
 
23
23
  &:hover {
24
- ${stylish.blur};
25
24
  background: ${token.colorFillTertiary};
26
25
  }
27
26
  `,
@@ -58,7 +58,6 @@ const useStyles = createStyles(({ css, token }) => {
58
58
  height: 100%;
59
59
 
60
60
  background: ${token.colorBgMask};
61
- backdrop-filter: blur(4px);
62
61
 
63
62
  transition: all 0.3s ease-in-out;
64
63
  `,
@@ -31,7 +31,6 @@ export const useStyles = createStyles(({ css, token, prefixCls, isDarkMode, resp
31
31
  `,
32
32
  wrap: css`
33
33
  overflow: hidden auto;
34
- backdrop-filter: blur(2px);
35
34
  `,
36
35
  };
37
36
  });
@@ -32,7 +32,6 @@ const useStyles = createStyles(({ css, token, prefixCls }) => {
32
32
  `,
33
33
  wrap: css`
34
34
  overflow: hidden auto;
35
- backdrop-filter: blur(2px);
36
35
  `,
37
36
  };
38
37
  });
@@ -43,10 +43,9 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
43
43
 
44
44
  const data = useChatStore((s) => {
45
45
  const showInboxWelcome = chatSelectors.showInboxWelcome(s);
46
- const ids = showInboxWelcome
46
+ return showInboxWelcome
47
47
  ? [WELCOME_GUIDE_CHAT_ID]
48
48
  : chatSelectors.currentChatIDsWithGuideMessage(s);
49
- return ['empty', ...ids];
50
49
  }, isEqual);
51
50
 
52
51
  useEffect(() => {
@@ -71,11 +70,7 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
71
70
  (index: number, id: string) => {
72
71
  if (id === WELCOME_GUIDE_CHAT_ID) return <InboxWelcome />;
73
72
 
74
- return index === 0 ? (
75
- <div style={{ height: 24 + (mobile ? 0 : 64) }} />
76
- ) : (
77
- <Item id={id} index={index - 1} />
78
- );
73
+ return <Item id={id} index={index} />;
79
74
  },
80
75
  [mobile],
81
76
  );
@@ -26,7 +26,6 @@ export const useStyles = createStyles(
26
26
  `,
27
27
  modalBackdrop: css`
28
28
  background: ${token.colorBgMask};
29
- backdrop-filter: blur(2px);
30
29
  `,
31
30
  modalContent: css`
32
31
  &.${prefixCls}-modalContent {