# ============================================================================= # TianShuAPI Docker Compose - 1Panel 环境配置 # ============================================================================= # 此配置文件适用于已有 1Panel 环境,复用现有 Redis # ============================================================================= services: # =========================================================================== # TianShuAPI Application # =========================================================================== sub2api: # 方式1:使用官方镜像(快速部署) # image: weishaw/sub2api:latest # 方式2:从本地代码构建(二次开发) build: context: ../ dockerfile: Dockerfile args: - BUILD_TAGS=embed image: sub2api:local container_name: sub2api restart: unless-stopped ulimits: nofile: soft: 100000 hard: 100000 ports: - "${BIND_HOST:-0.0.0.0}:${SERVER_PORT:-8080}:8080" volumes: - sub2api_data:/app/data environment: # Auto Setup - AUTO_SETUP=true # Server Configuration - SERVER_HOST=0.0.0.0 - SERVER_PORT=8080 - SERVER_MODE=${SERVER_MODE:-release} - RUN_MODE=${RUN_MODE:-standard} # Database Configuration - DATABASE_HOST=postgres - DATABASE_PORT=5432 - DATABASE_USER=${POSTGRES_USER:-sub2api} - DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - DATABASE_DBNAME=${POSTGRES_DB:-sub2api} - DATABASE_SSLMODE=disable - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} # Redis Configuration - 使用外部 Redis - REDIS_HOST=${REDIS_HOST} - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_PASSWORD=${REDIS_PASSWORD} - REDIS_DB=${REDIS_DB:-0} - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} - REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false} # Admin Account - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@sub2api.local} - ADMIN_PASSWORD=${ADMIN_PASSWORD:-} # JWT Configuration - JWT_SECRET=${JWT_SECRET:-} - JWT_EXPIRE_HOUR=${JWT_EXPIRE_HOUR:-24} # ======================================================================= # TOTP (2FA) Configuration # ======================================================================= # IMPORTANT: Set a fixed encryption key for TOTP secrets. If left empty, # a random key will be generated on each startup, causing all existing # TOTP configurations to become invalid (users won't be able to login # with 2FA). # Generate a secure key: openssl rand -hex 32 - TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY:-} # ======================================================================= # Timezone Configuration # This affects ALL time operations in the application: # - Database timestamps # - Usage statistics "today" boundary # - Subscription expiry times # - Log timestamps # Common values: Asia/Shanghai, America/New_York, Europe/London, UTC # ======================================================================= - TZ=${TZ:-Asia/Shanghai} # Gemini OAuth (可选) - GEMINI_OAUTH_CLIENT_ID=${GEMINI_OAUTH_CLIENT_ID:-} - GEMINI_OAUTH_CLIENT_SECRET=${GEMINI_OAUTH_CLIENT_SECRET:-} - GEMINI_OAUTH_SCOPES=${GEMINI_OAUTH_SCOPES:-} - GEMINI_QUOTA_POLICY=${GEMINI_QUOTA_POLICY:-} # Built-in OAuth client secrets (optional) # SECURITY: This repo does not embed third-party client_secret. - GEMINI_CLI_OAUTH_CLIENT_SECRET=${GEMINI_CLI_OAUTH_CLIENT_SECRET:-} - ANTIGRAVITY_OAUTH_CLIENT_SECRET=${ANTIGRAVITY_OAUTH_CLIENT_SECRET:-} # ======================================================================= # Security Configuration (URL Allowlist) # ======================================================================= # Enable URL allowlist validation (false to skip allowlist checks) - SECURITY_URL_ALLOWLIST_ENABLED=${SECURITY_URL_ALLOWLIST_ENABLED:-false} # Allow insecure HTTP URLs when allowlist is disabled (default: false, requires https) - SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=${SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP:-false} # Allow private IP addresses for upstream/pricing/CRS (for internal deployments) - SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=${SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS:-false} # Upstream hosts whitelist (comma-separated, only used when enabled=true) - SECURITY_URL_ALLOWLIST_UPSTREAM_HOSTS=${SECURITY_URL_ALLOWLIST_UPSTREAM_HOSTS:-} # ======================================================================= # Update Configuration (在线更新配置) # ======================================================================= # Proxy for accessing GitHub (online updates + pricing data) # Examples: http://host:port, socks5://host:port - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-} depends_on: postgres: condition: service_healthy extra_hosts: - "host.docker.internal:host-gateway" networks: - sub2api-network - 1panel-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s # =========================================================================== # PostgreSQL Database # =========================================================================== postgres: image: postgres:18-alpine container_name: sub2api-postgres restart: unless-stopped ulimits: nofile: soft: 100000 hard: 100000 volumes: - postgres_data:/var/lib/postgresql/data environment: # postgres:18-alpine 默认 PGDATA=/var/lib/postgresql/18/docker(位于镜像声明的匿名卷 /var/lib/postgresql 内)。 # 若不显式设置 PGDATA,则即使挂载了 postgres_data 到 /var/lib/postgresql/data,数据也不会落盘到该命名卷, # docker compose down/up 后会触发 initdb 重新初始化,导致用户/密码等数据丢失。 - PGDATA=/var/lib/postgresql/data - POSTGRES_USER=${POSTGRES_USER:-sub2api} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - POSTGRES_DB=${POSTGRES_DB:-sub2api} - TZ=${TZ:-Asia/Shanghai} networks: - sub2api-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sub2api} -d ${POSTGRES_DB:-sub2api}"] interval: 10s timeout: 5s retries: 5 start_period: 10s # ============================================================================= # Volumes # ============================================================================= volumes: sub2api_data: driver: local postgres_data: driver: local # ============================================================================= # Networks # ============================================================================= networks: sub2api-network: driver: bridge 1panel-network: external: true