Commit 27e24cfb authored by uuo's avatar uuo

chore: 增强配置安全并添加自动化部署脚本

- 移除硬编码的敏感信息,改为从环境变量读取
- 添加 JWT 密钥长度验证和必需环境变量检查
- 创建自动化部署脚本 start.sh 和密钥生成脚本 generate_secrets.py
- 统一 docker-compose 配置,支持环境变量注入
- 更新各服务的配置文件以支持外部化配置
parent 69a4019b
...@@ -7,17 +7,17 @@ services: ...@@ -7,17 +7,17 @@ services:
container_name: llm-filter-db container_name: llm-filter-db
restart: always restart: always
environment: environment:
POSTGRES_USER: admin POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: llm_filter_db POSTGRES_DB: ${DB_NAME}
ports: ports:
- "5433:5432" - "${POSTGRES_PORT_EXTERNAL:-5433}:5432"
volumes: volumes:
- postgres_data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
networks: networks:
- llm-network - llm-network
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin -d llm_filter_db"] test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
...@@ -30,14 +30,18 @@ services: ...@@ -30,14 +30,18 @@ services:
container_name: llm-filter-auth container_name: llm-filter-auth
restart: always restart: always
ports: ports:
- "8081:8081" - "${AUTH_SERVICE_PORT:-8081}:8081"
environment: environment:
- DB_HOST=postgres - DB_HOST=${DB_HOST}
- DB_USER=admin - DB_PORT=${DB_PORT}
- DB_PASSWORD=password - DB_USER=${DB_USER}
- DB_NAME=llm_filter_db - DB_PASSWORD=${DB_PASSWORD}
- DB_PORT=5432 - DB_NAME=${DB_NAME}
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- ADMIN_USERNAME=${ADMIN_USERNAME}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- ADMIN_EMAIL=${ADMIN_EMAIL}
- TZ=${TZ}
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
...@@ -52,14 +56,23 @@ services: ...@@ -52,14 +56,23 @@ services:
container_name: llm-filter-edu container_name: llm-filter-edu
restart: always restart: always
ports: ports:
- "8082:8082" - "${EDU_SERVICE_PORT:-8082}:8082"
environment: environment:
- DB_HOST=postgres - DB_HOST=${DB_HOST}
- DB_USER=admin - DB_PORT=${DB_PORT}
- DB_PASSWORD=password - DB_USER=${DB_USER}
- DB_NAME=llm_filter_db - DB_PASSWORD=${DB_PASSWORD}
- DB_PORT=5432 - DB_NAME=${DB_NAME}
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- SERVER_PORT=${SERVER_PORT}
- JPA_DDL_AUTO=${JPA_DDL_AUTO}
- JPA_SHOW_SQL=${JPA_SHOW_SQL}
- JPA_FORMAT_SQL=${JPA_FORMAT_SQL}
- JPA_DIALECT=${JPA_DIALECT}
- LOGGING_LEVEL=${LOGGING_LEVEL}
- SPRING_REDIS_HOST=${REDIS_HOST}
- SPRING_REDIS_PORT=${REDIS_PORT}
- TZ=${TZ}
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
...@@ -76,22 +89,35 @@ services: ...@@ -76,22 +89,35 @@ services:
# 生产环境不需要 --reload # 生产环境不需要 --reload
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips '*' command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips '*'
ports: ports:
- "8000:8000" - "${LLM_SERVICE_PORT:-8000}:8000"
# 生产环境移除代码挂载,使用镜像内的代码 # 生产环境移除代码挂载,使用镜像内的代码
volumes: volumes:
- ./scripts:/app/scripts - ./scripts:/app/scripts
environment: environment:
- MONGODB_URL=mongodb://mongo:27017 - MONGODB_URL=${MONGODB_URL}
- DB_NAME=llm_filter_db - DB_NAME=${DB_NAME}
- SECRET_KEY=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - SECRET_KEY=${JWT_SECRET}
- ALGORITHM=HS256 - ALGORITHM=${ALGORITHM}
- ACCESS_TOKEN_EXPIRE_MINUTES=30 - ACCESS_TOKEN_EXPIRE_MINUTES=${ACCESS_TOKEN_EXPIRE_MINUTES}
- TERM_START_DATE=2025-09-01 - TERM_START_DATE=${TERM_START_DATE}
- OLLAMA_BASE_URL=http://192.168.6.6:11434/ - OLLAMA_BASE_URL=${OLLAMA_BASE_URL}
- OLLAMA_MODEL=deepseek-r1:14b - OLLAMA_MODEL=${OLLAMA_MODEL}
# Dify Configuration # Dify Configuration
- DIFY_API_URL=http://192.168.6.6/v1 - DIFY_API_URL=${DIFY_API_URL}
- DIFY_API_KEY=app-lkK33EQOVXXrjD9x3SKbItr7 - DIFY_API_KEY=${DIFY_API_KEY}
- DIFY_RESPONSE_MODE=${DIFY_RESPONSE_MODE}
- DIFY_MESSAGE_ENDPOINT=${DIFY_MESSAGE_ENDPOINT}
# Redis Configuration
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
- REDIS_DB=${REDIS_DB}
- REDIS_PASSWORD=${REDIS_PASSWORD}
# App Configuration
- APP_BASE_URL=${APP_BASE_URL}
- API_V1_STR=${API_V1_STR}
- APP_MODE=${APP_MODE}
- CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS}
- TZ=${TZ}
depends_on: depends_on:
- mongo - mongo
networks: networks:
...@@ -107,14 +133,21 @@ services: ...@@ -107,14 +133,21 @@ services:
# 生产环境不需要 --reload # 生产环境不需要 --reload
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips '*' command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips '*'
ports: ports:
- "8003:8000" - "${SECURITY_SERVICE_PORT:-8003}:8000"
# 生产环境移除代码挂载 # 生产环境移除代码挂载
environment: environment:
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- DIFY_API_URL=http://192.168.6.6/v1 - ALGORITHM=${ALGORITHM}
- DIFY_API_KEY=app-ggTb0oC9WXQQm2r7KrvVUS6v - DIFY_API_URL=${DIFY_API_URL}
- MONGODB_URL=mongodb://mongo:27017 - DIFY_API_KEY=${DIFY_API_KEY}
- MONGODB_DB_NAME=security_service_db - DIFY_RESPONSE_MODE=${DIFY_RESPONSE_MODE}
- MONGODB_URL=${MONGODB_URL}
- MONGODB_DB_NAME=${MONGODB_DB_NAME}
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
- REDIS_DB=${REDIS_DB}
- REDIS_PASSWORD=${REDIS_PASSWORD}
- TZ=${TZ}
networks: networks:
- llm-network - llm-network
...@@ -124,7 +157,7 @@ services: ...@@ -124,7 +157,7 @@ services:
container_name: llm-filter-mongo container_name: llm-filter-mongo
restart: always restart: always
ports: ports:
- "27017:27017" - "${MONGODB_PORT_EXTERNAL:-27017}:27017"
volumes: volumes:
- mongo_data:/data/db - mongo_data:/data/db
networks: networks:
...@@ -136,9 +169,11 @@ services: ...@@ -136,9 +169,11 @@ services:
container_name: llm-filter-gateway container_name: llm-filter-gateway
restart: always restart: always
ports: ports:
- "8080:80" - "${GATEWAY_PORT:-8080}:80"
volumes: volumes:
- ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro - ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro
environment:
- TZ=${TZ}
depends_on: depends_on:
- auth-service - auth-service
- edu-service - edu-service
......
...@@ -6,11 +6,11 @@ services: ...@@ -6,11 +6,11 @@ services:
image: postgres:15-alpine image: postgres:15-alpine
container_name: llm-filter-db container_name: llm-filter-db
environment: environment:
POSTGRES_USER: admin POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: llm_filter_db POSTGRES_DB: ${DB_NAME}
ports: ports:
- "5433:5432" - "${POSTGRES_PORT_EXTERNAL:-5433}:5432"
volumes: volumes:
- postgres_data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
networks: networks:
...@@ -20,10 +20,13 @@ services: ...@@ -20,10 +20,13 @@ services:
redis: redis:
image: redis:7-alpine image: redis:7-alpine
container_name: llm-filter-redis container_name: llm-filter-redis
command: redis-server --requirepass ${REDIS_PASSWORD}
ports: ports:
- "6379:6379" - "${REDIS_PORT_EXTERNAL:-6379}:6379"
volumes: volumes:
- redis_data:/data - redis_data:/data
environment:
- TZ=${TZ}
networks: networks:
- llm-network - llm-network
...@@ -34,36 +37,47 @@ services: ...@@ -34,36 +37,47 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: llm-filter-auth container_name: llm-filter-auth
ports: ports:
- "8081:8081" - "${AUTH_SERVICE_PORT:-8081}:8081"
environment: environment:
- DB_HOST=postgres - DB_HOST=${DB_HOST}
- DB_USER=admin - DB_PORT=${DB_PORT}
- DB_PASSWORD=password - DB_USER=${DB_USER}
- DB_NAME=llm_filter_db - DB_PASSWORD=${DB_PASSWORD}
- DB_PORT=5432 - DB_NAME=${DB_NAME}
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- ADMIN_USERNAME=${ADMIN_USERNAME}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- ADMIN_EMAIL=${ADMIN_EMAIL}
- TZ=${TZ}
depends_on: depends_on:
- postgres - postgres
networks: networks:
- llm-network - llm-network
# 教务核心服务 (Go) # 教务核心服务
edu-service: edu-service:
build: build:
context: ./microservices/edu-service context: ./microservices/edu-service
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: llm-filter-edu container_name: llm-filter-edu
ports: ports:
- "8082:8082" - "${EDU_SERVICE_PORT:-8082}:8082"
environment: environment:
- DB_HOST=postgres - DB_HOST=${DB_HOST}
- DB_USER=admin - DB_PORT=${DB_PORT}
- DB_PASSWORD=password - DB_USER=${DB_USER}
- DB_NAME=llm_filter_db - DB_PASSWORD=${DB_PASSWORD}
- DB_PORT=5432 - DB_NAME=${DB_NAME}
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- SPRING_REDIS_HOST=redis - SERVER_PORT=${SERVER_PORT}
- SPRING_REDIS_PORT=6379 - JPA_DDL_AUTO=${JPA_DDL_AUTO}
- JPA_SHOW_SQL=${JPA_SHOW_SQL}
- JPA_FORMAT_SQL=${JPA_FORMAT_SQL}
- JPA_DIALECT=${JPA_DIALECT}
- LOGGING_LEVEL=${LOGGING_LEVEL}
- SPRING_REDIS_HOST=${REDIS_HOST}
- SPRING_REDIS_PORT=${REDIS_PORT}
- TZ=${TZ}
depends_on: depends_on:
- postgres - postgres
- redis - redis
...@@ -78,25 +92,35 @@ services: ...@@ -78,25 +92,35 @@ services:
container_name: llm-filter-llm container_name: llm-filter-llm
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --proxy-headers --forwarded-allow-ips '*' command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --proxy-headers --forwarded-allow-ips '*'
ports: ports:
- "8000:8000" - "${LLM_SERVICE_PORT:-8000}:8000"
volumes: volumes:
- ./microservices/llm-service:/app - ./microservices/llm-service:/app
- ./scripts:/app/scripts - ./scripts:/app/scripts
environment: environment:
- MONGODB_URL=mongodb://mongo:27017 - MONGODB_URL=${MONGODB_URL}
- DB_NAME=llm_filter_db - DB_NAME=${DB_NAME}
- SECRET_KEY=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - SECRET_KEY=${JWT_SECRET}
- ALGORITHM=HS256 - ALGORITHM=${ALGORITHM}
- ACCESS_TOKEN_EXPIRE_MINUTES=30 - ACCESS_TOKEN_EXPIRE_MINUTES=${ACCESS_TOKEN_EXPIRE_MINUTES}
- TERM_START_DATE=2025-09-01 - TERM_START_DATE=${TERM_START_DATE}
- OLLAMA_BASE_URL=http://192.168.6.6:11434/ - OLLAMA_BASE_URL=${OLLAMA_BASE_URL}
- OLLAMA_MODEL=deepseek-r1:14b - OLLAMA_MODEL=${OLLAMA_MODEL}
# Dify Configuration # Dify Configuration
- DIFY_API_URL=http://192.168.6.6/v1 - DIFY_API_URL=${DIFY_API_URL}
- DIFY_API_KEY=app-sLnrbNjEi1GiTDGgL2B2DwLZ - DIFY_API_KEY=${DIFY_API_KEY}
- DIFY_RESPONSE_MODE=${DIFY_RESPONSE_MODE}
- DIFY_MESSAGE_ENDPOINT=${DIFY_MESSAGE_ENDPOINT}
# Redis Configuration # Redis Configuration
- REDIS_HOST=redis - REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=6379 - REDIS_PORT=${REDIS_PORT}
- REDIS_DB=${REDIS_DB}
- REDIS_PASSWORD=${REDIS_PASSWORD}
# App Configuration
- APP_BASE_URL=${APP_BASE_URL}
- API_V1_STR=${API_V1_STR}
- APP_MODE=${APP_MODE}
- CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS}
- TZ=${TZ}
depends_on: depends_on:
- mongo - mongo
- redis - redis
...@@ -111,15 +135,22 @@ services: ...@@ -111,15 +135,22 @@ services:
container_name: llm-filter-security container_name: llm-filter-security
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --proxy-headers --forwarded-allow-ips '*' command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --proxy-headers --forwarded-allow-ips '*'
ports: ports:
- "8003:8000" - "${SECURITY_SERVICE_PORT:-8003}:8000"
volumes: volumes:
- ./microservices/security-service/app:/app/app - ./microservices/security-service/app:/app/app
environment: environment:
- JWT_SECRET=llm_filter_secure_secret_key_2025_update_must_be_32_bytes - JWT_SECRET=${JWT_SECRET}
- DIFY_API_URL=http://192.168.6.6/v1 - ALGORITHM=${ALGORITHM}
- DIFY_API_KEY=app-ggTb0oC9WXQQm2r7KrvVUS6v - DIFY_API_URL=${DIFY_API_URL}
- MONGODB_URL=mongodb://mongo:27017 - DIFY_API_KEY=${DIFY_API_KEY}
- MONGODB_DB_NAME=security_service_db - DIFY_RESPONSE_MODE=${DIFY_RESPONSE_MODE}
- MONGODB_URL=${MONGODB_URL}
- MONGODB_DB_NAME=${MONGODB_DB_NAME}
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
- REDIS_DB=${REDIS_DB}
- REDIS_PASSWORD=${REDIS_PASSWORD}
- TZ=${TZ}
depends_on: depends_on:
- mongo - mongo
networks: networks:
...@@ -130,7 +161,7 @@ services: ...@@ -130,7 +161,7 @@ services:
image: mongo:latest image: mongo:latest
container_name: llm-filter-mongo container_name: llm-filter-mongo
ports: ports:
- "27017:27017" - "${MONGODB_PORT_EXTERNAL:-27017}:27017"
volumes: volumes:
- mongo_data:/data/db - mongo_data:/data/db
networks: networks:
...@@ -141,9 +172,11 @@ services: ...@@ -141,9 +172,11 @@ services:
image: nginx:alpine image: nginx:alpine
container_name: llm-filter-gateway container_name: llm-filter-gateway
ports: ports:
- "8080:80" - "${GATEWAY_PORT:-8080}:80"
volumes: volumes:
- ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro - ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro
environment:
- TZ=${TZ}
depends_on: depends_on:
- auth-service - auth-service
- edu-service - edu-service
......
...@@ -37,21 +37,9 @@ func main() { ...@@ -37,21 +37,9 @@ func main() {
dbName := os.Getenv("DB_NAME") dbName := os.Getenv("DB_NAME")
dbPort := os.Getenv("DB_PORT") dbPort := os.Getenv("DB_PORT")
// 默认值处理(用于本地开发) // 必需的环境变量检查
if dbHost == "" { if dbHost == "" || dbUser == "" || dbPassword == "" || dbName == "" || dbPort == "" {
dbHost = "localhost" log.Fatal("Missing required database environment variables: DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT")
}
if dbUser == "" {
dbUser = "admin"
}
if dbPassword == "" {
dbPassword = "password" // 请确保本地有此密码的数据库或修改此处
}
if dbName == "" {
dbName = "llm_filter_db"
}
if dbPort == "" {
dbPort = "5433"
} }
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai",
...@@ -111,7 +99,11 @@ func main() { ...@@ -111,7 +99,11 @@ func main() {
} }
func initAdminUser(repo *repository.UserRepository) { func initAdminUser(repo *repository.UserRepository) {
adminUsername := "admin" adminUsername := os.Getenv("ADMIN_USERNAME")
if adminUsername == "" {
adminUsername = "admin"
}
exists, err := repo.ExistsByUsername(adminUsername) exists, err := repo.ExistsByUsername(adminUsername)
if err != nil { if err != nil {
log.Printf("Failed to check admin user existence: %v", err) log.Printf("Failed to check admin user existence: %v", err)
...@@ -123,7 +115,7 @@ func initAdminUser(repo *repository.UserRepository) { ...@@ -123,7 +115,7 @@ func initAdminUser(repo *repository.UserRepository) {
adminPassword := os.Getenv("ADMIN_PASSWORD") adminPassword := os.Getenv("ADMIN_PASSWORD")
if adminPassword == "" { if adminPassword == "" {
adminPassword = "password123" log.Fatal("ADMIN_PASSWORD environment variable is required for initial admin user creation")
} }
hashedPwd, err := utils.HashPassword(adminPassword) hashedPwd, err := utils.HashPassword(adminPassword)
...@@ -132,11 +124,16 @@ func initAdminUser(repo *repository.UserRepository) { ...@@ -132,11 +124,16 @@ func initAdminUser(repo *repository.UserRepository) {
return return
} }
adminEmail := os.Getenv("ADMIN_EMAIL")
if adminEmail == "" {
adminEmail = "admin@example.com"
}
adminUser := &model.User{ adminUser := &model.User{
Username: adminUsername, Username: adminUsername,
Email: "admin@example.com", Email: adminEmail,
Password: hashedPwd, Password: hashedPwd,
Role: "administrator", // 兼容旧系统的最高权限角色 Role: "administrator",
RoleLevel: 5, RoleLevel: 5,
Edition: "edu", Edition: "edu",
} }
...@@ -144,7 +141,7 @@ func initAdminUser(repo *repository.UserRepository) { ...@@ -144,7 +141,7 @@ func initAdminUser(repo *repository.UserRepository) {
if err := repo.Create(adminUser); err != nil { if err := repo.Create(adminUser); err != nil {
log.Printf("Failed to create admin user: %v", err) log.Printf("Failed to create admin user: %v", err)
} else { } else {
log.Printf("Admin user created successfully. Username: %s, Password: %s", adminUsername, adminPassword) log.Printf("Admin user created successfully. Username: %s", adminUsername)
} }
} else { } else {
log.Println("Admin user already exists.") log.Println("Admin user already exists.")
......
...@@ -9,12 +9,17 @@ import ( ...@@ -9,12 +9,17 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
var jwtSecret = []byte("your-secret-key") var jwtSecret []byte
func init() { func init() {
if secret := os.Getenv("JWT_SECRET"); secret != "" { secret := os.Getenv("JWT_SECRET")
jwtSecret = []byte(secret) if secret == "" {
log.Fatal("JWT_SECRET environment variable is required")
} }
if len(secret) < 32 {
log.Fatal("JWT_SECRET must be at least 32 characters long")
}
jwtSecret = []byte(secret)
} }
func GetJWTSecret() []byte { func GetJWTSecret() []byte {
......
server.port=8082 server.port=${SERVER_PORT:8082}
spring.application.name=edu-service spring.application.name=edu-service
# Database Configuration # ============================================================
# 数据库配置
# ============================================================
spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5433}/${DB_NAME:llm_filter_db} spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5433}/${DB_NAME:llm_filter_db}
spring.datasource.username=${DB_USER:admin} spring.datasource.username=${DB_USER:admin}
spring.datasource.password=${DB_PASSWORD:password} spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.driver-class-name=org.postgresql.Driver
# JPA Configuration # ============================================================
spring.jpa.hibernate.ddl-auto=update # JPA/Hibernate 配置
spring.jpa.show-sql=true # ============================================================
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=${JPA_DDL_AUTO:update}
spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=${JPA_SHOW_SQL:true}
spring.jpa.properties.hibernate.dialect=${JPA_DIALECT:org.hibernate.dialect.PostgreSQLDialect}
spring.jpa.properties.hibernate.format_sql=${JPA_FORMAT_SQL:true}
# Security # ============================================================
jwt.secret=${JWT_SECRET:your_secret_key_here_must_be_very_long_to_be_secure_at_least_32_bytes} # 安全配置
# ============================================================
jwt.secret=${JWT_SECRET}
# Redis Configuration # ============================================================
# Redis 配置
# ============================================================
spring.redis.host=${SPRING_REDIS_HOST:localhost} spring.redis.host=${SPRING_REDIS_HOST:localhost}
spring.redis.port=${SPRING_REDIS_PORT:6379} spring.redis.port=${SPRING_REDIS_PORT:6379}
spring.redis.timeout=2000 spring.redis.timeout=${REDIS_TIMEOUT:2000}
spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-active=${REDIS_POOL_MAX_ACTIVE:8}
spring.redis.lettuce.pool.max-wait=-1 spring.redis.lettuce.pool.max-wait=${REDIS_POOL_MAX_WAIT:-1}
spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.max-idle=${REDIS_POOL_MAX_IDLE:8}
spring.redis.lettuce.pool.min-idle=0 spring.redis.lettuce.pool.min-idle=${REDIS_POOL_MIN_IDLE:0}
# ============================================================
# 日志配置
# ============================================================
logging.level.root=${LOGGING_LEVEL:INFO}
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
import os import os
# Pydantic v2 中 BaseSettings 已迁移到 pydantic-settings
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
from dotenv import load_dotenv from dotenv import load_dotenv
...@@ -15,23 +14,23 @@ class Settings(BaseSettings): ...@@ -15,23 +14,23 @@ class Settings(BaseSettings):
APP_NAME: str = "LLM过滤系统" APP_NAME: str = "LLM过滤系统"
API_V1_STR: str = "/api/v1" API_V1_STR: str = "/api/v1"
APP_BASE_URL: str = os.getenv("APP_BASE_URL", "http://localhost:8000") APP_BASE_URL: str = os.getenv("APP_BASE_URL", "http://localhost:8000")
# 数据库配置 # 数据库配置
MONGODB_URL: str = os.getenv("MONGODB_URL", "mongodb://localhost:27017") MONGODB_URL: str = os.getenv("MONGODB_URL", "mongodb://localhost:27017")
DB_NAME: str = os.getenv("DB_NAME", "llm_filter_db") DB_NAME: str = os.getenv("DB_NAME", "llm_filter_db")
# JWT配置 # JWT配置
SECRET_KEY: str = os.getenv("SECRET_KEY", "your_secret_key_here") SECRET_KEY: str = os.getenv("SECRET_KEY", "")
ALGORITHM: str = os.getenv("ALGORITHM", "HS256") ALGORITHM: str = os.getenv("ALGORITHM", "HS256")
ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30")) ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
# Ollama配置 # Ollama配置
OLLAMA_BASE_URL: str = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") OLLAMA_BASE_URL: str = os.getenv("OLLAMA_BASE_URL", "http://192.168.6.6:11434/")
OLLAMA_MODEL: str = os.getenv("OLLAMA_MODEL", "llama2") OLLAMA_MODEL: str = os.getenv("OLLAMA_MODEL", "deepseek-r1:14b")
# Dify配置 # Dify配置
DIFY_API_URL: str = os.getenv("DIFY_API_URL", "http://192.168.6.6/v1") DIFY_API_URL: str = os.getenv("DIFY_API_URL", "http://192.168.6.6/v1")
DIFY_API_KEY: str = os.getenv("DIFY_API_KEY", "app-sLnrbNjEi1GiTDGgL2B2DwLZ") DIFY_API_KEY: str = os.getenv("DIFY_API_KEY", "")
DIFY_RESPONSE_MODE: str = os.getenv("DIFY_RESPONSE_MODE", "streaming") DIFY_RESPONSE_MODE: str = os.getenv("DIFY_RESPONSE_MODE", "streaming")
DIFY_MESSAGE_ENDPOINT: str = os.getenv("DIFY_MESSAGE_ENDPOINT", "chat-messages") DIFY_MESSAGE_ENDPOINT: str = os.getenv("DIFY_MESSAGE_ENDPOINT", "chat-messages")
...@@ -42,7 +41,7 @@ class Settings(BaseSettings): ...@@ -42,7 +41,7 @@ class Settings(BaseSettings):
CORS_ALLOWED_ORIGINS: str = os.getenv("CORS_ALLOWED_ORIGINS", "*") CORS_ALLOWED_ORIGINS: str = os.getenv("CORS_ALLOWED_ORIGINS", "*")
GITHUB_DEFAULT_REPO: str = os.getenv("GITHUB_DEFAULT_REPO", "") GITHUB_DEFAULT_REPO: str = os.getenv("GITHUB_DEFAULT_REPO", "")
GITHUB_TOKEN: str = os.getenv("GITHUB_TOKEN", "") GITHUB_TOKEN: str = os.getenv("GITHUB_TOKEN", "")
# 学期配置 # 学期配置
TERM_START_DATE: str = os.getenv("TERM_START_DATE", "2025-09-01") # 默认开学日期 TERM_START_DATE: str = os.getenv("TERM_START_DATE", "2025-09-01") # 默认开学日期
......
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
import os
class Settings(BaseSettings): class Settings(BaseSettings):
API_V1_STR: str = "/api/v1" API_V1_STR: str = "/api/v1"
PROJECT_NAME: str = "Security Service" PROJECT_NAME: str = "Security Service"
# 鉴权配置 (与 Auth Service 保持一致) # 鉴权配置 (与 Auth Service 保持一致)
JWT_SECRET: str = "llm_filter_secure_secret_key_2025_update_must_be_32_bytes" JWT_SECRET: str = os.getenv("JWT_SECRET", "")
ALGORITHM: str = "HS256" ALGORITHM: str = os.getenv("ALGORITHM", "HS256")
# Dify 配置 # Dify 配置
DIFY_API_URL: str = "http://192.168.6.6/v1" DIFY_API_URL: str = os.getenv("DIFY_API_URL", "http://192.168.6.6/v1")
DIFY_API_KEY: str = "app-lkK33EQOVXXrjD9x3SKbItr7" DIFY_API_KEY: str = os.getenv("DIFY_API_KEY", "")
DIFY_RESPONSE_MODE: str = os.getenv("DIFY_RESPONSE_MODE", "streaming")
# MongoDB 配置 # MongoDB 配置
MONGODB_URL: str = "mongodb://localhost:27017" MONGODB_URL: str = os.getenv("MONGODB_URL", "mongodb://localhost:27017")
MONGODB_DB_NAME: str = "security_service_db" MONGODB_DB_NAME: str = os.getenv("MONGODB_DB_NAME", "security_service_db")
# Redis 配置
REDIS_HOST: str = os.getenv("REDIS_HOST", "localhost")
REDIS_PORT: int = int(os.getenv("REDIS_PORT", "6379"))
REDIS_DB: int = int(os.getenv("REDIS_DB", "0"))
REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "")
class Config: class Config:
case_sensitive = True case_sensitive = True
......
This diff is collapsed.
#!/bin/bash
# LLM Filter 项目启动脚本
echo "=========================================="
echo " LLM Filter 项目启动脚本"
echo "=========================================="
echo ""
# 检查 Docker 和 Docker Compose
if ! command -v docker &> /dev/null; then
echo "[ERROR] Docker 未安装"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo "[ERROR] Docker Compose 未安装"
exit 1
fi
echo "[INFO] Docker 和 Docker Compose 已安装"
echo ""
# 检查 .env 文件
if [ ! -f .env ]; then
echo "[ERROR] .env 文件不存在,请先运行:"
echo " python scripts/generate_secrets.py"
exit 1
fi
echo "[INFO] .env 文件存在"
echo ""
# 步骤 1:停止现有服务
echo "=========================================="
echo "步骤 1: 停止现有服务"
echo "=========================================="
docker-compose down
echo ""
# 步骤 2:启动基础设施
echo "=========================================="
echo "步骤 2: 启动基础设施 (PostgreSQL, Redis, MongoDB)"
echo "=========================================="
docker-compose up -d postgres redis mongo
echo "[INFO] 等待数据库启动..."
sleep 10
echo ""
echo "[INFO] 检查数据库状态..."
docker-compose ps postgres redis mongo
echo ""
# 步骤 3:启动业务服务
echo "=========================================="
echo "步骤 3: 启动业务服务"
echo "=========================================="
docker-compose up -d auth-service edu-service llm-service security-service
echo "[INFO] 等待服务启动..."
sleep 15
echo ""
echo "[INFO] 检查业务服务状态..."
docker-compose ps auth-service edu-service llm-service security-service
echo ""
# 步骤 4:启动网关
echo "=========================================="
echo "步骤 4: 启动 API 网关"
echo "=========================================="
docker-compose up -d gateway
echo "[INFO] 等待网关启动..."
sleep 5
echo ""
echo "[INFO] 检查网关状态..."
docker-compose ps gateway
echo ""
# 步骤 5:验证服务
echo "=========================================="
echo "步骤 5: 验证所有服务"
echo "=========================================="
docker-compose ps
echo ""
echo "=========================================="
echo " 启动完成!"
echo "=========================================="
echo ""
echo "📚 文档地址:"
echo " - Gateway: http://localhost:8080"
echo " - Auth Service: http://localhost:8080/docs/auth/"
echo " - Edu Service: http://localhost:8080/docs/edu/"
echo " - LLM Service: http://localhost:8080/docs/llm/"
echo " - Security: http://localhost:8080/docs/security/"
echo ""
echo "🔑 默认管理员账号:"
echo " - 用户名: admin"
echo " - 密码: 查看 .env 文件中的 ADMIN_PASSWORD"
echo ""
echo "📊 查看日志:"
echo " - 所有服务: docker-compose logs -f"
echo " - 特定服务: docker-compose logs -f [service-name]"
echo ""
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment