# `latest` tracks the latest stable release image. # For deterministic environments, pin a release tag like `v0.1.0`. # Use `edge` only when you explicitly want the latest build from `main`. SKILLHUB_VERSION=latest SKILLHUB_SERVER_IMAGE=ghcr.io/iflytek/skillhub-server SKILLHUB_WEB_IMAGE=ghcr.io/iflytek/skillhub-web SKILLHUB_SCANNER_IMAGE=ghcr.io/iflytek/skillhub-scanner POSTGRES_IMAGE=postgres:16-alpine REDIS_IMAGE=redis:7-alpine # Public entrypoint seen by browsers/CLI, no trailing slash. # Default to localhost so `runtime.sh up` works as a zero-config quickstart. SKILLHUB_PUBLIC_BASE_URL=http://localhost # Frontend usually keeps this empty and proxies to the backend through nginx. SKILLHUB_WEB_API_BASE_URL= SKILLHUB_API_UPSTREAM=http://server:8080 # Keep false for direct exposure. Enable only behind a trusted proxy that replaces # X-Forwarded-Proto and blocks direct access to the web container. SKILLHUB_TRUST_FORWARDED_PROTO=false POSTGRES_BIND_ADDRESS=127.0.0.1 POSTGRES_PORT=5432 POSTGRES_DB=skillhub POSTGRES_USER=skillhub POSTGRES_PASSWORD=change-this-postgres-password REDIS_BIND_ADDRESS=127.0.0.1 REDIS_PORT=6379 # Optional external Redis connection. Leave these commented to use the bundled # standalone Redis service. For Redis Cluster, every advertised node address # must be reachable from the server container. # SPRING_DATA_REDIS_CLUSTER_NODES=redis-0.example.com:6379,redis-1.example.com:6379,redis-2.example.com:6379 # SPRING_DATA_REDIS_CLUSTER_MAX_REDIRECTS=5 # SPRING_DATA_REDIS_USERNAME= # SPRING_DATA_REDIS_PASSWORD= # SPRING_DATA_REDIS_SSL_ENABLED=false # SPRING_DATA_REDIS_CONNECT_TIMEOUT=5s # SPRING_DATA_REDIS_TIMEOUT=3s # SPRING_DATA_REDIS_CLIENT_NAME=skillhub # Optional external Redis Sentinel. Sentinel takes precedence if both Sentinel # and Cluster settings are present. Use separate credentials when Sentinel ACL # differs from the Redis data nodes. # SPRING_DATA_REDIS_SENTINEL_MASTER=mymaster # SPRING_DATA_REDIS_SENTINEL_NODES=sentinel-0.example.com:26379,sentinel-1.example.com:26379,sentinel-2.example.com:26379 # SPRING_DATA_REDIS_SENTINEL_USERNAME= # SPRING_DATA_REDIS_SENTINEL_PASSWORD= # SKILLHUB_REDIS_SENTINEL_CHECK_SENTINELS_LIST=true API_PORT=8080 WEB_PORT=80 SESSION_COOKIE_SECURE=false # Account Merge requires an indexed Spring Session repository in a namespace # that has never contained legacy sessions. This one-time cutover signs out # existing web sessions. Enable only after the rollout procedure in # docs/25-secure-account-merge-operations.md is complete. SESSION_REDIS_NAMESPACE=skillhub:session:indexed-v1 SPRING_SESSION_REDIS_REPOSITORY_TYPE=indexed # Use none only when the managed Redis service already supplies the required # keyspace notification configuration and rejects CONFIG commands. SPRING_SESSION_REDIS_CONFIGURE_ACTION=notify-keyspace-events SKILLHUB_AUTH_ACCOUNT_MERGE_ENABLED=false SKILLHUB_AUTH_ACCOUNT_MERGE_SESSION_CUTOVER_COMPLETE=false # Observability defaults require no Collector or tracing backend. # Use json in container deployments when stdout is collected centrally. SKILLHUB_TRACING_MODE=none SKILLHUB_LOG_FORMAT=json SKILLHUB_LOG_ASYNC_QUEUE_SIZE=1024 SKILLHUB_SERVICE_VERSION=unknown SKILLHUB_SERVICE_ENVIRONMENT=production SKILLHUB_TRACING_SAMPLING_PROBABILITY=0.1 # Set only with SKILLHUB_TRACING_MODE=otel-sdk. MANAGEMENT_OTLP_TRACING_ENDPOINT= SKILLHUB_OTLP_TIMEOUT=5s SKILLHUB_OTLP_COMPRESSION=gzip # Zero-config runtime validation uses local storage. # Switch to `s3` and fill the fields below before a real production deployment. SKILLHUB_STORAGE_PROVIDER=local SKILLHUB_STORAGE_S3_ENDPOINT=https://oss-cn-example.aliyuncs.com SKILLHUB_STORAGE_S3_PUBLIC_ENDPOINT= SKILLHUB_STORAGE_S3_BUCKET=skillhub-prod # Static credentials for S3-compatible storage (MinIO, Alibaba OSS, etc.). # Leave both blank to use IAM authentication (EC2 instance profile, ECS task role, EKS IRSA). SKILLHUB_STORAGE_S3_ACCESS_KEY=replace-me SKILLHUB_STORAGE_S3_SECRET_KEY=replace-me SKILLHUB_STORAGE_S3_REGION=cn-shanghai SKILLHUB_STORAGE_S3_FORCE_PATH_STYLE=false # Aliyun OSS rejects aws-chunked encoding; set to true when targeting Aliyun OSS. SKILLHUB_STORAGE_S3_DISABLE_CHUNKED_ENCODING=true SKILLHUB_STORAGE_S3_AUTO_CREATE_BUCKET=false SKILLHUB_STORAGE_S3_PRESIGN_EXPIRY=PT10M # Bootstrap local admin account for first login. Rotate or disable after initial setup. BOOTSTRAP_ADMIN_ENABLED=true BOOTSTRAP_ADMIN_USER_ID=docker-admin BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD=ChangeMe!2026 BOOTSTRAP_ADMIN_DISPLAY_NAME=Platform Admin BOOTSTRAP_ADMIN_EMAIL=admin@example.com # Optional override. Defaults to ${SKILLHUB_PUBLIC_BASE_URL}/device. DEVICE_AUTH_VERIFICATION_URI= # Optional: configure real GitHub OAuth before exposing the stack to other users. OAUTH2_GITHUB_CLIENT_ID= OAUTH2_GITHUB_CLIENT_SECRET= # Optional: configure real GitLab OAuth before exposing the stack to other users. # Set OAUTH2_GITLAB_BASE_URI to your self-hosted GitLab URL when applicable. OAUTH2_GITLAB_CLIENT_ID= OAUTH2_GITLAB_CLIENT_SECRET= OAUTH2_GITLAB_BASE_URI=https://gitlab.com OAUTH2_GITLAB_DISPLAY_NAME=GitLab # Optional: OIDC login (e.g. Keycloak, Okta, Azure AD). # Replace "OIDC" in variable names with your registration id (uppercase). # The registration id becomes identity_binding.provider_code — keep it stable. SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_ID= SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_SECRET= SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_PROVIDER=oidc SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_AUTHORIZATION_GRANT_TYPE=authorization_code SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_REDIRECT_URI={baseUrl}/login/oauth2/code/{registrationId} SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_SCOPE=openid,profile,email SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_NAME=OIDC SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER_URI= # Optional: LDAP/Active Directory credential login. The provider remains # hidden until enabled and every required field is valid. Keep provider code, # authority and stable subject mapping unchanged after identities are bound. SKILLHUB_AUTH_LDAP_ENABLED=false SKILLHUB_AUTH_LDAP_PROVIDER_CODE=ldap-main SKILLHUB_AUTH_LDAP_DISPLAY_NAME=Corporate Directory SKILLHUB_AUTH_LDAP_AUTHORITY=corp-directory SKILLHUB_AUTH_LDAP_URL=ldaps://ldap.example.com:636 SKILLHUB_AUTH_LDAP_START_TLS=false SKILLHUB_AUTH_LDAP_ALLOW_INSECURE_FOR_TESTING=false SKILLHUB_AUTH_LDAP_DIRECTORY_TYPE=OPENLDAP SKILLHUB_AUTH_LDAP_BASE_DN=dc=example,dc=com SKILLHUB_AUTH_LDAP_USER_SEARCH_BASE=ou=people SKILLHUB_AUTH_LDAP_USER_SEARCH_FILTER=(uid={0}) SKILLHUB_AUTH_LDAP_BIND_DN=cn=skillhub,ou=services,dc=example,dc=com SKILLHUB_AUTH_LDAP_BIND_PASSWORD= # OPENLDAP defaults to entryUUID/ldap_entry_uuid; ACTIVE_DIRECTORY defaults # to objectGUID/ad_object_guid. Leave both blank to use those safe defaults. SKILLHUB_AUTH_LDAP_SUBJECT_ATTRIBUTE= SKILLHUB_AUTH_LDAP_SUBJECT_TYPE= SKILLHUB_AUTH_LDAP_USERNAME_ATTRIBUTE=uid SKILLHUB_AUTH_LDAP_DISPLAY_NAME_ATTRIBUTE=displayName SKILLHUB_AUTH_LDAP_EMAIL_ATTRIBUTE=mail SKILLHUB_AUTH_LDAP_AVATAR_URL_ATTRIBUTE= SKILLHUB_AUTH_LDAP_EMAIL_AUTHORITATIVE=false SKILLHUB_AUTH_LDAP_CONNECT_TIMEOUT=PT5S SKILLHUB_AUTH_LDAP_READ_TIMEOUT=PT10S SKILLHUB_AUTH_LDAP_POOL_WAIT_TIMEOUT=PT2S SKILLHUB_AUTH_LDAP_MAX_CONCURRENT_REQUESTS=16 SKILLHUB_AUTH_LDAP_MAX_ATTRIBUTE_VALUES=16 # Optional: CAS 2.0/3.0 browser login. The provider remains hidden until # enabled and every required field is valid. Keep provider code and authority # stable after users have created identity bindings. SKILLHUB_AUTH_CAS_ENABLED=false SKILLHUB_AUTH_CAS_PROVIDER_CODE=cas-main SKILLHUB_AUTH_CAS_DISPLAY_NAME=Corporate CAS SKILLHUB_AUTH_CAS_AUTHORITY=corp-cas SKILLHUB_AUTH_CAS_SERVER_URL=https://cas.example.com/cas SKILLHUB_AUTH_CAS_SERVICE_URL=https://skillhub.example.com/api/v1/auth/cas/cas-main/callback SKILLHUB_AUTH_CAS_PROTOCOL_VERSION=3.0 SKILLHUB_AUTH_CAS_SUBJECT_TYPE=cas_principal SKILLHUB_AUTH_CAS_ALLOW_INSECURE_FOR_TESTING=false SKILLHUB_AUTH_CAS_CONNECT_TIMEOUT=PT5S SKILLHUB_AUTH_CAS_READ_TIMEOUT=PT10S SKILLHUB_AUTH_CAS_STATE_TTL=PT5M SKILLHUB_AUTH_CAS_MAX_RESPONSE_BYTES=1048576 # Optional CAS attribute mappings. If subject is blank, the CAS principal is used. SKILLHUB_AUTH_CAS_ATTRIBUTES_SUBJECT= SKILLHUB_AUTH_CAS_ATTRIBUTES_DISPLAY_NAME=displayName SKILLHUB_AUTH_CAS_ATTRIBUTES_EMAIL=mail SKILLHUB_AUTH_CAS_ATTRIBUTES_AVATAR_URL= # Direct (username/password) authentication for environments without OAuth2. # To enable, set BOTH: # - SKILLHUB_AUTH_DIRECT_ENABLED=true (server: enables the /api/v1/auth/direct endpoint) # - SKILLHUB_WEB_AUTH_DIRECT_ENABLED=true (web: surfaces the username/password form) # Set SKILLHUB_WEB_AUTH_DIRECT_PROVIDER to the provider id (e.g. "local"). SKILLHUB_AUTH_DIRECT_ENABLED=false SKILLHUB_WEB_AUTH_DIRECT_ENABLED=false SKILLHUB_WEB_AUTH_DIRECT_PROVIDER= # SMTP configuration for password reset verification emails. SPRING_MAIL_HOST= SPRING_MAIL_PORT=587 SPRING_MAIL_USERNAME= SPRING_MAIL_PASSWORD= SPRING_MAIL_SMTP_AUTH=true SPRING_MAIL_SMTP_STARTTLS_ENABLE=true SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=false SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST= SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=noreply@example.com SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=SkillHub # Security scanner is enabled by default. Set to false to disable scanning. SKILLHUB_SECURITY_SCANNER_ENABLED=true # Required for signing anonymous download rate-limit cookies. Use a unique random value per deployment. # runtime.sh generates and persists one automatically when this placeholder is still present. SKILLHUB_DOWNLOAD_ANON_COOKIE_SECRET=replace-with-random-download-secret-32-bytes # Scanner LLM configuration (optional, for AI-powered scanning features) SKILL_SCANNER_LLM_API_KEY= SKILL_SCANNER_LLM_BASE_URL= SKILL_SCANNER_LLM_MODEL=