Files
OSGAccountServer/compose.yaml
T
Rocky 034a3e8745
CI / verify (push) Has been cancelled
CI / publish (push) Has been cancelled
Add complimentary OOBE polish and configurable admin mTLS
Allow one server-audited onboarding polish request without credits and make the certificate gate temporarily reversible while preserving application authentication.
2026-08-20 17:05:35 +08:00

105 lines
4.5 KiB
YAML

services:
account-server:
image: ${ACCOUNT_IMAGE:-ghcr.io/hkgood/osg-account-server}:${IMAGE_TAG:-main}
pull_policy: always
restart: unless-stopped
init: true
user: "10001:10001"
stop_grace_period: 30s
environment:
APP_ENV: production
PORT: "8080"
PUBLIC_BASE_URL: https://account.osglab.com
INVITE_BASE_URL: https://osglab.com/i
APP_STORE_URL: ${APP_STORE_URL:?set the production App Store HTTPS URL}
# Reuse the existing MySQL; this stack intentionally creates no database.
DATABASE_URL: ${DATABASE_URL:?set DATABASE_URL for the existing MySQL}
DATABASE_USER: ${DATABASE_USER:?set DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:?set DATABASE_PASSWORD}
DATABASE_POOL_SIZE: ${DATABASE_POOL_SIZE:-10}
DATABASE_MIGRATION_USER: ${DATABASE_MIGRATION_USER:?set DATABASE_MIGRATION_USER}
DATABASE_MIGRATION_PASSWORD: ${DATABASE_MIGRATION_PASSWORD:?set DATABASE_MIGRATION_PASSWORD}
JWT_ISSUER: https://account.osglab.com
JWT_AUDIENCE: ${JWT_AUDIENCE:-osgkeyboard-ios}
JWT_SECRET: ${JWT_SECRET:?set a random JWT secret}
ACCESS_TOKEN_MINUTES: ${ACCESS_TOKEN_MINUTES:-15}
REFRESH_TOKEN_DAYS: ${REFRESH_TOKEN_DAYS:-30}
GATEWAY_GRANT_DAYS: ${GATEWAY_GRANT_DAYS:-30}
FIELD_ENCRYPTION_KEY: ${FIELD_ENCRYPTION_KEY:?set a 32-byte Base64 key}
IDENTITY_HMAC_KEY: ${IDENTITY_HMAC_KEY:?set a distinct Base64 key}
IDENTITY_TOMBSTONE_RETENTION_DAYS: ${IDENTITY_TOMBSTONE_RETENTION_DAYS:-365}
ADMIN_ENABLED: ${ADMIN_ENABLED:-false}
ADMIN_MTLS_REQUIRED: ${ADMIN_MTLS_REQUIRED:-true}
ADMIN_BOOTSTRAP_ENABLED: ${ADMIN_BOOTSTRAP_ENABLED:-false}
ADMIN_BOOTSTRAP_OPERATOR_ID: ${ADMIN_BOOTSTRAP_OPERATOR_ID:-}
ADMIN_BOOTSTRAP_USERNAME: ${ADMIN_BOOTSTRAP_USERNAME:-}
ADMIN_BOOTSTRAP_PASSWORD_HASH: ${ADMIN_BOOTSTRAP_PASSWORD_HASH:-}
ADMIN_BOOTSTRAP_TOTP_SECRET_BASE32: ${ADMIN_BOOTSTRAP_TOTP_SECRET_BASE32:-}
ADMIN_SESSION_HOURS: ${ADMIN_SESSION_HOURS:-8}
ADMIN_MAXIMUM_MANUAL_GRANT: ${ADMIN_MAXIMUM_MANUAL_GRANT:-100000}
APPLE_TEAM_ID: ${APPLE_TEAM_ID:?set Apple team ID}
APPLE_KEY_ID: ${APPLE_KEY_ID:?set Apple key ID}
APPLE_CLIENT_ID: ${APPLE_CLIENT_ID:-com.osgkeyboard.ios}
APPLE_PRIVATE_KEY_PEM: ${APPLE_PRIVATE_KEY_PEM:?set Apple private key PEM}
APPLE_INTEGRITY_ENVIRONMENT: production
APP_ATTEST_CHALLENGE_TTL_SECONDS: ${APP_ATTEST_CHALLENGE_TTL_SECONDS:-300}
ENFORCE_DEVICE_CHECK: "true"
ENFORCE_APP_ATTEST: "true"
VOLCENGINE_API_KEY: ${VOLCENGINE_API_KEY:?set Volcengine API key}
VOLCENGINE_RESOURCE_ID: ${VOLCENGINE_RESOURCE_ID:-volc.seedasr.sauc.duration}
VOLCENGINE_ASR_ENDPOINT: ${VOLCENGINE_ASR_ENDPOINT:-wss://openspeech.bytedance.com/api/v3/sauc/bigmodel}
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:?set DeepSeek API key}
DEEPSEEK_MODEL: ${DEEPSEEK_MODEL:-deepseek-v4-flash}
DEEPSEEK_REASONING_MODEL: ${DEEPSEEK_REASONING_MODEL:-}
DEEPSEEK_ENDPOINT: ${DEEPSEEK_ENDPOINT:-https://api.deepseek.com/v1}
SIGNUP_TRIAL_CREDITS: ${SIGNUP_TRIAL_CREDITS:-1000}
REFERRAL_INVITER_CREDITS: ${REFERRAL_INVITER_CREDITS:-1000}
REFERRAL_INVITEE_CREDITS: ${REFERRAL_INVITEE_CREDITS:-1000}
REFERRAL_BINDING_DAYS: ${REFERRAL_BINDING_DAYS:-7}
STOREKIT_ENABLED: ${STOREKIT_ENABLED:-true}
STOREKIT_BUNDLE_ID: ${STOREKIT_BUNDLE_ID:-com.osgkeyboard.ios}
STOREKIT_APP_APPLE_ID: ${STOREKIT_APP_APPLE_ID:-6781553267}
STOREKIT_PRODUCTS: ${STOREKIT_PRODUCTS:-500tks:500,1500tks:1500,3000tks:3000}
ports:
- "127.0.0.1:${ACCOUNT_BIND_PORT:-18080}:8080"
read_only: true
pids_limit: 256
tmpfs:
- /tmp:size=64m,mode=1777,noexec,nosuid,nodev
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8080/health/ready"]
interval: 30s
timeout: 3s
start_period: 30s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
- account-backend
# Separate egress keeps Apple/provider traffic available when the shared
# database network was created with Docker's --internal flag.
- account-egress
networks:
# Pre-create this shared network with:
# docker network create --internal account-backend
# Attach the existing MySQL container without publishing port 3306.
account-backend:
external: true
name: ${ACCOUNT_DOCKER_NETWORK:-account-backend}
account-egress:
driver: bridge