mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 14:50:55 +03:00
config: manually set viper defaults
so we can override config via env var even without a configuration file Fixes #208
This commit is contained in:
@@ -165,6 +165,7 @@ func init() {
|
|||||||
replacer := strings.NewReplacer(".", "__")
|
replacer := strings.NewReplacer(".", "__")
|
||||||
viper.SetEnvKeyReplacer(replacer)
|
viper.SetEnvKeyReplacer(replacer)
|
||||||
viper.SetConfigName(DefaultConfigName)
|
viper.SetConfigName(DefaultConfigName)
|
||||||
|
setViperDefaults()
|
||||||
viper.AutomaticEnv()
|
viper.AutomaticEnv()
|
||||||
viper.AllowEmptyEnv(true)
|
viper.AllowEmptyEnv(true)
|
||||||
}
|
}
|
||||||
@@ -252,10 +253,8 @@ func LoadConfig(configDir, configName string) error {
|
|||||||
viper.AddConfigPath(".")
|
viper.AddConfigPath(".")
|
||||||
viper.SetConfigName(configName)
|
viper.SetConfigName(configName)
|
||||||
if err = viper.ReadInConfig(); err != nil {
|
if err = viper.ReadInConfig(); err != nil {
|
||||||
logger.Warn(logSender, "", "error loading configuration file: %v. Default configuration will be used: %+v",
|
logger.Warn(logSender, "", "error loading configuration file: %v", err)
|
||||||
err, getRedactedGlobalConf())
|
logger.WarnToConsole("error loading configuration file: %v", err)
|
||||||
logger.WarnToConsole("error loading configuration file: %v. Default configuration will be used.", err)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
err = viper.Unmarshal(&globalConf)
|
err = viper.Unmarshal(&globalConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -349,3 +348,91 @@ func checkCommonParamsCompatibility() {
|
|||||||
globalConf.Common.ProxyAllowed = globalConf.SFTPD.ProxyAllowed //nolint:staticcheck
|
globalConf.Common.ProxyAllowed = globalConf.SFTPD.ProxyAllowed //nolint:staticcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setViperDefaults() {
|
||||||
|
viper.SetDefault("common.idle_timeout", globalConf.Common.IdleTimeout)
|
||||||
|
viper.SetDefault("common.upload_mode", globalConf.Common.UploadMode)
|
||||||
|
viper.SetDefault("common.actions.execute_on", globalConf.Common.Actions.ExecuteOn)
|
||||||
|
viper.SetDefault("common.actions.hook", globalConf.Common.Actions.Hook)
|
||||||
|
viper.SetDefault("common.setstat_mode", globalConf.Common.SetstatMode)
|
||||||
|
viper.SetDefault("common.proxy_protocol", globalConf.Common.ProxyProtocol)
|
||||||
|
viper.SetDefault("common.proxy_allowed", globalConf.Common.ProxyAllowed)
|
||||||
|
viper.SetDefault("common.post_connect_hook", globalConf.Common.PostConnectHook)
|
||||||
|
viper.SetDefault("sftpd.bind_port", globalConf.SFTPD.BindPort)
|
||||||
|
viper.SetDefault("sftpd.bind_address", globalConf.SFTPD.BindAddress)
|
||||||
|
viper.SetDefault("sftpd.max_auth_tries", globalConf.SFTPD.MaxAuthTries)
|
||||||
|
viper.SetDefault("sftpd.banner", globalConf.SFTPD.Banner)
|
||||||
|
viper.SetDefault("sftpd.host_keys", globalConf.SFTPD.HostKeys)
|
||||||
|
viper.SetDefault("sftpd.kex_algorithms", globalConf.SFTPD.KexAlgorithms)
|
||||||
|
viper.SetDefault("sftpd.ciphers", globalConf.SFTPD.Ciphers)
|
||||||
|
viper.SetDefault("sftpd.macs", globalConf.SFTPD.MACs)
|
||||||
|
viper.SetDefault("sftpd.trusted_user_ca_keys", globalConf.SFTPD.TrustedUserCAKeys)
|
||||||
|
viper.SetDefault("sftpd.login_banner_file", globalConf.SFTPD.LoginBannerFile)
|
||||||
|
viper.SetDefault("sftpd.enabled_ssh_commands", globalConf.SFTPD.EnabledSSHCommands)
|
||||||
|
viper.SetDefault("sftpd.keyboard_interactive_auth_hook", globalConf.SFTPD.KeyboardInteractiveHook)
|
||||||
|
viper.SetDefault("sftpd.password_authentication", globalConf.SFTPD.PasswordAuthentication)
|
||||||
|
viper.SetDefault("ftpd.bind_port", globalConf.FTPD.BindPort)
|
||||||
|
viper.SetDefault("ftpd.bind_address", globalConf.FTPD.BindAddress)
|
||||||
|
viper.SetDefault("ftpd.banner", globalConf.FTPD.Banner)
|
||||||
|
viper.SetDefault("ftpd.banner_file", globalConf.FTPD.BannerFile)
|
||||||
|
viper.SetDefault("ftpd.active_transfers_port_non_20", globalConf.FTPD.ActiveTransfersPortNon20)
|
||||||
|
viper.SetDefault("ftpd.force_passive_ip", globalConf.FTPD.ForcePassiveIP)
|
||||||
|
viper.SetDefault("ftpd.passive_port_range.start", globalConf.FTPD.PassivePortRange.Start)
|
||||||
|
viper.SetDefault("ftpd.passive_port_range.end", globalConf.FTPD.PassivePortRange.End)
|
||||||
|
viper.SetDefault("ftpd.certificate_file", globalConf.FTPD.CertificateFile)
|
||||||
|
viper.SetDefault("ftpd.certificate_key_file", globalConf.FTPD.CertificateKeyFile)
|
||||||
|
viper.SetDefault("ftpd.tls_mode", globalConf.FTPD.TLSMode)
|
||||||
|
viper.SetDefault("webdavd.bind_port", globalConf.WebDAVD.BindPort)
|
||||||
|
viper.SetDefault("webdavd.bind_address", globalConf.WebDAVD.BindAddress)
|
||||||
|
viper.SetDefault("webdavd.certificate_file", globalConf.WebDAVD.CertificateFile)
|
||||||
|
viper.SetDefault("webdavd.certificate_key_file", globalConf.WebDAVD.CertificateKeyFile)
|
||||||
|
viper.SetDefault("webdavd.cors.enabled", globalConf.WebDAVD.Cors.Enabled)
|
||||||
|
viper.SetDefault("webdavd.cors.allowed_origins", globalConf.WebDAVD.Cors.AllowedOrigins)
|
||||||
|
viper.SetDefault("webdavd.cors.allowed_methods", globalConf.WebDAVD.Cors.AllowedMethods)
|
||||||
|
viper.SetDefault("webdavd.cors.allowed_headers", globalConf.WebDAVD.Cors.AllowedHeaders)
|
||||||
|
viper.SetDefault("webdavd.cors.exposed_headers", globalConf.WebDAVD.Cors.ExposedHeaders)
|
||||||
|
viper.SetDefault("webdavd.cors.allow_credentials", globalConf.WebDAVD.Cors.AllowCredentials)
|
||||||
|
viper.SetDefault("webdavd.cors.max_age", globalConf.WebDAVD.Cors.MaxAge)
|
||||||
|
viper.SetDefault("webdavd.cache.enabled", globalConf.WebDAVD.Cache.Enabled)
|
||||||
|
viper.SetDefault("webdavd.cache.expiration_time", globalConf.WebDAVD.Cache.ExpirationTime)
|
||||||
|
viper.SetDefault("webdavd.cache.max_size", globalConf.WebDAVD.Cache.MaxSize)
|
||||||
|
viper.SetDefault("data_provider.driver", globalConf.ProviderConf.Driver)
|
||||||
|
viper.SetDefault("data_provider.name", globalConf.ProviderConf.Name)
|
||||||
|
viper.SetDefault("data_provider.host", globalConf.ProviderConf.Host)
|
||||||
|
viper.SetDefault("data_provider.port", globalConf.ProviderConf.Port)
|
||||||
|
viper.SetDefault("data_provider.username", globalConf.ProviderConf.Username)
|
||||||
|
viper.SetDefault("data_provider.password", globalConf.ProviderConf.Password)
|
||||||
|
viper.SetDefault("data_provider.sslmode", globalConf.ProviderConf.SSLMode)
|
||||||
|
viper.SetDefault("data_provider.connection_string", globalConf.ProviderConf.ConnectionString)
|
||||||
|
viper.SetDefault("data_provider.sql_tables_prefix", globalConf.ProviderConf.SQLTablesPrefix)
|
||||||
|
viper.SetDefault("data_provider.manage_users", globalConf.ProviderConf.ManageUsers)
|
||||||
|
viper.SetDefault("data_provider.track_quota", globalConf.ProviderConf.TrackQuota)
|
||||||
|
viper.SetDefault("data_provider.pool_size", globalConf.ProviderConf.PoolSize)
|
||||||
|
viper.SetDefault("data_provider.users_base_dir", globalConf.ProviderConf.UsersBaseDir)
|
||||||
|
viper.SetDefault("data_provider.actions.execute_on", globalConf.ProviderConf.Actions.ExecuteOn)
|
||||||
|
viper.SetDefault("data_provider.actions.hook", globalConf.ProviderConf.Actions.Hook)
|
||||||
|
viper.SetDefault("data_provider.external_auth_hook", globalConf.ProviderConf.ExternalAuthHook)
|
||||||
|
viper.SetDefault("data_provider.external_auth_scope", globalConf.ProviderConf.ExternalAuthScope)
|
||||||
|
viper.SetDefault("data_provider.credentials_path", globalConf.ProviderConf.CredentialsPath)
|
||||||
|
viper.SetDefault("data_provider.prefer_database_credentials", globalConf.ProviderConf.PreferDatabaseCredentials)
|
||||||
|
viper.SetDefault("data_provider.pre_login_hook", globalConf.ProviderConf.PreLoginHook)
|
||||||
|
viper.SetDefault("data_provider.post_login_hook", globalConf.ProviderConf.PostLoginHook)
|
||||||
|
viper.SetDefault("data_provider.post_login_scope", globalConf.ProviderConf.PostLoginScope)
|
||||||
|
viper.SetDefault("data_provider.check_password_hook", globalConf.ProviderConf.CheckPasswordHook)
|
||||||
|
viper.SetDefault("data_provider.check_password_scope", globalConf.ProviderConf.CheckPasswordScope)
|
||||||
|
viper.SetDefault("data_provider.password_hashing.argon2_options.memory", globalConf.ProviderConf.PasswordHashing.Argon2Options.Memory)
|
||||||
|
viper.SetDefault("data_provider.password_hashing.argon2_options.iterations", globalConf.ProviderConf.PasswordHashing.Argon2Options.Iterations)
|
||||||
|
viper.SetDefault("data_provider.password_hashing.argon2_options.parallelism", globalConf.ProviderConf.PasswordHashing.Argon2Options.Parallelism)
|
||||||
|
viper.SetDefault("data_provider.update_mode", globalConf.ProviderConf.UpdateMode)
|
||||||
|
viper.SetDefault("httpd.bind_port", globalConf.HTTPDConfig.BindPort)
|
||||||
|
viper.SetDefault("httpd.bind_address", globalConf.HTTPDConfig.BindAddress)
|
||||||
|
viper.SetDefault("httpd.templates_path", globalConf.HTTPDConfig.TemplatesPath)
|
||||||
|
viper.SetDefault("httpd.static_files_path", globalConf.HTTPDConfig.StaticFilesPath)
|
||||||
|
viper.SetDefault("httpd.backups_path", globalConf.HTTPDConfig.BackupsPath)
|
||||||
|
viper.SetDefault("httpd.auth_user_file", globalConf.HTTPDConfig.AuthUserFile)
|
||||||
|
viper.SetDefault("httpd.certificate_file", globalConf.HTTPDConfig.CertificateFile)
|
||||||
|
viper.SetDefault("httpd.certificate_key_file", globalConf.HTTPDConfig.CertificateKeyFile)
|
||||||
|
viper.SetDefault("http.timeout", globalConf.HTTPConfig.Timeout)
|
||||||
|
viper.SetDefault("http.ca_certificates", globalConf.HTTPConfig.CACertificates)
|
||||||
|
viper.SetDefault("http.skip_tls_verify", globalConf.HTTPConfig.SkipTLSVerify)
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ func TestLoadConfigTest(t *testing.T) {
|
|||||||
confName := tempConfigName + ".json"
|
confName := tempConfigName + ".json"
|
||||||
configFilePath := filepath.Join(configDir, confName)
|
configFilePath := filepath.Join(configDir, confName)
|
||||||
err = config.LoadConfig(configDir, tempConfigName)
|
err = config.LoadConfig(configDir, tempConfigName)
|
||||||
assert.NotNil(t, err)
|
assert.NoError(t, err)
|
||||||
err = ioutil.WriteFile(configFilePath, []byte("{invalid json}"), os.ModePerm)
|
err = ioutil.WriteFile(configFilePath, []byte("{invalid json}"), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = config.LoadConfig(configDir, tempConfigName)
|
err = config.LoadConfig(configDir, tempConfigName)
|
||||||
assert.NotNil(t, err)
|
assert.NoError(t, err)
|
||||||
err = ioutil.WriteFile(configFilePath, []byte("{\"sftpd\": {\"bind_port\": \"a\"}}"), os.ModePerm)
|
err = ioutil.WriteFile(configFilePath, []byte("{\"sftpd\": {\"bind_port\": \"a\"}}"), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = config.LoadConfig(configDir, tempConfigName)
|
err = config.LoadConfig(configDir, tempConfigName)
|
||||||
@@ -280,3 +280,25 @@ func TestSetGetConfig(t *testing.T) {
|
|||||||
assert.Equal(t, webDavConf.CertificateFile, config.GetWebDAVDConfig().CertificateFile)
|
assert.Equal(t, webDavConf.CertificateFile, config.GetWebDAVDConfig().CertificateFile)
|
||||||
assert.Equal(t, webDavConf.CertificateKeyFile, config.GetWebDAVDConfig().CertificateKeyFile)
|
assert.Equal(t, webDavConf.CertificateKeyFile, config.GetWebDAVDConfig().CertificateKeyFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigFromEnv(t *testing.T) {
|
||||||
|
os.Setenv("SFTPGO_SFTPD__BIND_ADDRESS", "127.0.0.1")
|
||||||
|
os.Setenv("SFTPGO_DATA_PROVIDER__PASSWORD_HASHING__ARGON2_OPTIONS__ITERATIONS", "41")
|
||||||
|
os.Setenv("SFTPGO_DATA_PROVIDER__POOL_SIZE", "10")
|
||||||
|
os.Setenv("SFTPGO_DATA_PROVIDER__ACTIONS__EXECUTE_ON", "add")
|
||||||
|
t.Cleanup(func() {
|
||||||
|
os.Unsetenv("SFTPGO_SFTPD__BIND_ADDRESS")
|
||||||
|
os.Unsetenv("SFTPGO_DATA_PROVIDER__PASSWORD_HASHING__ARGON2_OPTIONS__ITERATIONS")
|
||||||
|
os.Unsetenv("SFTPGO_DATA_PROVIDER__POOL_SIZE")
|
||||||
|
os.Unsetenv("SFTPGO_DATA_PROVIDER__ACTIONS__EXECUTE_ON")
|
||||||
|
})
|
||||||
|
err := config.LoadConfig(".", "invalid config")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
sftpdConfig := config.GetSFTPDConfig()
|
||||||
|
assert.Equal(t, "127.0.0.1", sftpdConfig.BindAddress)
|
||||||
|
dataProviderConf := config.GetProviderConf()
|
||||||
|
assert.Equal(t, uint32(41), dataProviderConf.PasswordHashing.Argon2Options.Iterations)
|
||||||
|
assert.Equal(t, 10, dataProviderConf.PoolSize)
|
||||||
|
assert.Len(t, dataProviderConf.Actions.ExecuteOn, 1)
|
||||||
|
assert.Contains(t, dataProviderConf.Actions.ExecuteOn, "add")
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ For each account, the following properties can be configured:
|
|||||||
- `allowed_extensions`, list of, case insensitive, allowed files extension. Shell like expansion is not supported so you have to specify `.jpg` and not `*.jpg`. Any file that does not end with this suffix will be denied
|
- `allowed_extensions`, list of, case insensitive, allowed files extension. Shell like expansion is not supported so you have to specify `.jpg` and not `*.jpg`. Any file that does not end with this suffix will be denied
|
||||||
- `denied_extensions`, list of, case insensitive, denied files extension. Denied file extensions are evaluated before the allowed ones
|
- `denied_extensions`, list of, case insensitive, denied files extension. Denied file extensions are evaluated before the allowed ones
|
||||||
- `path`, SFTP/SCP path, if no other specific filter is defined, the filter apply for sub directories too. For example if filters are defined for the paths `/` and `/sub` then the filters for `/` are applied for any file outside the `/sub` directory
|
- `path`, SFTP/SCP path, if no other specific filter is defined, the filter apply for sub directories too. For example if filters are defined for the paths `/` and `/sub` then the filters for `/` are applied for any file outside the `/sub` directory
|
||||||
- `fs_provider`, filesystem to serve via SFTP. Local filesystem, S3 Compatible Object Storage, Google Cloud Storage and Azure Blob Storage are supported
|
- `fs_provider`, filesystem to serve via SFTP. Local filesystem (0), S3 Compatible Object Storage (1), Google Cloud Storage (2) and Azure Blob Storage (3) are supported
|
||||||
- `s3_bucket`, required for S3 filesystem
|
- `s3_bucket`, required for S3 filesystem
|
||||||
- `s3_region`, required for S3 filesystem. Must match the region for your bucket. You can find here the list of available [AWS regions](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). For example if your bucket is at `Frankfurt` you have to set the region to `eu-central-1`
|
- `s3_region`, required for S3 filesystem. Must match the region for your bucket. You can find here the list of available [AWS regions](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions). For example if your bucket is at `Frankfurt` you have to set the region to `eu-central-1`
|
||||||
- `s3_access_key`
|
- `s3_access_key`
|
||||||
|
|||||||
@@ -200,5 +200,3 @@ Let's see some examples:
|
|||||||
|
|
||||||
- To set sftpd `bind_port`, you need to define the env var `SFTPGO_SFTPD__BIND_PORT`
|
- To set sftpd `bind_port`, you need to define the env var `SFTPGO_SFTPD__BIND_PORT`
|
||||||
- To set the `execute_on` actions, you need to define the env var `SFTPGO_COMMON__ACTIONS__EXECUTE_ON`. For example `SFTPGO_COMMON__ACTIONS__EXECUTE_ON=upload,download`
|
- To set the `execute_on` actions, you need to define the env var `SFTPGO_COMMON__ACTIONS__EXECUTE_ON`. For example `SFTPGO_COMMON__ACTIONS__EXECUTE_ON=upload,download`
|
||||||
|
|
||||||
Please note that in order to override configuration options with environment variables, you need a configuration file containing the options to override, this is a [viper bug](https://github.com/spf13/viper/issues/584). For example, you can deploy the default configuration file and then override the options to customize using environment variables.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user