Enterprise AI Workspace prototype: LobeChat (de-branded) + Enterprise Gateway + Postgres/Redis stack
Revalidate Docs / Revalidate Docs (push) Failing after 2s
E2E CI / Check Duplicate Run (push) Failing after 5s
Test CI / Check Duplicate Run (push) Failing after 6s
E2E CI / Test Web App (push) Has been skipped
Test CI / Test Packages (push) Has been skipped
Test CI / Test App (shard 1/3) (push) Has been skipped
Test CI / Test App (shard 2/3) (push) Has been skipped
Test CI / Test App (shard 3/3) (push) Has been skipped
Test CI / Test Desktop App (push) Has been skipped
🔄 Branch Synchronization / sync-branches (push) Failing after 11s
Test CI / Test Database (push) Has been skipped
Test CI / Merge and Upload App Coverage (push) Has been skipped
Database Schema Visualization CI / build (push) Failing after 4m14s
Revalidate Docs / Revalidate Docs (push) Failing after 2s
E2E CI / Check Duplicate Run (push) Failing after 5s
Test CI / Check Duplicate Run (push) Failing after 6s
E2E CI / Test Web App (push) Has been skipped
Test CI / Test Packages (push) Has been skipped
Test CI / Test App (shard 1/3) (push) Has been skipped
Test CI / Test App (shard 2/3) (push) Has been skipped
Test CI / Test App (shard 3/3) (push) Has been skipped
Test CI / Test Desktop App (push) Has been skipped
🔄 Branch Synchronization / sync-branches (push) Failing after 11s
Test CI / Test Database (push) Has been skipped
Test CI / Merge and Upload App Coverage (push) Has been skipped
Database Schema Visualization CI / build (push) Failing after 4m14s
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Proxy, if you need it
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
# Allowed email addresses for login, separated by commas
|
||||
# When set, only emails in the list can log in, other users cannot log in
|
||||
# Leave empty to allow all users to register
|
||||
# AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com
|
||||
|
||||
# Disable user registration (SSO-only mode)
|
||||
# When set to 1, users cannot register via email/password, only SSO login is allowed
|
||||
# AUTH_DISABLE_EMAIL_PASSWORD=1
|
||||
|
||||
# ===========================
|
||||
# ====== Preset config ======
|
||||
# ===========================
|
||||
# if no special requirements, no need to change
|
||||
LOBE_PORT=3210
|
||||
RUSTFS_PORT=9000
|
||||
RUSTFS_ADMIN_PORT=9001
|
||||
APP_URL=http://localhost:3210
|
||||
# INTERNAL_APP_URL is used for internal server-to-server communication.
|
||||
# Required for Docker Compose deployments, otherwise features like
|
||||
# AI image generation will fail when APP_URL is a host/LAN IP.
|
||||
INTERNAL_APP_URL=http://localhost:3210
|
||||
|
||||
# Secrets (auto-generated by setup.sh)
|
||||
KEY_VAULTS_SECRET=YOUR_KEY_VAULTS_SECRET
|
||||
AUTH_SECRET=YOUR_AUTH_SECRET
|
||||
|
||||
# Postgres related, which are the necessary environment variables for DB
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
|
||||
|
||||
# RUSTFS S3 configuration
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
RUSTFS_ACCESS_KEY=admin
|
||||
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
|
||||
|
||||
# Configure the bucket information of RUSTFS
|
||||
RUSTFS_LOBE_BUCKET=lobe
|
||||
|
||||
JWKS_KEY={"keys":[{"d":"PVoFyqyrGstB8wU52S7gqqQQdZLtin_thcEM0nrNtqp9U-NlKLlhgEcWp5t89ycgvhsAzmrRbezGj4JBTr3jn7eWdwQpPJNYiipnsgeJn0pwsB0H2dMqtavxinoPVXkMTOuGHMTFhhyguFBw2JbIL0PTQUcUlXjv40OoJpYHZeggSxgfV-TuxjwW8Ll4-n84M5IOi6A53RvioE-Hm1iyIc2XLBCfyOu-SbAQYi8HzrA64kCxobAB0peLQMiAzfZmwPKiGOhnhKrAlYmG02qFnbUYiJu_-AXwsAyGv9S9i6dwK7QXaGGWYyis8LlPpd_JmPrBnrWomwDlI045NUMWZQ","dp":"OSXI2NBBZl2r0Dpf4-1z44A_jC5lOyXtJhXQYnSXy5eIuxTJcEtkUYagGEwnREO4Q3t-4J-lT_6Y71M1ZlgKG1upwfw1O4aE3vGpHOik9iZYYCjA8fe5uBfOpX1ELmOtHNoHRhMtyjuPxSFXLlSp3bgcF1f3F40ClukdvXCx0Mc","dq":"m6hNdfj-F8E_7nUlX2nG95OffkFrhHTo67ML9aPgpvFwBlzg-hk5LwtxMfUzngqWF78TMl0JDm7vS1bz0xlWqXqu8pFPoTUnUoWgYfvuyHLBwR5TgccQkfoKbkSMzYNy8VJPXZeyIjVXsW98tZvj-NZF-M9Pke_EWJm-jjXCu_8","e":"AQAB","kty":"RSA","n":"piffosMS0HOSgsSr_zQkXYaQt1kOCD73VR0b2XJD6UdQCKPbnBOzTIuA_xowX61QVsl5pCZLTw8ERC3r2Nlxj5Rp_H6RuOT7ioUqlbnxSGnfuAn8dFupY3A-sf9HVDOvtJdlS-nO9yA4wWU-A50zZ1Mf0pPZlUZE6dUQfsJFi5yXaNAybyk3U4VpMO_SXAilWEHVhiO0F0ccpJMCkT47AeXmYH9MlWwIGcay0UiAsdrs8J-q1arZ7Mbq0oxHmUXJG0vwRvAL8KnCEi8cJ3e2kKCRcr-BQCujsHUyUl6f_ATwSVuTHdAR1IzIcW37v27h3WQK_v0ffQM1NstamDX5vQ","p":"4myVm2M5cZGvVXsOmWUTUG87VC1GlQcL5tmMNSGSpQCL8yWZ1vANkmCxSMptrKB4dU9DAB3On6_oMhW1pJ3uYNGSW49BcmJoLkiWKeg5zWFnKPQNuThQmY1sCCubtKhBQgaYUr7TVzN9smrDV3zCu9MlRl-XPwnEmWaDII3g-f8","q":"u9v4IOEsb4l2Y3eWKE2bwJh5fJRR4vivaYA7U-1-OpvDwB3A48Rey9IL1ucXqE5G1Du8BtijPm5oSAar5uzrjtg1bZ9gevif6DnBGaIRE7LnSrUsTPfZwzntJ1rTaGiVe_pAdnTKXXaH6DxygXxH4wvGgA44V3TTfBXQUcjzdEM","qi":"lDBnSPKkRnYqQvbqVD1LxzqBPEeqEA3GyCqMj6fIZNgoEaBSLi0TSsUyGZ5mahX3KO35vKAZa5jvGjhvUGUiXycq8KvRZdeGK45vJdwZT2TiXiDwo9IQgJcbFMpxaB9DhjX2x0yqxgUY5ca75jLqbMuKBKBN0PVqIr9jlHkR8_s","use":"sig","kid":"6823046760c5d460","alg":"RS256"}]}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Proxy,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
# 允许登录的邮箱地址,用英文逗号分隔
|
||||
# 设置后只有列表中的邮箱可以登录,其他用户可以注册但无法登录
|
||||
# 留空则允许所有用户注册登录
|
||||
# AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com
|
||||
|
||||
# 禁用用户注册(仅允许 SSO 登录)
|
||||
# 设置为 1 后,用户无法通过邮箱密码注册,只能通过 SSO 登录
|
||||
# AUTH_DISABLE_EMAIL_PASSWORD=1
|
||||
|
||||
# ===================
|
||||
# ===== 预设配置 =====
|
||||
# ===================
|
||||
# 如没有特殊需要不用更改
|
||||
LOBE_PORT=3210
|
||||
APP_URL=http://localhost:3210
|
||||
# 内部应用URL,用于容器内部服务间通信
|
||||
# Docker Compose 部署时必须配置,否则当 APP_URL 为宿主机 IP 时 AI 生图等功能会失败
|
||||
INTERNAL_APP_URL=http://localhost:3210
|
||||
|
||||
# 密钥配置(由 setup.sh 自动生成)
|
||||
KEY_VAULTS_SECRET=YOUR_KEY_VAULTS_SECRET
|
||||
AUTH_SECRET=YOUR_AUTH_SECRET
|
||||
|
||||
# PostgreSQL 配置
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
|
||||
|
||||
# RustFS S3 配置
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
RUSTFS_PORT=9000
|
||||
RUSTFS_ADMIN_PORT=9001
|
||||
RUSTFS_ACCESS_KEY=admin
|
||||
RUSTFS_SECRET_KEY=YOUR_RUSTFS_PASSWORD
|
||||
RUSTFS_LOBE_BUCKET=lobe
|
||||
|
||||
JWKS_KEY={"keys":[{"d":"PVoFyqyrGstB8wU52S7gqqQQdZLtin_thcEM0nrNtqp9U-NlKLlhgEcWp5t89ycgvhsAzmrRbezGj4JBTr3jn7eWdwQpPJNYiipnsgeJn0pwsB0H2dMqtavxinoPVXkMTOuGHMTFhhyguFBw2JbIL0PTQUcUlXjv40OoJpYHZeggSxgfV-TuxjwW8Ll4-n84M5IOi6A53RvioE-Hm1iyIc2XLBCfyOu-SbAQYi8HzrA64kCxobAB0peLQMiAzfZmwPKiGOhnhKrAlYmG02qFnbUYiJu_-AXwsAyGv9S9i6dwK7QXaGGWYyis8LlPpd_JmPrBnrWomwDlI045NUMWZQ","dp":"OSXI2NBBZl2r0Dpf4-1z44A_jC5lOyXtJhXQYnSXy5eIuxTJcEtkUYagGEwnREO4Q3t-4J-lT_6Y71M1ZlgKG1upwfw1O4aE3vGpHOik9iZYYCjA8fe5uBfOpX1ELmOtHNoHRhMtyjuPxSFXLlSp3bgcF1f3F40ClukdvXCx0Mc","dq":"m6hNdfj-F8E_7nUlX2nG95OffkFrhHTo67ML9aPgpvFwBlzg-hk5LwtxMfUzngqWF78TMl0JDm7vS1bz0xlWqXqu8pFPoTUnUoWgYfvuyHLBwR5TgccQkfoKbkSMzYNy8VJPXZeyIjVXsW98tZvj-NZF-M9Pke_EWJm-jjXCu_8","e":"AQAB","kty":"RSA","n":"piffosMS0HOSgsSr_zQkXYaQt1kOCD73VR0b2XJD6UdQCKPbnBOzTIuA_xowX61QVsl5pCZLTw8ERC3r2Nlxj5Rp_H6RuOT7ioUqlbnxSGnfuAn8dFupY3A-sf9HVDOvtJdlS-nO9yA4wWU-A50zZ1Mf0pPZlUZE6dUQfsJFi5yXaNAybyk3U4VpMO_SXAilWEHVhiO0F0ccpJMCkT47AeXmYH9MlWwIGcay0UiAsdrs8J-q1arZ7Mbq0oxHmUXJG0vwRvAL8KnCEi8cJ3e2kKCRcr-BQCujsHUyUl6f_ATwSVuTHdAR1IzIcW37v27h3WQK_v0ffQM1NstamDX5vQ","p":"4myVm2M5cZGvVXsOmWUTUG87VC1GlQcL5tmMNSGSpQCL8yWZ1vANkmCxSMptrKB4dU9DAB3On6_oMhW1pJ3uYNGSW49BcmJoLkiWKeg5zWFnKPQNuThQmY1sCCubtKhBQgaYUr7TVzN9smrDV3zCu9MlRl-XPwnEmWaDII3g-f8","q":"u9v4IOEsb4l2Y3eWKE2bwJh5fJRR4vivaYA7U-1-OpvDwB3A48Rey9IL1ucXqE5G1Du8BtijPm5oSAar5uzrjtg1bZ9gevif6DnBGaIRE7LnSrUsTPfZwzntJ1rTaGiVe_pAdnTKXXaH6DxygXxH4wvGgA44V3TTfBXQUcjzdEM","qi":"lDBnSPKkRnYqQvbqVD1LxzqBPEeqEA3GyCqMj6fIZNgoEaBSLi0TSsUyGZ5mahX3KO35vKAZa5jvGjhvUGUiXycq8KvRZdeGK45vJdwZT2TiXiDwo9IQgJcbFMpxaB9DhjX2x0yqxgUY5ca75jLqbMuKBKBN0PVqIr9jlHkR8_s","use":"sig","kid":"6823046760c5d460","alg":"RS256"}]}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"ID": "",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*"]
|
||||
},
|
||||
"Action": ["s3:GetObject"],
|
||||
"NotAction": [],
|
||||
"Resource": ["arn:aws:s3:::lobe/*"],
|
||||
"NotResource": [],
|
||||
"Condition": {}
|
||||
}
|
||||
],
|
||||
"Version": "2012-10-17"
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
name: lobehub
|
||||
services:
|
||||
lobe:
|
||||
image: lobehub/lobehub
|
||||
container_name: lobehub
|
||||
ports:
|
||||
- '${LOBE_PORT}:3210'
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
rustfs:
|
||||
condition: service_healthy
|
||||
rustfs-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
- 'KEY_VAULTS_SECRET=${KEY_VAULTS_SECRET}'
|
||||
- 'AUTH_SECRET=${AUTH_SECRET}'
|
||||
- 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
|
||||
- 'INTERNAL_APP_URL=http://localhost:3210'
|
||||
- 'S3_ENDPOINT=${S3_ENDPOINT}'
|
||||
- 'S3_BUCKET=${RUSTFS_LOBE_BUCKET}'
|
||||
- 'S3_ENABLE_PATH_STYLE=1'
|
||||
- 'S3_ACCESS_KEY=${RUSTFS_ACCESS_KEY}'
|
||||
- 'S3_ACCESS_KEY_ID=${RUSTFS_ACCESS_KEY}'
|
||||
- 'S3_SECRET_ACCESS_KEY=${RUSTFS_SECRET_KEY}'
|
||||
- 'LLM_VISION_IMAGE_USE_BASE64=1'
|
||||
- 'S3_SET_ACL=0'
|
||||
- 'SEARXNG_URL=http://searxng:8080'
|
||||
- 'REDIS_URL=redis://redis:6379'
|
||||
- 'REDIS_PREFIX=lobechat'
|
||||
- 'REDIS_TLS=0'
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
postgresql:
|
||||
image: paradedb/paradedb:latest-pg17
|
||||
container_name: lobe-postgres
|
||||
# Optional: Remove or change these ports if:
|
||||
# - You don't need external database access
|
||||
# - The ports conflict with other services on your host
|
||||
ports:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- './data:/var/lib/postgresql/data'
|
||||
environment:
|
||||
- 'POSTGRES_DB=${LOBE_DB_NAME}'
|
||||
- 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}'
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U postgres']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: lobe-redis
|
||||
# Optional: Remove or change these ports if:
|
||||
# - You don't need external access
|
||||
# - The ports conflict with other services on your host
|
||||
ports:
|
||||
- '6379:6379'
|
||||
command: redis-server --save 60 1000 --appendonly yes
|
||||
volumes:
|
||||
- 'redis_data:/data'
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', 'ping']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
rustfs:
|
||||
image: rustfs/rustfs:latest
|
||||
container_name: lobe-rustfs
|
||||
ports:
|
||||
- '${RUSTFS_PORT}:9000'
|
||||
- '${RUSTFS_ADMIN_PORT}:9001'
|
||||
# Optional: Remove or change RUSTFS_ADMIN_PORT if:
|
||||
# - You don't need external access to rustfs control panel
|
||||
# - The ports conflict with other services on your host
|
||||
# - RUSTFS_PORT is necessary only if you need to upload images to conversations. (avatar uploads are not affected)
|
||||
# - Uploading images to conversations requires a browser-accessible S3_ENDPOINT.
|
||||
environment:
|
||||
- RUSTFS_CONSOLE_ENABLE=true
|
||||
- RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY}
|
||||
- RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY}
|
||||
volumes:
|
||||
- 'rustfs-data:/data'
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'wget -qO- http://localhost:9000/health >/dev/null 2>&1 || exit 1']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
command:
|
||||
['--access-key', '${RUSTFS_ACCESS_KEY}', '--secret-key', '${RUSTFS_SECRET_KEY}', '/data']
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
rustfs-init:
|
||||
image: minio/mc:latest
|
||||
container_name: lobe-rustfs-init
|
||||
depends_on:
|
||||
rustfs:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./bucket.config.json:/bucket.config.json:ro
|
||||
entrypoint: /bin/sh
|
||||
command: -c ' set -eux; echo "S3_ACCESS_KEY=${RUSTFS_ACCESS_KEY}, S3_SECRET_KEY=${RUSTFS_SECRET_KEY}"; mc --version; mc alias set rustfs "http://rustfs:9000" "${RUSTFS_ACCESS_KEY}" "${RUSTFS_SECRET_KEY}"; mc ls rustfs || true; mc mb "rustfs/lobe" --ignore-existing; mc admin info rustfs || true; mc anonymous set-json "/bucket.config.json" "rustfs/lobe"; '
|
||||
restart: 'no'
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
searxng:
|
||||
image: searxng/searxng
|
||||
container_name: lobe-searxng
|
||||
volumes:
|
||||
- './searxng-settings.yml:/etc/searxng/settings.yml'
|
||||
environment:
|
||||
- 'SEARXNG_SETTINGS_FILE=/etc/searxng/settings.yml'
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
networks:
|
||||
lobe-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
driver: local
|
||||
rustfs-data:
|
||||
driver: local
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
# Proxy, if you need it
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
|
||||
# Other environment variables, as needed. You can refer to the environment variables configuration for the client version, making sure not to have ACCESS_CODE.
|
||||
# OPENAI_API_KEY=sk-xxxx
|
||||
# OPENAI_PROXY_URL=https://api.openai.com/v1
|
||||
# OPENAI_MODEL_LIST=...
|
||||
|
||||
|
||||
# ===========================
|
||||
# ====== Preset config ======
|
||||
# ===========================
|
||||
# if no special requirements, no need to change
|
||||
LOBE_PORT=3210
|
||||
RUSTFS_PORT=9000
|
||||
|
||||
# Postgres related, which are the necessary environment variables for DB
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=change_this_password_on_production
|
||||
|
||||
# RUSTFS S3 configuration
|
||||
RUSTFS_ACCESS_KEY=admin
|
||||
RUSTFS_SECRET_KEY=change_this_password_on_production
|
||||
|
||||
# Configure the bucket information of RUSTFS
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
RUSTFS_LOBE_BUCKET=lobe
|
||||
@@ -0,0 +1,29 @@
|
||||
# Proxy,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
|
||||
# 其他环境变量,视需求而定,可以参照客户端版本的环境变量配置,注意不要有 ACCESS_CODE
|
||||
# OPENAI_API_KEY=sk-xxxx
|
||||
# OPENAI_PROXY_URL=https://api.openai.com/v1
|
||||
# OPENAI_MODEL_LIST=...
|
||||
|
||||
|
||||
# ===================
|
||||
# ===== 预设配置 =====
|
||||
# ===================
|
||||
# 如没有特殊需要不用更改
|
||||
LOBE_PORT=3210
|
||||
RUSTFS_PORT=9000
|
||||
|
||||
# Postgres 相关,也即 DB 必须的环境变量
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=change_this_password_on_production
|
||||
|
||||
# RustFS S3 配置
|
||||
RUSTFS_ACCESS_KEY=admin
|
||||
RUSTFS_SECRET_KEY=change_this_password_on_production
|
||||
|
||||
# RustFS bucket 配置
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
RUSTFS_LOBE_BUCKET=lobe
|
||||
@@ -0,0 +1,2 @@
|
||||
data/
|
||||
s3_data/
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"ID": "",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*"]
|
||||
},
|
||||
"Action": ["s3:GetObject"],
|
||||
"NotAction": [],
|
||||
"Resource": ["arn:aws:s3:::lobe/*"],
|
||||
"NotResource": [],
|
||||
"Condition": {}
|
||||
}
|
||||
],
|
||||
"Version": "2012-10-17"
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
name: lobehub
|
||||
services:
|
||||
network-service:
|
||||
image: alpine
|
||||
container_name: lobe-network
|
||||
restart: always
|
||||
ports:
|
||||
- '${RUSTFS_PORT}:9000' # RustFS API
|
||||
- '9001:9001' # RustFS Console
|
||||
- '${LOBE_PORT}:3210' # LobeChat
|
||||
command: tail -f /dev/null
|
||||
networks:
|
||||
- lobe-network
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
postgresql:
|
||||
image: paradedb/paradedb:latest-pg17
|
||||
container_name: lobe-postgres
|
||||
ports:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- './data:/var/lib/postgresql/data'
|
||||
environment:
|
||||
- 'POSTGRES_DB=${LOBE_DB_NAME}'
|
||||
- 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}'
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U postgres']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: lobe-redis
|
||||
ports:
|
||||
- '6379:6379'
|
||||
command: redis-server --save 60 1000 --appendonly yes
|
||||
volumes:
|
||||
- 'redis_data:/data'
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', 'ping']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
rustfs:
|
||||
image: rustfs/rustfs:latest
|
||||
container_name: lobe-rustfs
|
||||
network_mode: 'service:network-service'
|
||||
environment:
|
||||
- RUSTFS_CONSOLE_ENABLE=true
|
||||
- RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY}
|
||||
- RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY}
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'wget -qO- http://localhost:9000/health >/dev/null 2>&1 || exit 1']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
command: ['--access-key','${RUSTFS_ACCESS_KEY}','--secret-key','${RUSTFS_SECRET_KEY}','/data']
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
rustfs-init:
|
||||
image: minio/mc:latest
|
||||
container_name: lobe-rustfs-init
|
||||
depends_on:
|
||||
rustfs:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./bucket.config.json:/bucket.config.json:ro
|
||||
entrypoint: /bin/sh
|
||||
command: -c '
|
||||
set -eux;
|
||||
echo "S3_ACCESS_KEY=${RUSTFS_ACCESS_KEY}, S3_SECRET_KEY=${RUSTFS_SECRET_KEY}";
|
||||
mc --version;
|
||||
mc alias set rustfs "http://network-service:9000" "${RUSTFS_ACCESS_KEY}" "${RUSTFS_SECRET_KEY}";
|
||||
mc ls rustfs || true;
|
||||
mc mb "rustfs/lobe" --ignore-existing;
|
||||
mc admin info rustfs || true;
|
||||
mc anonymous set-json "/bucket.config.json" "rustfs/lobe";
|
||||
'
|
||||
restart: 'no'
|
||||
networks:
|
||||
- lobe-network
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
searxng:
|
||||
image: searxng/searxng
|
||||
container_name: lobe-searxng
|
||||
ports:
|
||||
- '8180:8080'
|
||||
volumes:
|
||||
- './searxng-settings.yml:/etc/searxng/settings.yml'
|
||||
environment:
|
||||
- 'SEARXNG_SETTINGS_FILE=/etc/searxng/settings.yml'
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
volumes:
|
||||
data:
|
||||
driver: local
|
||||
redis_data:
|
||||
driver: local
|
||||
rustfs-data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
lobe-network:
|
||||
driver: bridge
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
# Proxy, if you need it
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
|
||||
# Other environment variables, as needed. You can refer to the environment variables configuration for the client version, making sure not to have ACCESS_CODE.
|
||||
# OPENAI_API_KEY=sk-xxxx
|
||||
# OPENAI_PROXY_URL=https://api.openai.com/v1
|
||||
# OPENAI_MODEL_LIST=...
|
||||
|
||||
|
||||
# ===========================
|
||||
# ====== Preset config ======
|
||||
# ===========================
|
||||
# if no special requirements, no need to change
|
||||
LOBE_PORT=3210
|
||||
CASDOOR_PORT=8000
|
||||
MINIO_PORT=9000
|
||||
APP_URL=http://localhost:3210
|
||||
AUTH_URL=http://localhost:3210/api/auth
|
||||
|
||||
# Postgres related, which are the necessary environment variables for DB
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
|
||||
|
||||
AUTH_CASDOOR_ISSUER=http://localhost:8000
|
||||
# Casdoor secret
|
||||
AUTH_CASDOOR_ID=a387a4892ee19b1a2249
|
||||
AUTH_CASDOOR_SECRET=dbf205949d704de81b0b5b3603174e23fbecc354
|
||||
CASDOOR_WEBHOOK_SECRET=casdoor-secret
|
||||
|
||||
# MinIO S3 configuration
|
||||
MINIO_ROOT_USER=admin
|
||||
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
|
||||
|
||||
# Configure the bucket information of MinIO
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
MINIO_LOBE_BUCKET=lobe
|
||||
|
||||
GF_SECURITY_ADMIN_PASSWORD=YOUR_GRAFANA_PASSWORD
|
||||
|
||||
# Configure for casdoor
|
||||
origin=http://localhost:8000
|
||||
@@ -0,0 +1,41 @@
|
||||
# Proxy,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
|
||||
# HTTP_PROXY=http://localhost:7890
|
||||
# HTTPS_PROXY=http://localhost:7890
|
||||
|
||||
|
||||
# 其他环境变量,视需求而定,可以参照客户端版本的环境变量配置,注意不要有 ACCESS_CODE
|
||||
# OPENAI_API_KEY=sk-xxxx
|
||||
# OPENAI_PROXY_URL=https://api.openai.com/v1
|
||||
# OPENAI_MODEL_LIST=...
|
||||
|
||||
|
||||
# ===================
|
||||
# ===== 预设配置 =====
|
||||
# ===================
|
||||
# 如没有特殊需要不用更改
|
||||
LOBE_PORT=3210
|
||||
CASDOOR_PORT=8000
|
||||
MINIO_PORT=9000
|
||||
APP_URL=http://localhost:3210
|
||||
AUTH_URL=http://localhost:3210/api/auth
|
||||
|
||||
# Postgres 相关,也即 DB 必须的环境变量
|
||||
LOBE_DB_NAME=lobechat
|
||||
POSTGRES_PASSWORD=uWNZugjBqixf8dxC
|
||||
|
||||
AUTH_CASDOOR_ISSUER=http://localhost:8000
|
||||
# Casdoor secret
|
||||
AUTH_CASDOOR_ID=a387a4892ee19b1a2249
|
||||
AUTH_CASDOOR_SECRET=dbf205949d704de81b0b5b3603174e23fbecc354
|
||||
CASDOOR_WEBHOOK_SECRET=casdoor-secret
|
||||
|
||||
# MinIO S3 配置
|
||||
MINIO_ROOT_USER=admin
|
||||
MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD
|
||||
|
||||
# 在下方配置 minio 中添加的桶
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
MINIO_LOBE_BUCKET=lobe
|
||||
|
||||
# 为 casdoor 配置
|
||||
origin=http://localhost:8000
|
||||
@@ -0,0 +1,250 @@
|
||||
name: lobehub
|
||||
services:
|
||||
network-service:
|
||||
image: alpine
|
||||
container_name: lobe-network
|
||||
restart: always
|
||||
ports:
|
||||
- '${MINIO_PORT}:${MINIO_PORT}' # MinIO API
|
||||
- '9001:9001' # MinIO Console
|
||||
- '${CASDOOR_PORT}:${CASDOOR_PORT}' # Casdoor
|
||||
- '${LOBE_PORT}:3210' # LobeChat
|
||||
- '3000:3000' # Grafana
|
||||
- '4318:4318' # otel-collector HTTP
|
||||
- '4317:4317' # otel-collector gRPC
|
||||
command: tail -f /dev/null
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
postgresql:
|
||||
image: paradedb/paradedb:latest-pg17
|
||||
container_name: lobe-postgres
|
||||
ports:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- './data:/var/lib/postgresql/data'
|
||||
environment:
|
||||
- 'POSTGRES_DB=${LOBE_DB_NAME}'
|
||||
- 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}'
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U postgres']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-04-22T22-12-26Z
|
||||
container_name: lobe-minio
|
||||
network_mode: 'service:network-service'
|
||||
volumes:
|
||||
- './s3_data:/etc/minio/data'
|
||||
environment:
|
||||
- 'MINIO_API_CORS_ALLOW_ORIGIN=*'
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
minio server /etc/minio/data --address ':${MINIO_PORT}' --console-address ':9001' &
|
||||
MINIO_PID=\$!
|
||||
while ! curl -s http://localhost:${MINIO_PORT}/minio/health/live; do
|
||||
echo 'Waiting for MinIO to start...'
|
||||
sleep 1
|
||||
done
|
||||
sleep 5
|
||||
mc alias set myminio http://localhost:${MINIO_PORT} ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}
|
||||
echo 'Creating bucket ${MINIO_LOBE_BUCKET}'
|
||||
mc mb myminio/${MINIO_LOBE_BUCKET}
|
||||
wait \$MINIO_PID
|
||||
"
|
||||
|
||||
|
||||
# version lock ref: https://github.com/lobehub/lobe-chat/pull/7331
|
||||
casdoor:
|
||||
image: casbin/casdoor:v2.13.0
|
||||
container_name: lobe-casdoor
|
||||
entrypoint: /bin/sh -c './server --createDatabase=true'
|
||||
network_mode: 'service:network-service'
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
httpport: ${CASDOOR_PORT}
|
||||
RUNNING_IN_DOCKER: 'true'
|
||||
driverName: 'postgres'
|
||||
dataSourceName: 'user=postgres password=${POSTGRES_PASSWORD} host=postgresql port=5432 sslmode=disable dbname=casdoor'
|
||||
runmode: 'dev'
|
||||
volumes:
|
||||
- ./init_data.json:/init_data.json
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
searxng:
|
||||
image: searxng/searxng
|
||||
container_name: lobe-searxng
|
||||
volumes:
|
||||
- './searxng-settings.yml:/etc/searxng/settings.yml'
|
||||
environment:
|
||||
- 'SEARXNG_SETTINGS_FILE=/etc/searxng/settings.yml'
|
||||
restart: always
|
||||
networks:
|
||||
- lobe-network
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:12.2.0-17419259409
|
||||
container_name: lobe-grafana
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
|
||||
- GF_FEATURE_TOGGLES_ENABLE=traceqlEditor
|
||||
volumes:
|
||||
- grafana_data:/var/lib/grafana
|
||||
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards
|
||||
- ./grafana/datasources:/etc/grafana/provisioning/datasources
|
||||
depends_on:
|
||||
- tempo
|
||||
- prometheus
|
||||
|
||||
tempo:
|
||||
image: grafana/tempo:latest
|
||||
container_name: lobe-tempo
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
volumes:
|
||||
- ./tempo/tempo.yaml:/etc/tempo.yaml
|
||||
- tempo_data:/var/tempo
|
||||
command: ['-config.file=/etc/tempo.yaml']
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
container_name: lobe-prometheus
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
volumes:
|
||||
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus_data:/prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--web.enable-otlp-receiver'
|
||||
- '--web.enable-remote-write-receiver'
|
||||
- '--enable-feature=exemplar-storage'
|
||||
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector
|
||||
container_name: lobe-otel-collector
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
volumes:
|
||||
- ./otel-collector/collector-config.yaml:/etc/otelcol/config.yaml
|
||||
command: ['--config', '/etc/otelcol/config.yaml']
|
||||
depends_on:
|
||||
- tempo
|
||||
- prometheus
|
||||
|
||||
otel-tracing-test:
|
||||
profiles:
|
||||
- otel-test
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.9
|
||||
container_name: lobe-otel-tracing-test
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
environment:
|
||||
- ENDPOINT=127.0.0.1:4317
|
||||
|
||||
lobe:
|
||||
image: lobehub/lobehub
|
||||
container_name: lobehub
|
||||
network_mode: 'service:network-service'
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
network-service:
|
||||
condition: service_started
|
||||
minio:
|
||||
condition: service_started
|
||||
casdoor:
|
||||
condition: service_started
|
||||
|
||||
environment:
|
||||
- 'AUTH_SSO_PROVIDERS=casdoor'
|
||||
- 'KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ='
|
||||
- 'AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg'
|
||||
- 'DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgresql:5432/${LOBE_DB_NAME}'
|
||||
- 'S3_BUCKET=${MINIO_LOBE_BUCKET}'
|
||||
- 'S3_ENABLE_PATH_STYLE=1'
|
||||
- 'S3_ACCESS_KEY=${MINIO_ROOT_USER}'
|
||||
- 'S3_ACCESS_KEY_ID=${MINIO_ROOT_USER}'
|
||||
- 'S3_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}'
|
||||
- 'LLM_VISION_IMAGE_USE_BASE64=1'
|
||||
- 'S3_SET_ACL=0'
|
||||
- 'SEARXNG_URL=http://searxng:8080'
|
||||
- 'OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf'
|
||||
- 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics'
|
||||
- 'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf'
|
||||
- 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces'
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
/bin/node /app/startServer.js &
|
||||
LOBE_PID=\$!
|
||||
sleep 3
|
||||
if [ $(wget --timeout=5 --spider --server-response ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration 2>&1 | grep -c 'HTTP/1.1 200 OK') -eq 0 ]; then
|
||||
echo '⚠️Warning: Unable to fetch OIDC configuration from Casdoor'
|
||||
echo 'Request URL: ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration'
|
||||
echo 'Read more at: https://lobehub.com/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
echo '⚠️注意:无法从 Casdoor 获取 OIDC 配置'
|
||||
echo '请求 URL: ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration'
|
||||
echo '了解更多:https://lobehub.com/zh/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
else
|
||||
if ! wget -O - --timeout=5 ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration 2>&1 | grep 'issuer' | grep ${AUTH_CASDOOR_ISSUER}; then
|
||||
printf '❌Error: The Auth issuer is conflict, Issuer in OIDC configuration is: %s' \$(wget -O - --timeout=5 ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration 2>&1 | grep -E 'issuer.*' | awk -F '\"' '{print \$4}')
|
||||
echo ' , but the issuer in .env file is: ${AUTH_CASDOOR_ISSUER} '
|
||||
echo 'Request URL: ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration'
|
||||
echo 'Read more at: https://lobehub.com/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
printf '❌错误:Auth 的 issuer 冲突,OIDC 配置中的 issuer 是:%s' \$(wget -O - --timeout=5 ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration 2>&1 | grep -E 'issuer.*' | awk -F '\"' '{print \$4}')
|
||||
echo ' , 但 .env 文件中的 issuer 是:${AUTH_CASDOOR_ISSUER} '
|
||||
echo '请求 URL: ${AUTH_CASDOOR_ISSUER}/.well-known/openid-configuration'
|
||||
echo '了解更多:https://lobehub.com/zh/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
fi
|
||||
fi
|
||||
if [ $(wget --timeout=5 --spider --server-response ${S3_ENDPOINT}/minio/health/live 2>&1 | grep -c 'HTTP/1.1 200 OK') -eq 0 ]; then
|
||||
echo '⚠️Warning: Unable to fetch MinIO health status'
|
||||
echo 'Request URL: ${S3_ENDPOINT}/minio/health/live'
|
||||
echo 'Read more at: https://lobehub.com/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
echo '⚠️注意:无法获取 MinIO 健康状态'
|
||||
echo '请求 URL: ${S3_ENDPOINT}/minio/health/live'
|
||||
echo '了解更多:https://lobehub.com/zh/docs/self-hosting/server-database/docker-compose#necessary-configuration'
|
||||
echo ''
|
||||
fi
|
||||
wait \$LOBE_PID
|
||||
"
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
driver: local
|
||||
s3_data:
|
||||
driver: local
|
||||
grafana_data:
|
||||
driver: local
|
||||
tempo_data:
|
||||
driver: local
|
||||
prometheus_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
lobe-network:
|
||||
driver: bridge
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
type: prometheus
|
||||
uid: prometheus
|
||||
access: proxy
|
||||
orgId: 1
|
||||
url: http://127.0.0.1:9090
|
||||
basicAuth: false
|
||||
isDefault: false
|
||||
version: 1
|
||||
editable: false
|
||||
jsonData:
|
||||
httpMethod: GET
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Tempo
|
||||
type: tempo
|
||||
access: proxy
|
||||
orgId: 1
|
||||
url: http://127.0.0.1:3200
|
||||
basicAuth: false
|
||||
isDefault: true
|
||||
version: 1
|
||||
editable: false
|
||||
apiVersion: 1
|
||||
uid: tempo
|
||||
jsonData:
|
||||
httpMethod: GET
|
||||
serviceMap:
|
||||
datasourceUid: prometheus
|
||||
streamingEnabled:
|
||||
search: true
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
extensions:
|
||||
health_check:
|
||||
endpoint: 127.0.0.1:13133
|
||||
|
||||
receivers:
|
||||
prometheus:
|
||||
config:
|
||||
scrape_configs:
|
||||
- job_name: otel-collector-metrics
|
||||
scrape_interval: 10s
|
||||
static_configs:
|
||||
- targets: ['127.0.0.1:8888']
|
||||
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
exporters:
|
||||
prometheusremotewrite:
|
||||
endpoint: http://127.0.0.1:9090/api/v1/write
|
||||
tls:
|
||||
insecure: true
|
||||
|
||||
otlp:
|
||||
endpoint: 127.0.0.1:14317
|
||||
tls:
|
||||
insecure: true
|
||||
|
||||
debug:
|
||||
verbosity: detailed
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers: [prometheus]
|
||||
exporters: [prometheusremotewrite]
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
exporters: [otlp]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
exporters: [debug]
|
||||
@@ -0,0 +1,11 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'prometheus'
|
||||
static_configs:
|
||||
- targets: ['127.0.0.1:9090']
|
||||
- job_name: 'tempo'
|
||||
static_configs:
|
||||
- targets: ['127.0.0.1:3200']
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
stream_over_http_enabled: true
|
||||
server:
|
||||
http_listen_port: 3200
|
||||
log_level: info
|
||||
|
||||
query_frontend:
|
||||
search:
|
||||
duration_slo: 5s
|
||||
throughput_bytes_slo: 1.073741824e+09
|
||||
metadata_slo:
|
||||
duration_slo: 5s
|
||||
throughput_bytes_slo: 1.073741824e+09
|
||||
trace_by_id:
|
||||
duration_slo: 5s
|
||||
|
||||
distributor:
|
||||
max_attribute_bytes: 10485760
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 127.0.0.1:14317
|
||||
http:
|
||||
endpoint: 127.0.0.1:14318
|
||||
|
||||
ingester:
|
||||
max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
|
||||
|
||||
compactor:
|
||||
compaction:
|
||||
block_retention: 1h # overall Tempo trace retention. set for demo purposes
|
||||
|
||||
metrics_generator:
|
||||
registry:
|
||||
external_labels:
|
||||
source: tempo
|
||||
cluster: docker-compose
|
||||
storage:
|
||||
path: /var/tempo/generator/wal
|
||||
remote_write:
|
||||
- url: http://127.0.0.1:9090/api/v1/write
|
||||
send_exemplars: true
|
||||
traces_storage:
|
||||
path: /var/tempo/generator/traces
|
||||
|
||||
storage:
|
||||
trace:
|
||||
backend: local # backend configuration to use
|
||||
wal:
|
||||
path: /var/tempo/wal # where to store the wal locally
|
||||
local:
|
||||
path: /var/tempo/blocks
|
||||
|
||||
overrides:
|
||||
defaults:
|
||||
metrics_generator:
|
||||
processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator
|
||||
generate_native_histograms: both
|
||||
@@ -0,0 +1,772 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==================
|
||||
# == Env settings ==
|
||||
# ==================
|
||||
|
||||
# check operating system
|
||||
# ref: https://github.com/lobehub/lobe-chat/pull/5247
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS
|
||||
SED_INPLACE_ARGS=('-i' '')
|
||||
else
|
||||
# not macOS
|
||||
SED_INPLACE_ARGS=('-i')
|
||||
fi
|
||||
|
||||
# ======================
|
||||
# == Process the args ==
|
||||
# ======================
|
||||
|
||||
# 1. Default values of arguments
|
||||
|
||||
# Arg: -l or --lang
|
||||
# Determine the language to show, default is en
|
||||
|
||||
# Arg: --url
|
||||
# Determine the source URL to download files
|
||||
SOURCE_URL="https://raw.githubusercontent.com/lobehub/lobe-chat/main"
|
||||
|
||||
# Arg: --host
|
||||
# Determine the server host
|
||||
HOST=""
|
||||
|
||||
# 2. Parse script arguments
|
||||
while getopts "l:-:" opt; do
|
||||
case $opt in
|
||||
l)
|
||||
LANGUAGE=$OPTARG
|
||||
;;
|
||||
-)
|
||||
case "${OPTARG}" in
|
||||
lang)
|
||||
LANGUAGE="${!OPTIND}"
|
||||
OPTIND=$(($OPTIND + 1))
|
||||
;;
|
||||
url)
|
||||
SOURCE_URL="${!OPTIND}"
|
||||
OPTIND=$(($OPTIND + 1))
|
||||
;;
|
||||
host)
|
||||
HOST="${!OPTIND}"
|
||||
OPTIND=$(($OPTIND + 1))
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [-l language|--lang language] [--url source] [--host serverhost]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [-l language|--lang language] [--url source]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
#######################
|
||||
## Helper Functions ##
|
||||
#######################
|
||||
|
||||
# Supported languages and messages
|
||||
# Arg: -l --lang
|
||||
# If the language is not supported, default to English
|
||||
# Function to show messages
|
||||
show_message() {
|
||||
local key="$1"
|
||||
case $key in
|
||||
choose_language)
|
||||
echo "Please choose a language / 请选择语言:"
|
||||
echo "(0) English"
|
||||
echo "(1) 简体中文"
|
||||
;;
|
||||
downloading)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "正在下载文件..."
|
||||
;;
|
||||
*)
|
||||
echo "Downloading files..."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
extracted_success)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo " 解压成功到目录:"
|
||||
;;
|
||||
*)
|
||||
echo " extracted successfully to directory: "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
extracted_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo " 解压失败。"
|
||||
;;
|
||||
*)
|
||||
echo " extraction failed."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
file_not_exists)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo " 不存在。"
|
||||
;;
|
||||
*)
|
||||
echo " does not exist."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
security_secrect_regenerate)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "重新生成安全密钥..."
|
||||
;;
|
||||
*)
|
||||
echo "Regenerate security secrets..."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
security_secrect_regenerate_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "无法重新生成安全密钥:"
|
||||
;;
|
||||
*)
|
||||
echo "Failed to regenerate security secrets: "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
host_regenerate)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "✔️ 已更新部署模式配置"
|
||||
;;
|
||||
*)
|
||||
echo "✔️ Updated deployment mode configuration"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
host_regenerate_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "无法重新生成服务器域名:"
|
||||
;;
|
||||
*)
|
||||
echo "Failed to regenerate server host: "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
security_secrect_regenerate_report)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "安全密钥生成结果如下:"
|
||||
;;
|
||||
*)
|
||||
echo "Security secret generation results are as follows:"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_download_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "$2 下载失败,请检查网络连接。"
|
||||
;;
|
||||
*)
|
||||
echo "$2 Download failed, please check the network connection."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_already_installed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "检测到您已经运行过 LobeHub,本安装程序只能完成初始化配置,并不能重复安装。如果你需要重新安装,请删除 data 和 s3_data 文件夹。"
|
||||
;;
|
||||
*)
|
||||
echo "It is detected that you have run LobeHub. This installation program can only complete the initialization configuration and cannot be reinstalled. If you need to reinstall, please delete the data and s3_data folders."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_run_command)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "您已经完成了所有配置。请运行以下命令启动 LobeHub 尝试启动:"
|
||||
;;
|
||||
*)
|
||||
echo "You have completed all configurations. Please run this command to start LobeHub:"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_if_want_searxng_logs)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "在上述命令中已屏蔽 SearXNG 的日志。如果你想查看 SearXNG 的日志,可以去除选项: --no-attach searxng 或运行以下命令:"
|
||||
;;
|
||||
*)
|
||||
echo "In the above command, the logs of SearXNG are blocked by default. If you want to view the logs of SearXNG, you can remove the option: --no-attach searxng or run the following command:"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_if_run_normally)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "如果一切运行正常,你可以使用以下指令在 daemon 模式下启动 LobeHub:"
|
||||
;;
|
||||
*)
|
||||
echo "If everything runs normally, you can use the following command to start LobeHub in daemon mode:"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_regen_jwks)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "在完成部署测试后,请前往 https://lobehub.com/zh/docs/self-hosting/environment-variables/auth#jwks_key 生成新的 JWKS_KEY 并替换 .env 中的值,以确保安全性。"
|
||||
;;
|
||||
*)
|
||||
echo "After completing the deployment test, please go to https://lobehub.com/docs/self-hosting/environment-variables/auth#jwks_key to generate a new JWKS_KEY and replace the value in .env to ensure security."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_disable_registration)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "如需限制用户注册,可在 .env 中配置:"
|
||||
echo " - 使用 SSO 登录时,设置 AUTH_DISABLE_EMAIL_PASSWORD=1 可禁用邮箱密码注册"
|
||||
echo " - 使用邮箱密码登录时,设置 AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com 可限制允许登录的邮箱"
|
||||
;;
|
||||
*)
|
||||
echo "To restrict user registration, configure in .env:"
|
||||
echo " - For SSO login: set AUTH_DISABLE_EMAIL_PASSWORD=1 to disable email/password registration"
|
||||
echo " - For email/password login: set AUTH_ALLOWED_EMAILS=user1@example.com,user2@example.com to allow specific emails"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_show_documentation)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "完整的环境变量在'.env'中可以在文档中找到:"
|
||||
;;
|
||||
*)
|
||||
echo "Full environment variables in the '.env' can be found at the documentation on "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_show_documentation_url)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "https://lobehub.com/zh/docs/self-hosting/environment-variables"
|
||||
;;
|
||||
*)
|
||||
echo "https://lobehub.com/docs/self-hosting/environment-variables"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_no_executable)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "没有找到,请先安装。"
|
||||
;;
|
||||
*)
|
||||
echo "not found, please install it first."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_allow_ports)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "请确保服务器以下端口未被占用且能被访问:3210, 9000, 9001"
|
||||
;;
|
||||
*)
|
||||
echo "Please make sure the following ports on the server are not occupied and can be accessed: 3210, 9000, 9001"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_auto_detected)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "已自动识别"
|
||||
;;
|
||||
*)
|
||||
echo "Auto-detected"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_private_ip_detected)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "注意,当前识别到内网 IP,如果需要外部访问,请替换为公网 IP 地址"
|
||||
;;
|
||||
*)
|
||||
echo "Note that the current internal IP is detected. If you need external access, please replace it with the public IP address."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_add_reverse_proxy)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "请在你的反向代理中完成域名到端口的映射:"
|
||||
;;
|
||||
*)
|
||||
echo "Please complete the mapping of domain to port in your reverse proxy:"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_no_docker_permission)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "WARN: 看起来当前用户没有 Docker 权限。"
|
||||
echo "使用 'sudo usermod -aG docker $USER' 为用户分配 Docker 权限(可能需要重新启动 shell)。"
|
||||
;;
|
||||
*)
|
||||
echo "WARN: It look like the current user does not have Docker permissions."
|
||||
echo "Use 'sudo usermod -aG docker $USER' to assign Docker permissions to the user (may require restarting shell)."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
tips_init_database_failed)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "无法初始化数据库"
|
||||
;;
|
||||
*)
|
||||
echo "Failed to initialize the database."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_regenerate_secrets)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "是否要重新生成安全密钥?"
|
||||
;;
|
||||
*)
|
||||
echo "Do you want to regenerate security secrets?"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_deploy_mode)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "请选择部署模式:"
|
||||
echo "(0) 域名模式(访问时无需指明端口),需要使用反向代理服务 LobeHub, RustFS,并分别分配一个域名;"
|
||||
echo "(1) 端口模式(访问时需要指明端口,如使用IP访问,或域名+端口访问),需要放开指定端口;"
|
||||
echo "(2) 本地模式(仅供本地测试使用)"
|
||||
echo "如果你对这些内容疑惑,可以先选择使用本地模式进行部署,稍后根据文档指引再进行修改。"
|
||||
echo "https://lobehub.com/docs/self-hosting/server-database/docker-compose"
|
||||
;;
|
||||
*)
|
||||
echo "Please select the deployment mode:"
|
||||
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;"
|
||||
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;"
|
||||
echo "(2) Local mode (for local testing only)"
|
||||
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."
|
||||
echo "https://lobehub.com/docs/self-hosting/server-database/docker-compose"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_host)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo " 部署IP/域名"
|
||||
;;
|
||||
*)
|
||||
echo " Deploy IP/Domain"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_domain)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "服务的域名(例如 $2 ,不要包含协议前缀):"
|
||||
;;
|
||||
*)
|
||||
echo "The domain of the service (e.g. $2, do not include the protocol prefix):"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_protocol)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "域名是否使用 https 协议? (所有服务需要使用同一协议)"
|
||||
;;
|
||||
*)
|
||||
echo "Does the domain use the https protocol? (All services need to use the same protocol)"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
ask_init_database)
|
||||
case $LANGUAGE in
|
||||
zh_CN)
|
||||
echo "是否初始化数据库?"
|
||||
;;
|
||||
*)
|
||||
echo "Do you want to initialize the database?"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to download files
|
||||
download_file() {
|
||||
wget "$1" -O "$2"
|
||||
# If run failed, exit
|
||||
if [ $? -ne 0 ]; then
|
||||
show_message "tips_download_failed" "$2"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
print_centered() {
|
||||
local text="$1" # Get input texts
|
||||
local color="${2:-reset}" # Get color, default to reset
|
||||
local term_width=$(tput cols) # Get terminal width
|
||||
local text_length=${#text} # Get text length
|
||||
local padding=$(((term_width - text_length) / 2)) # Get padding
|
||||
|
||||
# Get color code (compatible with bash 3.x)
|
||||
local color_code=""
|
||||
local reset_code="\e[0m"
|
||||
case "$color" in
|
||||
black) color_code="\e[30m" ;;
|
||||
red) color_code="\e[31m" ;;
|
||||
green) color_code="\e[32m" ;;
|
||||
yellow) color_code="\e[33m" ;;
|
||||
blue) color_code="\e[34m" ;;
|
||||
magenta) color_code="\e[35m" ;;
|
||||
cyan) color_code="\e[36m" ;;
|
||||
white) color_code="\e[37m" ;;
|
||||
reset) color_code="\e[0m" ;;
|
||||
*)
|
||||
echo "Invalid color specified. Available colors: black red green yellow blue magenta cyan white reset"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Print the text with padding
|
||||
printf "%*s${color_code}%s${reset_code}\n" $padding "" "$text"
|
||||
}
|
||||
|
||||
# Usage:
|
||||
# ```sh
|
||||
# ask "prompt" "default" "description"
|
||||
# echo $ask_result
|
||||
# ```
|
||||
# "prompt" ["description" "default"]:
|
||||
ask() {
|
||||
local prompt="$1"
|
||||
local default="$2"
|
||||
local description="$3"
|
||||
# Add a space after the description if it is not empty
|
||||
if [ -n "$description" ]; then
|
||||
description="$description "
|
||||
fi
|
||||
local result
|
||||
|
||||
if [ -n "$default" ]; then
|
||||
read -p "$prompt [${description}${default}]: " result
|
||||
result=${result:-$default}
|
||||
else
|
||||
read -p "$prompt: " result
|
||||
fi
|
||||
# trim and assign to global variable
|
||||
ask_result=$(echo "$result" | xargs)
|
||||
}
|
||||
|
||||
####################
|
||||
## Main Process ##
|
||||
####################
|
||||
|
||||
# ===============
|
||||
# == Variables ==
|
||||
# ===============
|
||||
# File list
|
||||
SUB_DIR="docker-compose/deploy"
|
||||
FILES=(
|
||||
"$SUB_DIR/docker-compose.yml"
|
||||
"$SUB_DIR/searxng-settings.yml"
|
||||
"$SUB_DIR/bucket.config.json"
|
||||
)
|
||||
ENV_EXAMPLES=(
|
||||
"$SUB_DIR/.env.zh-CN.example"
|
||||
"$SUB_DIR/.env.example"
|
||||
)
|
||||
# Default values
|
||||
RUSTFS_SECRET_KEY="YOUR_RUSTFS_PASSWORD"
|
||||
RUSTFS_HOST="localhost:9000"
|
||||
PROTOCOL="http"
|
||||
|
||||
# If no language is specified, ask the user to choose
|
||||
if [ -z "$LANGUAGE" ]; then
|
||||
show_message "choose_language"
|
||||
ask "(0,1)" "0"
|
||||
case $ask_result in
|
||||
0)
|
||||
LANGUAGE="en_US"
|
||||
;;
|
||||
1)
|
||||
LANGUAGE="zh_CN"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid language: $ask_result"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
section_download_files(){
|
||||
# Download files asynchronously
|
||||
if ! command -v wget &> /dev/null ; then
|
||||
echo "wget" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_file "$SOURCE_URL/${FILES[0]}" "docker-compose.yml"
|
||||
download_file "$SOURCE_URL/${FILES[1]}" "searxng-settings.yml"
|
||||
download_file "$SOURCE_URL/${FILES[2]}" "bucket.config.json"
|
||||
# Download .env.example with the specified language
|
||||
if [ "$LANGUAGE" = "zh_CN" ]; then
|
||||
download_file "$SOURCE_URL/${ENV_EXAMPLES[0]}" ".env"
|
||||
else
|
||||
download_file "$SOURCE_URL/${ENV_EXAMPLES[1]}" ".env"
|
||||
fi
|
||||
}
|
||||
# If the folder `data` or `s3_data` exists, warn the user
|
||||
if [ -d "data" ] || [ -d "s3_data" ]; then
|
||||
show_message "tips_already_installed"
|
||||
exit 0
|
||||
else
|
||||
section_download_files
|
||||
fi
|
||||
|
||||
section_configurate_host() {
|
||||
DEPLOY_MODE=$ask_result
|
||||
show_message "host_regenerate"
|
||||
# If run in local mode, skip this step
|
||||
if [[ "$DEPLOY_MODE" == "2" ]]; then
|
||||
HOST="localhost:3210"
|
||||
LOBE_HOST="$HOST"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Configurate protocol for domain
|
||||
if [[ "$DEPLOY_MODE" == "0" ]]; then
|
||||
# Ask if enable https
|
||||
echo $(show_message "ask_protocol")
|
||||
ask "(y/n)" "y"
|
||||
if [[ "$ask_result" == "y" ]]; then
|
||||
PROTOCOL="https"
|
||||
# Replace all http with https
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#http://#https://#" .env
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if sed is installed
|
||||
if ! command -v sed "${SED_INPLACE_ARGS[@]}" &> /dev/null ; then
|
||||
echo "sed" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If user not specify host, try to get the server ip
|
||||
if [ -z "$HOST" ]; then
|
||||
HOST=$(hostname -I | awk '{print $1}')
|
||||
# If the host is a private ip and the deploy mode is port mode
|
||||
if [[ "$DEPLOY_MODE" == "1" ]] && ([[ "$HOST" == "192.168."* ]] || [[ "$HOST" == "172."* ]] || [[ "$HOST" == "10."* ]]); then
|
||||
echo $(show_message "tips_private_ip_detected")
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
case $DEPLOY_MODE in
|
||||
0)
|
||||
DEPLOY_MODE="domain"
|
||||
echo "LobeHub" $(show_message "ask_domain" "example.com")
|
||||
ask "(example.com)"
|
||||
LOBE_HOST="$ask_result"
|
||||
# If user use domain mode, ask for the domain of RustFS
|
||||
echo "RustFS S3 API" $(show_message "ask_domain" "s3.example.com")
|
||||
ask "(s3.example.com)"
|
||||
RUSTFS_HOST="$ask_result"
|
||||
;;
|
||||
1)
|
||||
DEPLOY_MODE="ip"
|
||||
ask $(printf "%s%s" "LobeHub" $(show_message "ask_host")) "$HOST" $(printf "%s" $(show_message "tips_auto_detected"))
|
||||
LOBE_HOST="$ask_result"
|
||||
# If user use ip mode, use ask_result as the host
|
||||
HOST="$ask_result"
|
||||
# If user use ip mode, append the port to the host
|
||||
LOBE_HOST="${HOST}:3210"
|
||||
RUSTFS_HOST="${HOST}:9000"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid deploy mode: $ask_result"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# lobe host
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#^APP_URL=.*#APP_URL=$PROTOCOL://$LOBE_HOST#" .env
|
||||
# s3 related
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#^S3_ENDPOINT=.*#S3_ENDPOINT=$PROTOCOL://$RUSTFS_HOST#" .env
|
||||
|
||||
|
||||
# Check if env modified success
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "host_regenerate_failed") "$HOST in \`.env\`"
|
||||
fi
|
||||
}
|
||||
show_message "ask_deploy_mode"
|
||||
ask "(0,1,2)" "2"
|
||||
if [[ "$ask_result" == "0" ]] || [[ "$ask_result" == "1" ]] || [[ "$ask_result" == "2" ]]; then
|
||||
section_configurate_host
|
||||
else
|
||||
echo "Invalid deploy mode: $ask_result, please select 0, 1 or 2."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==========================
|
||||
# === Regenerate Secrets ===
|
||||
# ==========================
|
||||
section_regenerate_secrets() {
|
||||
# Check if openssl is installed
|
||||
if ! command -v openssl &> /dev/null ; then
|
||||
echo "openssl" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v tr &> /dev/null ; then
|
||||
echo "tr" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v fold &> /dev/null ; then
|
||||
echo "fold" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v head &> /dev/null ; then
|
||||
echo "head" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
|
||||
generate_key() {
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Usage: generate_key <length>"
|
||||
return 1
|
||||
fi
|
||||
echo $(openssl rand -hex $1 | tr -d '\n' | fold -w $1 | head -n 1)
|
||||
}
|
||||
|
||||
if ! command -v sed &> /dev/null ; then
|
||||
echo "sed" $(show_message "tips_no_executable")
|
||||
exit 1
|
||||
fi
|
||||
echo $(show_message "security_secrect_regenerate")
|
||||
|
||||
# Generate RUSTFS S3 User Password
|
||||
RUSTFS_SECRET_KEY=$(generate_key 8)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "RUSTFS_SECRET_KEY"
|
||||
RUSTFS_SECRET_KEY="YOUR_RUSTFS_PASSWORD"
|
||||
else
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#^RUSTFS_SECRET_KEY=.*#RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY}#" .env
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "RUSTFS_SECRET_KEY in \`.env\`"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generate KEY_VAULTS_SECRET (base64 encoded 32 bytes)
|
||||
KEY_VAULTS_SECRET=$(openssl rand -base64 32)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "KEY_VAULTS_SECRET"
|
||||
else
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#^KEY_VAULTS_SECRET=.*#KEY_VAULTS_SECRET=${KEY_VAULTS_SECRET}#" .env
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "KEY_VAULTS_SECRET in \`.env\`"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generate AUTH_SECRET (base64 encoded 32 bytes)
|
||||
AUTH_SECRET=$(openssl rand -base64 32)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "AUTH_SECRET"
|
||||
else
|
||||
sed "${SED_INPLACE_ARGS[@]}" "s#^AUTH_SECRET=.*#AUTH_SECRET=${AUTH_SECRET}#" .env
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "security_secrect_regenerate_failed") "AUTH_SECRET in \`.env\`"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
show_message "ask_regenerate_secrets"
|
||||
ask "(y/n)" "y"
|
||||
if [[ "$ask_result" == "y" ]]; then
|
||||
section_regenerate_secrets
|
||||
fi
|
||||
|
||||
section_init_database() {
|
||||
if ! command -v docker &> /dev/null ; then
|
||||
echo "docker" $(show_message "tips_no_executable")
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! docker compose &> /dev/null ; then
|
||||
echo "docker compose" $(show_message "tips_no_executable")
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if user has permissions to run Docker by trying to get the status of Docker (docker status).
|
||||
# If this fails, the user probably does not have permissions for Docker.
|
||||
# ref: https://github.com/paperless-ngx/paperless-ngx/blob/89e5c08a1fe4ca0b7641ae8fbd5554502199ae40/install-paperless-ngx.sh#L64-L72
|
||||
if ! docker stats --no-stream &> /dev/null ; then
|
||||
echo $(show_message "tips_no_docker_permission")
|
||||
return 1
|
||||
fi
|
||||
|
||||
docker compose pull
|
||||
docker compose up --detach postgresql
|
||||
# hopefully enough time for even the slower systems
|
||||
sleep 15
|
||||
docker compose stop
|
||||
}
|
||||
|
||||
show_message "ask_init_database"
|
||||
ask "(y/n)" "y"
|
||||
if [[ "$ask_result" == "y" ]]; then
|
||||
# If return 1 means failed
|
||||
section_init_database
|
||||
if [ $? -ne 0 ]; then
|
||||
echo $(show_message "tips_init_database_failed")
|
||||
fi
|
||||
else
|
||||
show_message "tips_init_database_failed"
|
||||
fi
|
||||
|
||||
section_display_configurated_report() {
|
||||
# Display configuration reports
|
||||
echo $(show_message "security_secrect_regenerate_report")
|
||||
|
||||
echo -e "LobeHub: \n - URL: $PROTOCOL://$LOBE_HOST"
|
||||
echo -e "RustFS: \n - URL: $PROTOCOL://$RUSTFS_HOST \n - Username: admin\n - Password: ${RUSTFS_SECRET_KEY}\n"
|
||||
|
||||
# if user run in domain mode, diplay reverse proxy configuration
|
||||
if [[ "$DEPLOY_MODE" == "domain" ]]; then
|
||||
echo $(show_message "tips_add_reverse_proxy")
|
||||
printf "\n%s\t->\t%s\n" "$LOBE_HOST" "127.0.0.1:3210"
|
||||
printf "%s\t->\t%s\n" "$RUSTFS_HOST" "127.0.0.1:9000"
|
||||
fi
|
||||
|
||||
# Display final message
|
||||
|
||||
printf "\n%s\n\n" "$(show_message "tips_run_command")"
|
||||
print_centered "docker compose up --no-attach searxng" "green"
|
||||
printf "\n%s\n" "$(show_message "tips_if_run_normally")"
|
||||
printf "\n%s\n" "$(show_message "tips_regen_jwks")"
|
||||
printf "\n%s\n\n" "$(show_message "tips_disable_registration")"
|
||||
print_centered "docker compose up -d --no-attach searxng" "green"
|
||||
printf "\n%s\n" "$(show_message "tips_if_want_searxng_logs")"
|
||||
print_centered "docker compose logs -f searxng" "white"
|
||||
printf "\n%s\n" "$(show_message "tips_allow_ports")"
|
||||
printf "\n%s" "$(show_message "tips_show_documentation")"
|
||||
printf "%s\n" $(show_message "tips_show_documentation_url")
|
||||
}
|
||||
section_display_configurated_report
|
||||
Reference in New Issue
Block a user