diff --git a/README.md b/README.md index cea92a58..d4f04b11 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,18 @@ curl -L https://raw.githubusercontent.com/OpenCSGs/csghub-server/main/docker-com docker-compose -f docker-compose.yml up -d ``` +## Start CSGHub Server Services Locally + +CSGHub supports TOML format for config files. When starting any service from the command line, you can specify the config file with the `--config` option: + +``` +go run cmd/csghub-server/main.go start server --config local.toml +go run cmd/csghub-server/main.go deploy runner --config local.toml +... +``` + +We provide an [example config file](common/config/config.toml.example), you can rename it, modify as needed and use. All available configurations are defined in [this Go file](common/config/config.go). The TOML configuration uses snake_case naming convention, and names automatically map to corresponding struct field names. + ## Technical Architecture
csghub-server architecture diff --git a/builder/git/gitserver/gitea/client.go b/builder/git/gitserver/gitea/client.go index 9e62672f..af348d68 100644 --- a/builder/git/gitserver/gitea/client.go +++ b/builder/git/gitserver/gitea/client.go @@ -38,7 +38,7 @@ type TokenResponse struct { func NewClient(config *config.Config) (client *Client, err error) { httpClient := &http.Client{ - Timeout: time.Duration(config.GitServer.TimtoutSEC) * time.Second, + Timeout: time.Duration(config.GitServer.TimeoutSEC) * time.Second, } token, err := findOrCreateAccessToken(context.Background(), config) if err != nil { diff --git a/common/config/README.md b/common/config/README.md new file mode 100644 index 00000000..37717ea7 --- /dev/null +++ b/common/config/README.md @@ -0,0 +1,22 @@ +CSGHub server supports two configuration methods: using environment variables or configuration files. You can also combine them, for example, by placing non-sensitive configurations in a config file and overriding sensitive configurations with environment variables. + +### Using a Config File + +CSGHub supports TOML format for config files. When starting any service from the command line, you can specify the config file with the `--config` option: + +``` +go run cmd/csghub-server/main.go start server --config local.toml +go run cmd/csghub-server/main.go deploy runner --config local.toml +``` + +We provide an [example config file](common/config/config.toml.example), you can rename it, modify as needed and use. All available configurations are defined in [this Go file](common/config/config.go). The TOML configuration uses snake_case naming convention, and names automatically map to corresponding struct field names. + +If a config value is missing in the config file, the `default` tag value specified in the Go struct file will be used. + +### Using Environment Variables + +CSGHub also supports configuration through environment variables. The relevant environment variable names are defined in [this Go file](common/config/config.go) under the `env` tag. If an environment variable is absent, the value in the `default` tag will be used. + +### Combining Config File with Environment Variables + +You can use config file together with environment variables. When both are used, environment variables take **higher priority** than the config file. For example, if you have a `Port` setting, and you specify it in the TOML file as `port=1234` and in an environment variable as `export PORT=5678`, the environment variable value (5678) will be used for the port configuration. diff --git a/common/config/config.go b/common/config/config.go index a0096fdb..9f684c2d 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -1,216 +1,242 @@ package config -import "github.com/kelseyhightower/envconfig" +import ( + "context" + "os" + + "github.com/naoina/toml" + "github.com/sethvargo/go-envconfig" +) + +var configFile = "" type Config struct { - Saas bool `envconfig:"STARHUB_SERVER_SAAS" default:"false"` - InstanceID string `envconfig:"STARHUB_SERVER_INSTANCE_ID"` - EnableSwagger bool `envconfig:"STARHUB_SERVER_ENABLE_SWAGGER" default:"false"` - APIToken string `envconfig:"STARHUB_SERVER_API_TOKEN" default:"0c11e6e4f2054444374ba3f0b70de4145935a7312289d404814cd5907c6aa93cc65cd35dbf94e04c13a3dedbf51f1694de84240c8acb7238b54a2c3ac8e87c59"` + Saas bool `env:"STARHUB_SERVER_SAAS, default=false"` + InstanceID string `env:"STARHUB_SERVER_INSTANCE_ID"` + EnableSwagger bool `env:"STARHUB_SERVER_ENABLE_SWAGGER, default=false"` + APIToken string `env:"STARHUB_SERVER_API_TOKEN, default=0c11e6e4f2054444374ba3f0b70de4145935a7312289d404814cd5907c6aa93cc65cd35dbf94e04c13a3dedbf51f1694de84240c8acb7238b54a2c3ac8e87c59"` // enable if you want to acess csghub through https, especially for space rproxy - EnableHTTPS bool `envconfig:"STARHUB_SERVER_ENABLE_HTTPS" default:"false"` + EnableHTTPS bool `env:"STARHUB_SERVER_ENABLE_HTTPS, default=false"` APIServer struct { - Port int `envconfig:"STARHUB_SERVER_SERVER_PORT" default:"8080"` - PublicDomain string `envconfig:"STARHUB_SERVER_PUBLIC_DOMAIN" default:"http://localhost:8080"` - SSHDomain string `envconfig:"STARHUB_SERVER_SSH_DOMAIN" default:"ssh://git@localhost:2222"` + Port int `env:"STARHUB_SERVER_SERVER_PORT, default=8080"` + PublicDomain string `env:"STARHUB_SERVER_PUBLIC_DOMAIN, default=http://localhost:8080"` + SSHDomain string `env:"STARHUB_SERVER_SSH_DOMAIN, default=git@localhost:2222"` } Mirror struct { - URL string `envconfig:"STARHUB_SERVER_MIRROR_URL" default:"http://localhost:8085"` - Token string `envconfig:"STARHUB_SERVER_MIRROR_Token" default:""` - Port int `envconfig:"STARHUB_SERVER_MIRROR_PORT" default:"8085"` - SessionSecretKey string `envconfig:"STARHUB_SERVER_MIRROR_SESSION_SECRET_KEY" default:"mirror"` - WorkerNumber int `envconfig:"STARHUB_SERVER_MIRROR_WORKER_NUMBER" default:"5"` + URL string `env:"STARHUB_SERVER_MIRROR_URL, default=http://localhost:8085"` + Token string `env:"STARHUB_SERVER_MIRROR_Token, default="` + Port int `env:"STARHUB_SERVER_MIRROR_PORT, default=8085"` + SessionSecretKey string `env:"STARHUB_SERVER_MIRROR_SESSION_SECRET_KEY, default=mirror"` + WorkerNumber int `env:"STARHUB_SERVER_MIRROR_WORKER_NUMBER, default=5"` } - DocsHost string `envconfig:"STARHUB_SERVER_SERVER_DOCS_HOST" default:"http://localhost:6636"` + DocsHost string `env:"STARHUB_SERVER_SERVER_DOCS_HOST, default=http://localhost:6636"` Database struct { - Driver string `envconfig:"STARHUB_DATABASE_DRIVER" default:"pg"` - DSN string `envconfig:"STARHUB_DATABASE_DSN" default:"postgresql://postgres:postgres@localhost:5432/starhub_server?sslmode=disable"` - TimeZone string `envconfig:"STARHUB_DATABASE_TIMEZONE" default:"Asia/Shanghai"` + Driver string `env:"STARHUB_DATABASE_DRIVER, default=pg"` + DSN string `env:"STARHUB_DATABASE_DSN, default=postgresql://postgres:postgres@localhost:5432/starhub_server?sslmode=disable"` + TimeZone string `env:"STARHUB_DATABASE_TIMEZONE, default=Asia/Shanghai"` } Redis struct { - Endpoint string `envconfig:"STARHUB_SERVER_REDIS_ENDPOINT" default:"localhost:6379"` - MaxRetries int `envconfig:"STARHUB_SERVER_REDIS_MAX_RETRIES" default:"3"` - MinIdleConnections int `envconfig:"STARHUB_SERVER_REDIS_MIN_IDLE_CONNECTIONS" default:"0"` - User string `envconfig:"STARHUB_SERVER_REDIS_USER"` - Password string `envconfig:"STARHUB_SERVER_REDIS_PASSWORD"` - SentinelMode bool `envconfig:"STARHUB_SERVER_REDIS_USE_SENTINEL" default:"false"` - SentinelMaster string `envconfig:"STARHUB_SERVER_REDIS_SENTINEL_MASTER"` - SentinelEndpoint string `envconfig:"STARHUB_SERVER_REDIS_SENTINEL_ENDPOINT"` + Endpoint string `env:"STARHUB_SERVER_REDIS_ENDPOINT, default=localhost:6379"` + MaxRetries int `env:"STARHUB_SERVER_REDIS_MAX_RETRIES, default=3"` + MinIdleConnections int `env:"STARHUB_SERVER_REDIS_MIN_IDLE_CONNECTIONS, default=0"` + User string `env:"STARHUB_SERVER_REDIS_USER"` + Password string `env:"STARHUB_SERVER_REDIS_PASSWORD"` + SentinelMode bool `env:"STARHUB_SERVER_REDIS_USE_SENTINEL, default=false"` + SentinelMaster string `env:"STARHUB_SERVER_REDIS_SENTINEL_MASTER"` + SentinelEndpoint string `env:"STARHUB_SERVER_REDIS_SENTINEL_ENDPOINT"` } GitServer struct { - URL string `envconfig:"STARHUB_SERVER_GITSERVER_URL" default:"http://localhost:3000"` - Type string `envconfig:"STARHUB_SERVER_GITSERVER_TYPE" default:"gitea"` - Host string `envconfig:"STARHUB_SERVER_GITSERVER_HOST" default:"http://localhost:3000"` - SecretKey string `envconfig:"STARHUB_SERVER_GITSERVER_SECRET_KEY" default:"619c849c49e03754454ccd4cda79a209ce0b30b3"` - Username string `envconfig:"STARHUB_SERVER_GITSERVER_USERNAME" default:"root"` - Password string `envconfig:"STARHUB_SERVER_GITSERVER_PASSWORD" default:"password123"` - TimtoutSEC int `envconfig:"STARHUB_SERVER_GITSERVER_TIMEOUT_SEC" default:"5"` + URL string `env:"STARHUB_SERVER_GITSERVER_URL, default=http://localhost:3000"` + Type string `env:"STARHUB_SERVER_GITSERVER_TYPE, default=gitea"` + Host string `env:"STARHUB_SERVER_GITSERVER_HOST, default=http://localhost:3000"` + SecretKey string `env:"STARHUB_SERVER_GITSERVER_SECRET_KEY, default=619c849c49e03754454ccd4cda79a209ce0b30b3"` + Username string `env:"STARHUB_SERVER_GITSERVER_USERNAME, default=root"` + Password string `env:"STARHUB_SERVER_GITSERVER_PASSWORD, default=password123"` + TimeoutSEC int `env:"STARHUB_SERVER_GITSERVER_TIMEOUT_SEC, default=5"` } GitalyServer struct { - Address string `envconfig:"STARHUB_SERVER_GITALY_SERVER_SOCKET" default:"tcp://localhost:9999"` - Storge string `envconfig:"STARHUB_SERVER_GITALY_STORGE" default:"default"` - Token string `envconfig:"STARHUB_SERVER_GITALY_TOKEN" default:"abc123secret"` - JWTSecret string `envconfig:"STARHUB_SERVER_GITALY_JWT_SECRET" default:"signing-key"` + Address string `env:"STARHUB_SERVER_GITALY_SERVER_SOCKET, default=tcp://localhost:9999"` + Storge string `env:"STARHUB_SERVER_GITALY_STORGE, default=default"` + Token string `env:"STARHUB_SERVER_GITALY_TOKEN, default=abc123secret"` + JWTSecret string `env:"STARHUB_SERVER_GITALY_JWT_SECRET, default=signing-key"` } MirrorServer struct { - Enable bool `envconfig:"STARHUB_SERVER_MIRRORSERVER_ENABLE" default:"true"` - URL string `envconfig:"STARHUB_SERVER_MIRRORSERVER_URL" default:"http://localhost:3001"` - Type string `envconfig:"STARHUB_SERVER_MIRRORSERVER_TYPE" default:"gitea"` - Host string `envconfig:"STARHUB_SERVER_MIRRORSERVER_HOST" default:"http://localhost:3001"` - SecretKey string `envconfig:"STARHUB_SERVER_MIRRORSERVER_SECRET_KEY" default:"619c849c49e03754454ccd4cda79a209ce0b30b3"` - Username string `envconfig:"STARHUB_SERVER_MIRRORSERVER_USERNAME" default:"root"` - Password string `envconfig:"STARHUB_SERVER_MIRRORSERVER_PASSWORD" default:"password123"` + Enable bool `env:"STARHUB_SERVER_MIRRORSERVER_ENABLE, default=true"` + URL string `env:"STARHUB_SERVER_MIRRORSERVER_URL, default=http://localhost:3001"` + Type string `env:"STARHUB_SERVER_MIRRORSERVER_TYPE, default=gitea"` + Host string `env:"STARHUB_SERVER_MIRRORSERVER_HOST, default=http://localhost:3001"` + SecretKey string `env:"STARHUB_SERVER_MIRRORSERVER_SECRET_KEY, default=619c849c49e03754454ccd4cda79a209ce0b30b3"` + Username string `env:"STARHUB_SERVER_MIRRORSERVER_USERNAME, default=root"` + Password string `env:"STARHUB_SERVER_MIRRORSERVER_PASSWORD, default=password123"` } Frontend struct { - URL string `envconfig:"STARHUB_SERVER_FRONTEND_URL" default:"https://opencsg.com"` + URL string `env:"STARHUB_SERVER_FRONTEND_URL, default=https://opencsg.com"` } S3 struct { - SSL bool `envconfig:"STARHUB_SERVER_S3_SSL" default:"false"` - AccessKeyID string `envconfig:"STARHUB_SERVER_S3_ACCESS_KEY_ID"` - AccessKeySecret string `envconfig:"STARHUB_SERVER_S3_ACCESS_KEY_SECRET"` - Region string `envconfig:"STARHUB_SERVER_S3_REGION"` - Endpoint string `envconfig:"STARHUB_SERVER_S3_ENDPOINT" default:"localhost:9000"` + SSL bool `env:"STARHUB_SERVER_S3_SSL, default=false"` + AccessKeyID string `env:"STARHUB_SERVER_S3_ACCESS_KEY_ID"` + AccessKeySecret string `env:"STARHUB_SERVER_S3_ACCESS_KEY_SECRET"` + Region string `env:"STARHUB_SERVER_S3_REGION"` + Endpoint string `env:"STARHUB_SERVER_S3_ENDPOINT, default=localhost:9000"` //for better performance of LFS downloading from s3. (can ignore if S3.Endpoint is alreay an internal domain or ip address) - InternalEndpoint string `envconfig:"STARHUB_SERVER_S3_INTERNAL_ENDPOINT" default:""` - Bucket string `envconfig:"STARHUB_SERVER_S3_BUCKET" default:"opencsg-test"` - EnableSSL bool `envconfig:"STARHUB_SERVER_S3_ENABLE_SSL" default:"false"` + InternalEndpoint string `env:"STARHUB_SERVER_S3_INTERNAL_ENDPOINT, default="` + Bucket string `env:"STARHUB_SERVER_S3_BUCKET, default=opencsg-test"` + EnableSSL bool `env:"STARHUB_SERVER_S3_ENABLE_SSL, default=false"` } SensitiveCheck struct { - Enable bool `envconfig:"STARHUB_SERVER_SENSITIVE_CHECK_ENABLE" default:"false"` - AccessKeyID string `envconfig:"STARHUB_SERVER_SENSITIVE_CHECK_ACCESS_KEY_ID"` - AccessKeySecret string `envconfig:"STARHUB_SERVER_SENSITIVE_CHECK_ACCESS_KEY_SECRET"` - Region string `envconfig:"STARHUB_SERVER_SENSITIVE_CHECK_REGION"` - Endpoint string `envconfig:"STARHUB_SERVER_SENSITIVE_CHECK_ENDPOINT" default:"oss-cn-beijing.aliyuncs.com"` - EnableSSL bool `envconfig:"STARHUB_SERVER_S3_ENABLE_SSH" default:"true"` + Enable bool `env:"STARHUB_SERVER_SENSITIVE_CHECK_ENABLE, default=false"` + AccessKeyID string `env:"STARHUB_SERVER_SENSITIVE_CHECK_ACCESS_KEY_ID"` + AccessKeySecret string `env:"STARHUB_SERVER_SENSITIVE_CHECK_ACCESS_KEY_SECRET"` + Region string `env:"STARHUB_SERVER_SENSITIVE_CHECK_REGION"` + Endpoint string `env:"STARHUB_SERVER_SENSITIVE_CHECK_ENDPOINT, default=oss-cn-beijing.aliyuncs.com"` + EnableSSL bool `env:"STARHUB_SERVER_S3_ENABLE_SSH, default=true"` } JWT struct { - SigningKey string `envconfig:"STARHUB_JWT_SIGNING_KEY" default:"signing-key"` - ValidHour int `envconfig:"STARHUB_JWT_VALIDATE_HOUR" default:"24"` + SigningKey string `env:"STARHUB_JWT_SIGNING_KEY, default=signing-key"` + ValidHour int `env:"STARHUB_JWT_VALIDATE_HOUR, default=24"` } Inference struct { - ServerAddr string `envconfig:"STARHUB_SERVER_INFERENCE_SERVER_ADDR" default:"http://localhost:8000"` + ServerAddr string `env:"STARHUB_SERVER_INFERENCE_SERVER_ADDR, default=http://localhost:8000"` } Space struct { - BuilderEndpoint string `envconfig:"STARHUB_SERVER_SPACE_BUILDER_ENDPOINT" default:"http://localhost:8081"` + BuilderEndpoint string `env:"STARHUB_SERVER_SPACE_BUILDER_ENDPOINT, default=http://localhost:8081"` // base url for space api running in k8s cluster - RunnerEndpoint string `envconfig:"STARHUB_SERVER_SPACE_RUNNER_ENDPOINT" default:"http://localhost:8082"` - RunnerServerPort int `envconfig:"STARHUB_SERVER_SPACE_RUNNER_SERVER_PORT" default:"8082"` + RunnerEndpoint string `env:"STARHUB_SERVER_SPACE_RUNNER_ENDPOINT, default=http://localhost:8082"` + RunnerServerPort int `env:"STARHUB_SERVER_SPACE_RUNNER_SERVER_PORT, default=8082"` // the internal root domain will be proxied to, should be internal access only - InternalRootDomain string `envconfig:"STARHUB_SERVER_INTERNAL_ROOT_DOMAIN" default:"internal.example.com"` + InternalRootDomain string `env:"STARHUB_SERVER_INTERNAL_ROOT_DOMAIN, default=internal.example.com"` // the public root domain will be proxied from - PublicRootDomain string `envconfig:"STARHUB_SERVER_PUBLIC_ROOT_DOMAIN" default:"public.example.com"` - DockerRegBase string `envconfig:"STARHUB_SERVER_DOCKER_REG_BASE" default:"registry.cn-beijing.aliyuncs.com/opencsg_public/"` - ImagePullSecret string `envconfig:"STARHUB_SERVER_DOCKER_IMAGE_PULL_SECRET" default:"opencsg-pull-secret"` + PublicRootDomain string `env:"STARHUB_SERVER_PUBLIC_ROOT_DOMAIN, default=public.example.com"` + DockerRegBase string `env:"STARHUB_SERVER_DOCKER_REG_BASE, default=registry.cn-beijing.aliyuncs.com/opencsg_public/"` + ImagePullSecret string `env:"STARHUB_SERVER_DOCKER_IMAGE_PULL_SECRET, default=opencsg-pull-secret"` // reverse proxy listening port - RProxyServerPort int `envconfig:"STARHUB_SERVER_SPACE_RPROXY_SERVER_PORT" default:"8083"` + RProxyServerPort int `env:"STARHUB_SERVER_SPACE_RPROXY_SERVER_PORT, default=8083"` // secret key for session encryption - SessionSecretKey string `envconfig:"STARHUB_SERVER_SPACE_SESSION_SECRET_KEY" default:"secret"` - DeployTimeoutInMin int `envconfig:"STARHUB_SERVER_SPACE_DEPLOY_TIMEOUT_IN_MINUTES" default:"30"` + SessionSecretKey string `env:"STARHUB_SERVER_SPACE_SESSION_SECRET_KEY, default=secret"` + DeployTimeoutInMin int `env:"STARHUB_SERVER_SPACE_DEPLOY_TIMEOUT_IN_MINUTES, default=30"` // gpu model label - GPUModelLabel string `envconfig:"STARHUB_SERVER_GPU_MODEL_LABEL" default:"aliyun.accelerator/nvidia_name"` - ReadnessDelaySeconds int `envconfig:"STARHUB_SERVER_READNESS_DELAY_SECONDS" default:"120"` - ReadnessPeriodSeconds int `envconfig:"STARHUB_SERVER_READNESS_PERIOD_SECONDS" default:"10"` - ReadnessFailureThreshold int `envconfig:"STARHUB_SERVER_READNESS_FAILURE_THRESHOLD" default:"3"` + GPUModelLabel string `env:"STARHUB_SERVER_GPU_MODEL_LABEL, default=aliyun.accelerator/nvidia_name"` + ReadnessDelaySeconds int `env:"STARHUB_SERVER_READNESS_DELAY_SECONDS, default=120"` + ReadnessPeriodSeconds int `env:"STARHUB_SERVER_READNESS_PERIOD_SECONDS, default=10"` + ReadnessFailureThreshold int `env:"STARHUB_SERVER_READNESS_FAILURE_THRESHOLD, default=3"` } Model struct { - DeployTimeoutInMin int `envconfig:"STARHUB_SERVER_MODEL_DEPLOY_TIMEOUT_IN_MINUTES" default:"60"` - DownloadEndpoint string `envconfig:"STARHUB_SERVER_MODEL_DOWNLOAD_ENDPOINT" default:"https://hub.opencsg.com"` - DockerRegBase string `envconfig:"STARHUB_SERVER_MODEL_DOCKER_REG_BASE" default:"opencsg-registry.cn-beijing.cr.aliyuncs.com/public/"` - NimDockerSecretName string `envconfig:"STARHUB_SERVER_MODEL_NIM_DOCKER_SECRET_NAME" default:"ngc-secret"` - NimNGCSecretName string `envconfig:"STARHUB_SERVER_MODEL_NIM_NGC_SECRET_NAME" default:"nvidia-nim-secrets"` + DeployTimeoutInMin int `env:"STARHUB_SERVER_MODEL_DEPLOY_TIMEOUT_IN_MINUTES, default=60"` + DownloadEndpoint string `env:"STARHUB_SERVER_MODEL_DOWNLOAD_ENDPOINT, default=https://hub.opencsg.com"` + DockerRegBase string `env:"STARHUB_SERVER_MODEL_DOCKER_REG_BASE, default=opencsg-registry.cn-beijing.cr.aliyuncs.com/public/"` + NimDockerSecretName string `env:"STARHUB_SERVER_MODEL_NIM_DOCKER_SECRET_NAME, default=ngc-secret"` + NimNGCSecretName string `env:"STARHUB_SERVER_MODEL_NIM_NGC_SECRET_NAME, default=nvidia-nim-secrets"` } // send events Event struct { - SyncInterval int `envconfig:"STARHUB_SERVER_SYNC_IN_MINUTES" default:"1"` + SyncInterval int `env:"STARHUB_SERVER_SYNC_IN_MINUTES, default=1"` } Casdoor struct { - ClientID string `envconfig:"STARHUB_SERVER_CASDOOR_CLIENT_ID" default:"client_id"` - ClientSecret string `envconfig:"STARHUB_SERVER_CASDOOR_CLIENT_SECRET" default:"client_secret"` - Endpoint string `envconfig:"STARHUB_SERVER_CASDOOR_ENDPOINT" default:"http://localhost:80"` - Certificate string `envconfig:"STARHUB_SERVER_CASDOOR_CERTIFICATE" default:"/etc/casdoor/certificate.pem"` - OrganizationName string `envconfig:"STARHUB_SERVER_CASDOOR_ORGANIZATION_NAME" default:"opencsg"` - ApplicationName string `envconfig:"STARHUB_SERVER_CASDOOR_APPLICATION_NAME" default:"opencsg"` + ClientID string `env:"STARHUB_SERVER_CASDOOR_CLIENT_ID, default=client_id"` + ClientSecret string `env:"STARHUB_SERVER_CASDOOR_CLIENT_SECRET, default=client_secret"` + Endpoint string `env:"STARHUB_SERVER_CASDOOR_ENDPOINT, default=http://localhost:80"` + Certificate string `env:"STARHUB_SERVER_CASDOOR_CERTIFICATE, default=/etc/casdoor/certificate.pem"` + OrganizationName string `env:"STARHUB_SERVER_CASDOOR_ORGANIZATION_NAME, default=opencsg"` + ApplicationName string `env:"STARHUB_SERVER_CASDOOR_APPLICATION_NAME, default=opencsg"` } Nats struct { - URL string `envconfig:"OPENCSG_ACCOUNTING_NATS_URL" default:"nats://account:g98dc5FA8v4J7ck90w@natsmaster:4222"` - MsgFetchTimeoutInSEC int `envconfig:"OPENCSG_ACCOUNTING_MSG_FETCH_TIMEOUTINSEC" default:"5"` - MeterRequestSubject string `envconfig:"OPENCSG_ACCOUNTING_METER_EVENT_SUBJECT" default:"accounting.metering.>"` - MeterDurationSendSubject string `envconfig:"STARHUB_SERVER_METER_DURATION_SEND_SUBJECT" default:"accounting.metering.duration"` - MeterTokenSendSubject string `envconfig:"STARHUB_SERVER_METER_TOKEN_SEND_SUBJECT" default:"accounting.metering.token"` - MeterQuotaSendSubject string `envconfig:"STARHUB_SERVER_METER_QUOTA_SEND_SUBJECT" default:"accounting.metering.quota"` + URL string `env:"OPENCSG_ACCOUNTING_NATS_URL, default=nats://account:g98dc5FA8v4J7ck90w@natsmaster:4222"` + MsgFetchTimeoutInSEC int `env:"OPENCSG_ACCOUNTING_MSG_FETCH_TIMEOUTINSEC, default=5"` + MeterRequestSubject string `env:"OPENCSG_ACCOUNTING_METER_EVENT_SUBJECT, default=accounting.metering.>"` + MeterDurationSendSubject string `env:"STARHUB_SERVER_METER_DURATION_SEND_SUBJECT, default=accounting.metering.duration"` + MeterTokenSendSubject string `env:"STARHUB_SERVER_METER_TOKEN_SEND_SUBJECT, default=accounting.metering.token"` + MeterQuotaSendSubject string `env:"STARHUB_SERVER_METER_QUOTA_SEND_SUBJECT, default=accounting.metering.quota"` } Accounting struct { - Host string `envconfig:"OPENCSG_ACCOUNTING_SERVER_HOST" default:"http://localhost"` - Port int `envconfig:"OPENCSG_ACCOUNTING_SERVER_PORT" default:"8086"` + Host string `env:"OPENCSG_ACCOUNTING_SERVER_HOST, default=http://localhost"` + Port int `env:"OPENCSG_ACCOUNTING_SERVER_PORT, default=8086"` } User struct { - Host string `envconfig:"OPENCSG_USER_SERVER_HOST" default:"http://localhost"` - Port int `envconfig:"OPENCSG_USER_SERVER_PORT" default:"8088"` - SigninSuccessRedirectURL string `envconfig:"OPENCSG_USER_SERVER_SIGNIN_SUCCESS_REDIRECT_URL" default:"http://localhost:3000/server/callback"` + Host string `env:"OPENCSG_USER_SERVER_HOST, default=http://localhost"` + Port int `env:"OPENCSG_USER_SERVER_PORT, default=8088"` + SigninSuccessRedirectURL string `env:"OPENCSG_USER_SERVER_SIGNIN_SUCCESS_REDIRECT_URL, default=http://localhost:3000/server/callback"` } MultiSync struct { - SaasAPIDomain string `envconfig:"OPENCSG_SAAS_API_DOMAIN" default:"https://hub.opencsg.com"` - SaasSyncDomain string `envconfig:"OPENCSG_SAAS_SYNC_DOMAIN" default:"https://sync.opencsg.com"` - Enabled bool `envconfig:"STARHUB_SERVER_MULTI_SYNC_ENABLED" default:"true"` + SaasAPIDomain string `env:"OPENCSG_SAAS_API_DOMAIN, default=https://hub.opencsg.com"` + SaasSyncDomain string `env:"OPENCSG_SAAS_SYNC_DOMAIN, default=https://sync.opencsg.com"` + Enabled bool `env:"STARHUB_SERVER_MULTI_SYNC_ENABLED, default=true"` } Telemetry struct { - Enable bool `envconfig:"STARHUB_SERVER_TELEMETRY_ENABLE" default:"true"` - ReportURL string `envconfig:"STARHUB_SERVER_TELEMETRY_URL" default:"http://hub.opencsg.com/api/v1/telemetry"` + Enable bool `env:"STARHUB_SERVER_TELEMETRY_ENABLE, default=true"` + ReportURL string `env:"STARHUB_SERVER_TELEMETRY_URL, default=http://hub.opencsg.com/api/v1/telemetry"` } AutoClean struct { - Instance bool `envconfig:"OPENCSG_AUTO_CLEANUP_INSTANCE_ENABLE" default:"false"` + Instance bool `env:"OPENCSG_AUTO_CLEANUP_INSTANCE_ENABLE, default=false"` } Dataset struct { - PromptMaxJsonlFileSize int64 `envconfig:"OPENCSG_PROMPT_MAX_JSONL_FILESIZE_BYTES" default:"1048576"` // 1MB + PromptMaxJsonlFileSize int64 `env:"OPENCSG_PROMPT_MAX_JSONL_FILESIZE_BYTES, default=1048576"` // 1MB } Dataflow struct { - Host string `envconfig:"OPENCSG_DATAFLOW_SERVER_HOST" default:"http://127.0.0.1"` - Port int `envconfig:"OPENCSG_DATAFLOW_SERVER_PORT" default:"8000"` + Host string `env:"OPENCSG_DATAFLOW_SERVER_HOST, default=http://127.0.0.1"` + Port int `env:"OPENCSG_DATAFLOW_SERVER_PORT, default=8000"` } Moderation struct { - Host string `envconfig:"OPENCSG_MODERATION_SERVER_HOST" default:"http://localhost"` - Port int `envconfig:"OPENCSG_MODERATION_SERVER_PORT" default:"8089"` + Host string `env:"OPENCSG_MODERATION_SERVER_HOST, default=http://localhost"` + Port int `env:"OPENCSG_MODERATION_SERVER_PORT, default=8089"` // comma splitted, and base64 encoded - EncodedSensitiveWords string `envconfig:"OPENCSG_MODERATION_SERVER_ENCODED_SENSITIVE_WORDS" default:"5Lmg6L+R5bmzLHhpamlucGluZw=="` + EncodedSensitiveWords string `env:"OPENCSG_MODERATION_SERVER_ENCODED_SENSITIVE_WORDS, default=5Lmg6L+R5bmzLHhpamlucGluZw=="` } WorkFLow struct { - Endpoint string `envconfig:"OPENCSG_WORKFLOW_SERVER_ENDPOINT" default:"localhost:7233"` + Endpoint string `env:"OPENCSG_WORKFLOW_SERVER_ENDPOINT, default=localhost:7233"` } } -func LoadConfig() (cfg *Config, err error) { - cfg = new(Config) - err = envconfig.Process("", cfg) - if err != nil { - return - } +func SetConfigFile(file string) { + configFile = file +} - return +func LoadConfig() (*Config, error) { + cfg := &Config{} + + if configFile != "" { + f, err := os.Open(configFile) + if err != nil { + return nil, err + } + err = toml.NewDecoder(f).Decode(cfg) + if err != nil { + return nil, err + } + } + + // Always read environment variables, even if a config file exists. If a config value is present in both the + // config file and the environment, the environment value takes priority. If a config value is missing from + // the config file, the default value (specified by the struct field's default tag) will be used. + err := envconfig.ProcessWith(context.Background(), &envconfig.Config{ + Target: cfg, + DefaultOverwrite: true, + }) + return cfg, err } diff --git a/common/config/config.toml.example b/common/config/config.toml.example new file mode 100644 index 00000000..bdbba68a --- /dev/null +++ b/common/config/config.toml.example @@ -0,0 +1,174 @@ +[saas] +enabled = false + +[instance] +id = "" + +[swagger] +enabled = false + +[api] +token = "0c11e6e4f2054444374ba3f0b70de4145935a7312289d404814cd5907c6aa93cc65cd35dbf94e04c13a3dedbf51f1694de84240c8acb7238b54a2c3ac8e87c59" + +[https] +enabled = false + +[api_server] +port = 8080 +public_domain = "http://localhost:8080" +ssh_domain = "git@localhost:2222" + +[mirror] +url = "http://localhost:8085" +token = "" +port = 8085 +session_secret_key = "mirror" +worker_number = 5 + +[docs_host] +url = "http://localhost:6636" + +[database] +driver = "pg" +dsn = "postgresql://postgres:postgres@localhost:5432/starhub_server?sslmode=disable" +timezone = "Asia/Shanghai" + +[redis] +endpoint = "localhost:6379" +max_retries = 3 +min_idle_connections = 0 +user = "" +password = "" +sentinel_mode = false +sentinel_master = "" +sentinel_endpoint = "" + +[git_server] +url = "http://localhost:3000" +type = "gitea" +host = "http://localhost:3000" +secret_key = "619c849c49e03754454ccd4cda79a209ce0b30b3" +username = "root" +password = "password123" +timeout_sec = 5 + +[gitaly_server] +address = "tcp://localhost:9999" +storage = "default" +token = "abc123secret" +jwt_secret = "signing-key" + +[mirror_server] +enabled = true +url = "http://localhost:3001" +type = "gitea" +host = "http://localhost:3001" +secret_key = "619c849c49e03754454ccd4cda79a209ce0b30b3" +username = "root" +password = "password123" + +[frontend] +url = "https://opencsg.com" + +[s3] +ssl = false +access_key_id = "" +access_key_secret = "" +region = "" +endpoint = "localhost:9000" +internal_endpoint = "" +bucket = "opencsg-test" +enable_ssl = false + +[sensitive_check] +enabled = false +access_key_id = "" +access_key_secret = "" +region = "" +endpoint = "oss-cn-beijing.aliyuncs.com" +enable_ssl = true + +[jwt] +signing_key = "signing-key" +valid_hour = 24 + +[inference] +server_addr = "http://localhost:8000" + +[space] +builder_endpoint = "http://localhost:8081" +runner_endpoint = "http://localhost:8082" +runner_server_port = 8082 +internal_root_domain = "internal.example.com" +public_root_domain = "public.example.com" +docker_reg_base = "registry.cn-beijing.aliyuncs.com/opencsg_public/" +image_pull_secret = "opencsg-pull-secret" +rproxy_server_port = 8083 +session_secret_key = "secret" +deploy_timeout_in_min = 30 +gpu_model_label = "aliyun.accelerator/nvidia_name" +readiness_delay_seconds = 120 +readiness_period_seconds = 10 +readiness_failure_threshold = 3 + +[model] +deploy_timeout_in_min = 60 +download_endpoint = "https://hub.opencsg.com" +docker_reg_base = "opencsg-registry.cn-beijing.cr.aliyuncs.com/public/" +nim_docker_secret_name = "ngc-secret" +nim_ngc_secret_name = "nvidia-nim-secrets" + +[event] +sync_interval = 1 + +[casdoor] +client_id = "client_id" +client_secret = "client_secret" +endpoint = "http://localhost:80" +certificate = "/etc/casdoor/certificate.pem" +organization_name = "opencsg" +application_name = "opencsg" + +[nats] +url = "nats://account:g98dc5FA8v4J7ck90w@natsmaster:4222" +msg_fetch_timeout_in_sec = 5 +meter_request_subject = "accounting.metering.>" +meter_duration_send_subject = "accounting.metering.duration" +meter_token_send_subject = "accounting.metering.token" +meter_quota_send_subject = "accounting.metering.quota" + +[accounting] +host = "http://localhost" +port = 8086 + +[user] +host = "http://localhost" +port = 8088 +signin_success_redirect_url = "http://localhost:3000/server/callback" + +[multi_sync] +saas_api_domain = "https://hub.opencsg.com" +saas_sync_domain = "https://sync.opencsg.com" +enabled = true + +[telemetry] +enabled = true +report_url = "http://hub.opencsg.com/api/v1/telemetry" + +[auto_clean] +instance = false + +[dataset] +prompt_max_jsonl_file_size = 1048576 + +[dataflow] +host = "http://127.0.0.1" +port = 8000 + +[moderation] +host = "http://localhost" +port = 8089 +encoded_sensitive_words = "5Lmg6L+R5bmzLHhpamlucGluZw==" + +[workflow] +endpoint = "localhost:7233" diff --git a/common/config/config_test.go b/common/config/config_test.go new file mode 100644 index 00000000..c72203a8 --- /dev/null +++ b/common/config/config_test.go @@ -0,0 +1,41 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestConfig_LoadConfig(t *testing.T) { + t.Run("config env", func(t *testing.T) { + t.Setenv("STARHUB_SERVER_INSTANCE_ID", "foo") + t.Setenv("STARHUB_SERVER_SERVER_PORT", "6789") + cfg, err := LoadConfig() + require.Nil(t, err) + + require.Equal(t, "foo", cfg.InstanceID) + require.Equal(t, 6789, cfg.APIServer.Port) + require.Equal(t, "git@localhost:2222", cfg.APIServer.SSHDomain) + }) + + t.Run("config file", func(t *testing.T) { + SetConfigFile("test.toml") + cfg, err := LoadConfig() + require.Nil(t, err) + + require.Equal(t, "bar", cfg.InstanceID) + require.Equal(t, 4321, cfg.APIServer.Port) + require.Equal(t, "git@localhost:2222", cfg.APIServer.SSHDomain) + }) + + t.Run("file and env", func(t *testing.T) { + SetConfigFile("test.toml") + t.Setenv("STARHUB_SERVER_INSTANCE_ID", "foobar") + cfg, err := LoadConfig() + require.Nil(t, err) + + require.Equal(t, "foobar", cfg.InstanceID) + require.Equal(t, 4321, cfg.APIServer.Port) + require.Equal(t, "git@localhost:2222", cfg.APIServer.SSHDomain) + }) +} diff --git a/common/config/test.toml b/common/config/test.toml new file mode 100644 index 00000000..8d2f2d57 --- /dev/null +++ b/common/config/test.toml @@ -0,0 +1,4 @@ +instance_id = "bar" + +[api_server] +port = 4321 diff --git a/go.mod b/go.mod index 1f1d2f85..1c035042 100644 --- a/go.mod +++ b/go.mod @@ -18,12 +18,14 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f - github.com/kelseyhightower/envconfig v1.4.0 github.com/marcboeker/go-duckdb v1.5.6 github.com/minio/minio-go/v7 v7.0.66 github.com/minio/sha256-simd v1.0.1 + github.com/naoina/toml v0.1.1 github.com/redis/go-redis/v9 v9.3.0 + github.com/sethvargo/go-envconfig v1.1.0 github.com/spf13/cobra v1.8.0 + github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.2 @@ -73,6 +75,7 @@ require ( github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 // indirect github.com/lightstep/lightstep-tracer-go v0.25.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nexus-rpc/sdk-go v0.0.11 // indirect @@ -90,7 +93,6 @@ require ( github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a // indirect github.com/shirou/gopsutil/v3 v3.21.12 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.9.0 // indirect github.com/tinylib/msgp v1.1.2 // indirect github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect diff --git a/go.sum b/go.sum index 4aa0dc9c..8820611f 100644 --- a/go.sum +++ b/go.sum @@ -328,8 +328,6 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= @@ -348,6 +346,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= @@ -392,6 +392,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8= +github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/nats.go v1.35.0 h1:XFNqNM7v5B+MQMKqVGAyHwYhyKb48jrenXNxIU20ULk= github.com/nats-io/nats.go v1.35.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= @@ -470,6 +474,8 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0= +github.com/sethvargo/go-envconfig v1.1.0 h1:cWZiJxeTm7AlCvzGXrEXaSTCNgip5oJepekh/BOQuog= +github.com/sethvargo/go-envconfig v1.1.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= github.com/shirou/gopsutil/v3 v3.21.2/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=