diff --git a/CHANGELOG.md b/CHANGELOG.md index 231420d..8d2f178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ This document outlines major changes between releases. ## [Unreleased] +### Updating from 0.8.3 + +Notice that configuration parameters in the `server` section were reorganized. +For example e.g.`server.schema` and `tls-listen-limit` were removed, and some +others were moved inside the array `endpoints`. Check your configuration with +the help of the [gate-configuration.md](./docs/gate-configuration.md) and +[config](./config/config.yaml). Also, flags in the command arguments were +changed. + ## [0.8.3] - 2024-03-25 ### Fixed diff --git a/cmd/neofs-rest-gw/config.go b/cmd/neofs-rest-gw/config.go index c656072..e830ceb 100644 --- a/cmd/neofs-rest-gw/config.go +++ b/cmd/neofs-rest-gw/config.go @@ -64,17 +64,30 @@ const ( cfgWalletAddress = "wallet.address" cfgWalletPassphrase = "wallet.passphrase" - // Config section for autogenerated flags. - cfgServerSection = "server." + // Server endpoints. + cfgServerSection = "server." + cfgServerEndpoints = cfgServerSection + "endpoints" + + cfgTLSEnabled = "tls.enabled" + cfgTLSKeyFile = "tls.key" + cfgTLSCertFile = "tls.certificate" + cfgTLSCertCAFile = "tls.ca-certificate" + + cfgEndpointAddress = "address" + cfgEndpointExternalAddress = "external-address" + cfgEndpointKeepAlive = "keep-alive" + cfgEndpointReadTimeout = "read-timeout" + cfgEndpointWriteTimeout = "write-timeout" // Command line args. - cmdHelp = "help" - cmdVersion = "version" - cmdPprof = "pprof" - cmdMetrics = "metrics" - cmdWallet = "wallet" - cmdAddress = "address" - cmdConfig = "config" + cmdHelp = "help" + cmdVersion = "version" + cmdPprof = "pprof" + cmdMetrics = "metrics" + cmdWallet = "wallet" + cmdAddress = "address" + cmdConfig = "config" + cmdListenAddress = "listen-address" baseURL = "/v1" ) @@ -123,9 +136,20 @@ func config() *viper.Viper { peers := flagSet.StringArrayP(cmdPeers, "p", nil, "NeoFS nodes") + flagSet.String(cmdListenAddress, "localhost:8080", "set the main address to listen") + flagSet.String(cfgTLSCertFile, "", "TLS certificate file to use; note that if you want to start HTTPS server, you should also set up --"+cmdListenAddress+" and --"+cfgTLSKeyFile) + flagSet.String(cfgTLSKeyFile, "", "TLS key file to use; note that if you want to start HTTPS server, you should also set up --"+cmdListenAddress+" and --"+cfgTLSCertFile) + flagSet.Duration(cfgEndpointKeepAlive, 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)") + flagSet.Duration(cfgEndpointReadTimeout, 30*time.Second, "maximum duration before timing out read of the request") + flagSet.Duration(cfgEndpointWriteTimeout, 30*time.Second, "maximum duration before timing out write of the response") + flagSet.String(cfgEndpointExternalAddress, "localhost:8090", "the IP and port to be shown in the API documentation") + // init server flags BindDefaultFlags(flagSet) + if err := bindServerFlags(v, flagSet); err != nil { + panic(fmt.Errorf("bind server flags: %w", err)) + } // set defaults: // pool v.SetDefault(cfgPoolErrorThreshold, defaultPoolErrorThreshold) @@ -191,6 +215,34 @@ func config() *viper.Viper { return v } +func bindServerFlags(v *viper.Viper, flags *pflag.FlagSet) error { + // This key is used only to check if the address comes from the command arguments. + if err := v.BindPFlag(cmdListenAddress, flags.Lookup(cmdListenAddress)); err != nil { + return err + } + + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgEndpointAddress, flags.Lookup(cmdListenAddress)); err != nil { + return err + } + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgEndpointExternalAddress, flags.Lookup(cfgEndpointExternalAddress)); err != nil { + return err + } + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgEndpointKeepAlive, flags.Lookup(cfgEndpointKeepAlive)); err != nil { + return err + } + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgEndpointReadTimeout, flags.Lookup(cfgEndpointReadTimeout)); err != nil { + return err + } + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgEndpointWriteTimeout, flags.Lookup(cfgEndpointWriteTimeout)); err != nil { + return err + } + if err := v.BindPFlag(cfgServerEndpoints+".0."+cfgTLSKeyFile, flags.Lookup(cfgTLSKeyFile)); err != nil { + return err + } + + return v.BindPFlag(cfgServerEndpoints+".0."+cfgTLSCertFile, flags.Lookup(cfgTLSCertFile)) +} + func init() { for _, flagName := range serverFlags { cfgName := cfgServerSection + flagName @@ -200,24 +252,10 @@ func init() { } var serverFlags = []string{ - FlagScheme, FlagCleanupTimeout, FlagGracefulTimeout, FlagMaxHeaderSize, - FlagListenAddress, FlagListenLimit, - FlagKeepAlive, - FlagReadTimeout, - FlagWriteTimeout, - FlagTLSListenAddress, - FlagTLSCertificate, - FlagTLSKey, - FlagTLSCa, - FlagTLSListenLimit, - FlagTLSKeepAlive, - FlagTLSReadTimeout, - FlagTLSWriteTimeout, - FlagExternalAddress, } var bindings = map[string]string{ @@ -250,6 +288,10 @@ func validateConfig(cfg *viper.Viper, logger *zap.Logger) { for _, providedKey := range cfg.AllKeys() { if !strings.HasPrefix(providedKey, cfgPeers) { + if strings.HasPrefix(providedKey, cfgServerEndpoints) { + // Do not validate `Endpoints` section. + continue + } if _, ok := knownConfigParams[providedKey]; !ok { logger.Warn("unknown config parameter", zap.String("key", providedKey)) } @@ -404,104 +446,82 @@ func newLogger(v *viper.Viper) *zap.Logger { // ServerConfig contains parsed config for the Echo server. type ServerConfig struct { - EnabledListeners []string - CleanupTimeout time.Duration - GracefulTimeout time.Duration - MaxHeaderSize int - - ListenAddress string - ListenLimit int - KeepAlive time.Duration - ReadTimeout time.Duration - WriteTimeout time.Duration - - TLSListenAddress string - TLSListenLimit int - TLSKeepAlive time.Duration - TLSReadTimeout time.Duration - TLSWriteTimeout time.Duration - TLSCertificate string - TLSCertificateKey string - TLSCACertificate string - - ExternalAddress string + CleanupTimeout time.Duration + GracefulTimeout time.Duration + MaxHeaderSize int + ListenLimit int + Endpoints []EndpointInfo } const ( - FlagScheme = "scheme" - FlagCleanupTimeout = "cleanup-timeout" - FlagGracefulTimeout = "graceful-timeout" - FlagMaxHeaderSize = "max-header-size" - FlagListenAddress = "listen-address" - FlagListenLimit = "listen-limit" - FlagKeepAlive = "keep-alive" - FlagReadTimeout = "read-timeout" - FlagWriteTimeout = "write-timeout" - FlagTLSListenAddress = "tls-listen-address" - FlagTLSCertificate = "tls-certificate" - FlagTLSKey = "tls-key" - FlagTLSCa = "tls-ca" - FlagTLSListenLimit = "tls-listen-limit" - FlagTLSKeepAlive = "tls-keep-alive" - FlagTLSReadTimeout = "tls-read-timeout" - FlagTLSWriteTimeout = "tls-write-timeout" - FlagExternalAddress = "external-address" + FlagCleanupTimeout = "cleanup-timeout" + FlagGracefulTimeout = "graceful-timeout" + FlagMaxHeaderSize = "max-header-size" + FlagListenLimit = "listen-limit" ) -var defaultSchemes []string - -func init() { - defaultSchemes = []string{ - schemeHTTP, - } -} - func BindDefaultFlags(flagSet *pflag.FlagSet) { - flagSet.StringSlice(FlagScheme, defaultSchemes, "the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec") - flagSet.Duration(FlagCleanupTimeout, 10*time.Second, "grace period for which to wait before killing idle connections") flagSet.Duration(FlagGracefulTimeout, 15*time.Second, "grace period for which to wait before shutting down the server") flagSet.Int(FlagMaxHeaderSize, 1000000, "controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body") - - flagSet.String(FlagListenAddress, "localhost:8080", "the IP and port to listen on") flagSet.Int(FlagListenLimit, 0, "limit the number of outstanding requests") - flagSet.Duration(FlagKeepAlive, 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)") - flagSet.Duration(FlagReadTimeout, 30*time.Second, "maximum duration before timing out read of the request") - flagSet.Duration(FlagWriteTimeout, 30*time.Second, "maximum duration before timing out write of the response") - - flagSet.String(FlagTLSListenAddress, "localhost:8081", "the IP and port to listen on") - flagSet.String(FlagTLSCertificate, "", "the certificate file to use for secure connections") - flagSet.String(FlagTLSKey, "", "the private key file to use for secure connections (without passphrase)") - flagSet.String(FlagTLSCa, "", "the certificate authority certificate file to be used with mutual tls auth") - flagSet.Int(FlagTLSListenLimit, 0, "limit the number of outstanding requests") - flagSet.Duration(FlagTLSKeepAlive, 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)") - flagSet.Duration(FlagTLSReadTimeout, 30*time.Second, "maximum duration before timing out read of the request") - flagSet.Duration(FlagTLSWriteTimeout, 30*time.Second, "maximum duration before timing out write of the response") - - flagSet.String(FlagExternalAddress, "localhost:8090", "the IP and port to be shown in the API documentation") } func serverConfig(v *viper.Viper) *ServerConfig { return &ServerConfig{ - EnabledListeners: v.GetStringSlice(cfgServerSection + FlagScheme), - CleanupTimeout: v.GetDuration(cfgServerSection + FlagCleanupTimeout), - GracefulTimeout: v.GetDuration(cfgServerSection + FlagGracefulTimeout), - MaxHeaderSize: v.GetInt(cfgServerSection + FlagMaxHeaderSize), - - ListenAddress: v.GetString(cfgServerSection + FlagListenAddress), - ListenLimit: v.GetInt(cfgServerSection + FlagListenLimit), - KeepAlive: v.GetDuration(cfgServerSection + FlagKeepAlive), - ReadTimeout: v.GetDuration(cfgServerSection + FlagReadTimeout), - WriteTimeout: v.GetDuration(cfgServerSection + FlagWriteTimeout), + CleanupTimeout: v.GetDuration(cfgServerSection + FlagCleanupTimeout), + GracefulTimeout: v.GetDuration(cfgServerSection + FlagGracefulTimeout), + MaxHeaderSize: v.GetInt(cfgServerSection + FlagMaxHeaderSize), + ListenLimit: v.GetInt(cfgServerSection + FlagListenLimit), + Endpoints: fetchEndpoints(v), + } +} - TLSListenAddress: v.GetString(cfgServerSection + FlagTLSListenAddress), - TLSListenLimit: v.GetInt(cfgServerSection + FlagTLSListenLimit), - TLSKeepAlive: v.GetDuration(cfgServerSection + FlagTLSKeepAlive), - TLSReadTimeout: v.GetDuration(cfgServerSection + FlagTLSReadTimeout), - TLSWriteTimeout: v.GetDuration(cfgServerSection + FlagTLSWriteTimeout), +func fetchEndpoints(v *viper.Viper) []EndpointInfo { + var servers []EndpointInfo + + if v.IsSet(cmdListenAddress) { + key := cfgServerEndpoints + ".0." + // If this address is set, we don't use config file to set other parameters. + serverInfo := EndpointInfo{ + Address: v.GetString(key + cfgEndpointAddress), + ExternalAddress: v.GetString(key + cfgEndpointExternalAddress), + KeepAlive: v.GetDuration(key + cfgEndpointKeepAlive), + ReadTimeout: v.GetDuration(key + cfgEndpointReadTimeout), + WriteTimeout: v.GetDuration(key + cfgEndpointWriteTimeout), + } + keyFile := v.GetString(key + cfgTLSKeyFile) + certFile := v.GetString(key + cfgTLSCertFile) + if keyFile != "" && certFile != "" { + // If TLS key and certificate are set in the command arguments, we enable TLS. + serverInfo.TLS.Enabled = true + serverInfo.TLS.KeyFile = keyFile + serverInfo.TLS.CertFile = certFile + } + servers = append(servers, serverInfo) + } else { + for i := 0; ; i++ { + key := cfgServerEndpoints + "." + strconv.Itoa(i) + "." - ExternalAddress: v.GetString(cfgServerSection + FlagExternalAddress), + var serverInfo EndpointInfo + serverInfo.Address = v.GetString(key + cfgEndpointAddress) + if serverInfo.Address == "" { + break + } + serverInfo.ExternalAddress = v.GetString(key + cfgEndpointExternalAddress) + serverInfo.KeepAlive = v.GetDuration(key + cfgEndpointKeepAlive) + serverInfo.ReadTimeout = v.GetDuration(key + cfgEndpointReadTimeout) + serverInfo.WriteTimeout = v.GetDuration(key + cfgEndpointWriteTimeout) + serverInfo.TLS.Enabled = v.GetBool(key + cfgTLSEnabled) + serverInfo.TLS.KeyFile = v.GetString(key + cfgTLSKeyFile) + serverInfo.TLS.CertFile = v.GetString(key + cfgTLSCertFile) + serverInfo.TLS.CertCAFile = v.GetString(key + cfgTLSCertCAFile) + + servers = append(servers, serverInfo) + } } + + return servers } func newNeofsAPI(ctx context.Context, logger *zap.Logger, v *viper.Viper) (*handlers.RestAPI, error) { diff --git a/cmd/neofs-rest-gw/integration_test.go b/cmd/neofs-rest-gw/integration_test.go index b9dd50e..0deca6a 100644 --- a/cmd/neofs-rest-gw/integration_test.go +++ b/cmd/neofs-rest-gw/integration_test.go @@ -207,8 +207,8 @@ func getDefaultConfig(node string) *viper.Viper { v.SetDefault(cfgPeers+".0.address", node) v.SetDefault(cfgPeers+".0.weight", 1) v.SetDefault(cfgPeers+".0.priority", 1) - v.SetDefault(cfgServerSection+FlagListenAddress, testListenAddress) - v.SetDefault(cfgServerSection+FlagWriteTimeout, 60*time.Second) + v.SetDefault(cfgServerSection+cmdListenAddress, testListenAddress) + v.SetDefault(cfgServerSection+cfgEndpointWriteTimeout, 60*time.Second) return v } diff --git a/cmd/neofs-rest-gw/main.go b/cmd/neofs-rest-gw/main.go index 2d52f78..dc66ac9 100644 --- a/cmd/neofs-rest-gw/main.go +++ b/cmd/neofs-rest-gw/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "crypto/tls" "errors" "fmt" "net/http" @@ -47,32 +48,6 @@ func main() { logger.Fatal("get swagger definition", zap.Error(err)) } - servers := make(openapi3.Servers, len(serverCfg.EnabledListeners)) - - if serverCfg.ExternalAddress != "" { - for i, scheme := range serverCfg.EnabledListeners { - switch scheme { - case schemeHTTP: - servers[i] = &openapi3.Server{ - URL: fmt.Sprintf("%s://%s%s", scheme, serverCfg.ExternalAddress, baseURL), - } - case schemeHTTPS: - servers[i] = &openapi3.Server{ - URL: fmt.Sprintf("%s://%s%s", scheme, serverCfg.ExternalAddress, baseURL), - } - default: - logger.Error("unknown scheme", zap.String("scheme", scheme)) - } - } - } - - swagger.Servers = servers - - swaggerPayload, err = swagger.MarshalJSON() - if err != nil { - logger.Fatal("swagger marshal", zap.Error(err)) - } - e := echo.New() e.HideBanner = true e.StaticFS(docsURL, docs.FS) @@ -87,23 +62,71 @@ func main() { e.Group(baseURL, middleware.OapiRequestValidator(swagger)) apiserver.RegisterHandlersWithBaseURL(e, neofsAPI, baseURL) - neofsAPI.RunServices() + servers := make(openapi3.Servers, len(serverCfg.Endpoints)) + for i, endpointInfo := range serverCfg.Endpoints { + if endpointInfo.ExternalAddress != "" { + var scheme string + // Determine the scheme based on whether TLS is enabled and set up e.TLSServer. + if endpointInfo.TLS.Enabled { + scheme = schemeHTTPS + e.TLSServer.ReadTimeout = endpointInfo.ReadTimeout + e.TLSServer.WriteTimeout = endpointInfo.WriteTimeout + e.TLSServer.IdleTimeout = endpointInfo.KeepAlive + + if endpointInfo.TLS.CertCAFile != "" { + ca, err := loadCA(endpointInfo.TLS.CertCAFile) + if err != nil { + logger.Fatal("reading server certificate", zap.Error(err)) + } + e.TLSServer.TLSConfig = &tls.Config{ClientCAs: ca} + } + } else { + scheme = schemeHTTP + } + servers[i] = &openapi3.Server{ + URL: fmt.Sprintf("%s://%s%s", scheme, endpointInfo.ExternalAddress, baseURL), + } + } else { + logger.Info("Endpoint with missing external-address", zap.String("address", endpointInfo.Address)) + } + } + swagger.Servers = servers - go func() { - neofsAPI.StartCallback() + swaggerPayload, err = swagger.MarshalJSON() + if err != nil { + logger.Fatal("swagger marshal", zap.Error(err)) + } + + neofsAPI.RunServices() - if err = e.Start(serverCfg.ListenAddress); err != nil { - if !errors.Is(err, http.ErrServerClosed) { - logger.Fatal("start", zap.Error(err)) + for i := range serverCfg.Endpoints { + go func(i int) { + endpointInfo := serverCfg.Endpoints[i] + logger.Info("starting server", zap.String("address", endpointInfo.Address)) + + if endpointInfo.TLS.Enabled { + if err = e.StartTLS(endpointInfo.Address, endpointInfo.TLS.CertFile, endpointInfo.TLS.KeyFile); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + logger.Fatal("start https", zap.Error(err)) + } + cancel() + } + } else { + if err = e.Start(endpointInfo.Address); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + logger.Fatal("start http", zap.Error(err)) + } + cancel() + } } + }(i) + } - cancel() - } - }() + go neofsAPI.StartCallback() <-ctx.Done() if err = e.Shutdown(ctx); err != nil { - logger.Fatal("shutdown", zap.Error(err)) + logger.Fatal("shutdown http and https", zap.Error(err)) } } diff --git a/cmd/neofs-rest-gw/server.go b/cmd/neofs-rest-gw/server.go new file mode 100644 index 0000000..13eeb5c --- /dev/null +++ b/cmd/neofs-rest-gw/server.go @@ -0,0 +1,36 @@ +package main + +import ( + "crypto/x509" + "os" + "time" +) + +type ( + EndpointInfo struct { + Address string + ExternalAddress string + TLS ServerTLSInfo + KeepAlive time.Duration + ReadTimeout time.Duration + WriteTimeout time.Duration + } + + ServerTLSInfo struct { + Enabled bool + CertFile string + KeyFile string + CertCAFile string + } +) + +// Helper function to load CA certificate. +func loadCA(path string) (*x509.CertPool, error) { + caCertPool := x509.NewCertPool() + caCert, err := os.ReadFile(path) + if err != nil { + return nil, err + } + caCertPool.AppendCertsFromPEM(caCert) + return caCertPool, nil +} diff --git a/config/config.yaml b/config/config.yaml index 6755975..b8c7f51 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -51,45 +51,45 @@ pool: weight: 9 server: - # The listeners to enable, this can be repeated and defaults to the schemes in the swagger spec. - scheme: [ http ] - # Grace period for which to wait before killing idle connections + endpoints: + # The IP and port to listen on. + - address: localhost:8081 + # The IP and port to be shown in the API documentation. + external-address: localhost:8091 + tls: + # Use TLS for a gRPC connection (min version is TLS 1.2). + enabled: true + # The certificate file to use for secure connections. + certificate: tls.crt + # The private key file to use for secure connections (without passphrase). + key: tls.key + # The certificate authority certificate file to be used with mutual tls auth. + ca-certificate: ca1.crt + # Sets the TCP keep-alive timeouts on accepted connections. + # It prunes dead TCP connections ( e.g. closing laptop mid-download). + keep-alive: 3m + # Maximum duration before timing out read of the request. + read-timeout: 30s + # Maximum duration before timing out write of the response. + write-timeout: 30s + + - address: localhost:8080 + external-address: localhost:8090 + tls: + enabled: false + certificate: /path/to/tls/cert + key: /path/to/tls/key + ca-certificate: /path/to/tls/ca + keep-alive: 3m + read-timeout: 30s + write-timeout: 30s + + # Grace period for which to wait before killing idle connections. cleanup-timeout: 10s - # Grace period for which to wait before shutting down the server + # Grace period for which to wait before shutting down the server. graceful-timeout: 15s # Controls the maximum number of bytes the server will read parsing the request header's keys and values, # including the request line. It does not limit the size of the request body. max-header-size: 1000000 - - # The IP and port to listen on. - listen-address: localhost:8080 # Limit the number of outstanding requests. listen-limit: 0 - # Sets the TCP keep-alive timeouts on accepted connections. - # It prunes dead TCP connections ( e.g. closing laptop mid-download). - keep-alive: 3m - # Maximum duration before timing out read of the request. - read-timeout: 30s - # Maximum duration before timing out write of the response. - write-timeout: 30s - - # The IP and port to listen on. - tls-listen-address: localhost:8081 - # The certificate file to use for secure connections. - tls-certificate: /path/to/tls/cert - # The private key file to use for secure connections (without passphrase). - tls-key: /path/to/tls/key - # The certificate authority certificate file to be used with mutual tls auth. - tls-ca: /path/to/tls/ca - # Limit the number of outstanding requests. - tls-listen-limit: 0 - # Sets the TCP keep-alive timeouts on accepted connections. - # It prunes dead TCP connections ( e.g. closing laptop mid-download). - tls-keep-alive: 3m - # Maximum duration before timing out read of the request. - tls-read-timeout: 30s - # Maximum duration before timing out write of the response. - tls-write-timeout: 30s - - # The IP and port to be shown in the API documentation. - external-address: localhost:8090 diff --git a/docs/gate-configuration.md b/docs/gate-configuration.md index a20aaff..6a5204f 100644 --- a/docs/gate-configuration.md +++ b/docs/gate-configuration.md @@ -12,59 +12,48 @@ There are some custom types used for brevity: | Section | Description | |--------------|-------------------------------------------------| -| no section | [General parameters](#general-section) | +| `server` | [Server parameters](#server-section) | | `wallet` | [Wallet configuration](#wallet-section) | | `pool` | [Pool configuration](#pool-section) | | `logger` | [Logger configuration](#logger-section) | | `pprof` | [Pprof configuration](#pprof-section) | | `prometheus` | [Prometheus configuration](#prometheus-section) | -# General section +# Server section ```yaml -scheme: [ http ] +endpoints: + - address: localhost:8080 + external-address: localhost:8090 + tls: + enabled: false + certificate: /path/to/tls/cert + key: /path/to/tls/key + ca-certificate: /path/to/tls/ca + keep-alive: 3m + read-timeout: 30s + write-timeout: 30s cleanup-timeout: 10s graceful-timeout: 15s max-header-size: 1000000 - -listen-address: localhost:8080 listen-limit: 0 -keep-alive: 3m -read-timeout: 30s -write-timeout: 30s - -tls-listen-address: localhost:8081 -tls-certificate: /path/to/tls/cert -tls-key: /path/to/tls/key -tls-ca: /path/to/tls/ca -tls-listen-limit: 0 -tls-keep-alive: 3m -tls-read-timeout: 30s -tls-write-timeout: 30s - -external-address: localhost:8090 ``` -| Parameter | Type | Default value | Description | -|----------------------|------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `scheme` | `[]string` | `[http]` | The listeners to enable, this can be repeated and defaults to the schemes in the swagger spec. | -| `cleanup-timeout` | `duration` | `10s` | Grace period for which to wait before killing idle connections. | -| `graceful-timeout` | `duration` | `15s` | Grace period for which to wait before shutting down the server. | -| `max-header-size` | `int` | `1000000` | Controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body. | -| `listen-address` | `string` | `localhost:8080` | The IP and port to listen on. | -| `listen-limit` | `int` | `0` | Limit the number of outstanding requests. `0` means no limit | | -| `keep-alive` | `duration` | `3m` | Sets the TCP keep-alive timeouts on accepted connections. | -| `read-timeout` | `duration` | `30s` | Maximum duration before timing out read of the request. It prunes dead TCP connections (e.g. closing laptop mid-download). | -| `write-timeout` | `duration` | `30s` | Maximum duration before timing out write of the response. | -| `tls-listen-address` | `string` | `localhost:8081` | The IP and port to listen on for TLS. | -| `tls-certificate` | `string` | | The certificate file to use for secure connections. | -| `tls-key` | `string` | | The private key file to use for secure connections (without passphrase). | -| `tls-ca` | `string` | | The certificate authority certificate file to be used with mutual tls auth. | -| `tls-listen-limit` | `int` | `0` | Limit the number of outstanding requests for TLS. `0` means no limit | | -| `tls-keep-alive` | `duration` | `3m` | Sets the TCP keep-alive timeouts on accepted connections for TLS. | -| `tls-read-timeout` | `duration` | `30s` | Maximum duration before timing out read of the request for TLS. It prunes dead TCP connections (e.g. closing laptop mid-download). | -| `tls-write-timeout` | `duration` | `30s` | Maximum duration before timing out write of the response for TLS. | -| `external-address` | `string` | `localhost:8090` | The IP and port to be shown in the API documentation. | +| Parameter | Type | Default value | Description | +|---------------------------------|------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `cleanup-timeout` | `duration` | `10s` | Grace period for which to wait before killing idle connections. | +| `graceful-timeout` | `duration` | `15s` | Grace period for which to wait before shutting down the server. | +| `max-header-size` | `int` | `1000000` | Controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body. | +| `listen-limit` | `int` | `0` | Limit the number of outstanding requests. `0` means no limit | | +| `endpoint.[0].listen-address` | `string` | `localhost:8080` | The IP and port to listen on. | +| `endpoint.[0].keep-alive` | `duration` | `3m` | Sets the TCP keep-alive timeouts on accepted connections. | +| `endpoint.[0].read-timeout` | `duration` | `30s` | Maximum duration before timing out read of the request. It prunes dead TCP connections (e.g. closing laptop mid-download). | +| `endpoint.[0].write-timeout` | `duration` | `30s` | Maximum duration before timing out write of the response. | +| `endpoint.[0].tls.enabled` | `bool` | `false` | Use TLS for a gRPC connection (min version is TLS 1.2). | +| `endpoint.[0].tls.certificate` | `string` | | The certificate file to use for secure connections. | +| `endpoint.[0].tls.key` | `string` | | The private key file to use for secure connections (without passphrase). | +| `endpoint.[0].tls.ca` | `string` | | The certificate authority certificate file to be used with mutual tls auth. | +| `endpoint.[0].external-address` | `string` | `localhost:8090` | The IP and port to be shown in the API documentation. | # `wallet` section