feat: deployment security hardening

- Redis: add password authentication (requirepass), update healthcheck
- PostgreSQL: replace hardcoded password with env variable
- Docker Compose: remove obsolete version field, use env vars for credentials
- Add .env.production.example template with strong password placeholders
- Update all .env files with new credentials and ports
This commit is contained in:
chiguyong 2026-06-01 21:34:13 +08:00
parent d5f752f419
commit 47719b25ce
4 changed files with 72 additions and 9 deletions

64
.env.production.example Normal file
View File

@ -0,0 +1,64 @@
# ============================================================
# GEO Platform Production Environment Configuration
# ============================================================
# IMPORTANT: Replace ALL placeholder values before deploying!
# Passwords must be at least 16 characters with mixed case, numbers, and symbols.
# ============================================================
# Database (MUST use strong password in production)
# ============================================================
POSTGRES_PASSWORD=CHANGE_ME_strong_pg_password_32chars!
DATABASE_URL=postgresql+asyncpg://postgres:CHANGE_ME_strong_pg_password_32chars!@db:5432/geo_platform
# ============================================================
# Redis (MUST use strong password in production)
# ============================================================
REDIS_PASSWORD=CHANGE_ME_strong_redis_password_32chars!
REDIS_URL=redis://:CHANGE_ME_strong_redis_password_32chars!@redis:6379/0
# ============================================================
# JWT (MUST be unique and at least 32 characters)
# ============================================================
JWT_SECRET=CHANGE_ME_unique_jwt_secret_at_least_32_chars
JWT_EXPIRE_HOURS=24
SECRET_KEY=CHANGE_ME_unique_nextauth_secret_at_least_32_chars
# ============================================================
# API Configuration
# ============================================================
NEXT_PUBLIC_API_URL=https://your-domain.com
CORS_ORIGINS=https://your-domain.com
# ============================================================
# LLM Provider (fill in at least one)
# ============================================================
ENABLE_LLM=true
DEFAULT_LLM_PROVIDER=deepseek
DEFAULT_LLM_MODEL=deepseek-chat
DEEPSEEK_API_KEY=
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
DEEPSEEK_MAX_CONTEXT=64000
OPENAI_API_KEY=
OPENAI_MODEL=
OPENAI_BASE_URL=
MOONSHOT_API_KEY=
BAIDU_QIANFAN_API_KEY=
BAIDU_QIANFAN_SECRET_KEY=
DOUBAO_API_KEY=
DOUBAO_ENDPOINT_ID=
# ============================================================
# Rate Limiting
# ============================================================
API_RATE_LIMIT_RPM=10
# ============================================================
# Payment / Distribution / Email (set to real mode in production)
# ============================================================
PAYMENT_MODE=mock
DISTRIBUTION_MODE=mock
EMAIL_MODE=mock

View File

@ -55,12 +55,12 @@ ENABLE_LLM=true
# ============================================================ # ============================================================
# 数据库配置 # 数据库配置
# ============================================================ # ============================================================
DATABASE_URL=postgresql+asyncpg://postgres:postgres123@localhost:5433/geo_platform DATABASE_URL=postgresql+asyncpg://postgres:geo_pg_dev_2026@localhost:5433/geo_platform
# ============================================================ # ============================================================
# Redis 配置 # Redis 配置
# ============================================================ # ============================================================
REDIS_URL=redis://localhost:6380/0 REDIS_URL=redis://:geo_redis_dev_2026@localhost:6380/0
# 是否启用Redis缓存 # 是否启用Redis缓存
ENABLE_REDIS=true ENABLE_REDIS=true

View File

@ -86,7 +86,7 @@ path_separator = os
# database URL. This is consumed by the user-maintained env.py script only. # database URL. This is consumed by the user-maintained env.py script only.
# other means of configuring database URLs may be customized within the env.py # other means of configuring database URLs may be customized within the env.py
# file. # file.
sqlalchemy.url = postgresql+asyncpg://postgres:postgres123@127.0.0.1:5433/geo_platform sqlalchemy.url = postgresql+asyncpg://postgres:geo_pg_dev_2026@127.0.0.1:5433/geo_platform
[post_write_hooks] [post_write_hooks]

View File

@ -1,5 +1,3 @@
version: "3.9"
services: services:
db: db:
image: postgres:15-alpine image: postgres:15-alpine
@ -7,7 +5,7 @@ services:
restart: unless-stopped restart: unless-stopped
environment: environment:
POSTGRES_USER: postgres POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres123 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_pg_dev_2026}
POSTGRES_DB: geo_platform POSTGRES_DB: geo_platform
ports: ports:
- "5433:5432" - "5433:5432"
@ -31,12 +29,13 @@ services:
image: redis:7-alpine image: redis:7-alpine
container_name: geo_redis container_name: geo_redis
restart: unless-stopped restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD:-geo_redis_dev_2026} --appendonly yes
ports: ports:
- "6380:6379" - "6380:6379"
volumes: volumes:
- redis_data:/data - redis_data:/data
healthcheck: healthcheck:
test: ["CMD", "redis-cli", "ping"] test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-geo_redis_dev_2026}", "ping"]
interval: 5s interval: 5s
timeout: 5s timeout: 5s
retries: 5 retries: 5
@ -57,8 +56,8 @@ services:
env_file: env_file:
- .env - .env
environment: environment:
DATABASE_URL: postgresql+asyncpg://postgres:postgres123@db:5432/geo_platform DATABASE_URL: postgresql+asyncpg://postgres:${POSTGRES_PASSWORD:-geo_pg_dev_2026}@db:5432/geo_platform
REDIS_URL: redis://redis:6379/0 REDIS_URL: redis://:${REDIS_PASSWORD:-geo_redis_dev_2026}@redis:6379/0
volumes: volumes:
- ./backend:/app - ./backend:/app
depends_on: depends_on: