diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 951e09bb..751932e7 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -10,6 +10,8 @@ import ( "os/signal" "time" + _ "net/http/pprof" + "github.com/gomods/athens/cmd/proxy/actions" "github.com/gomods/athens/pkg/build" "github.com/gomods/athens/pkg/config" @@ -61,6 +63,15 @@ func main() { close(idleConnsClosed) }() + if conf.EnablePprof { + go func() { + // pprof to be exposed on a different port than the application for security matters, not to expose profiling data and avoid DoS attacks (profiling slows down the service) + // https://www.farsightsecurity.com/txt-record/2016/10/28/cmikk-go-remote-profiling/ + log.Printf("Starting `pprof` at port %v", conf.PprofPort) + log.Fatal(http.ListenAndServe(conf.PprofPort, nil)) + }() + } + log.Printf("Starting application at port %v", conf.Port) if cert != "" && key != "" { err = srv.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile) diff --git a/config.dev.toml b/config.dev.toml index e623dd2d..1b7bb289 100755 --- a/config.dev.toml +++ b/config.dev.toml @@ -43,6 +43,14 @@ LogLevel = "debug" # Env override: ATHENS_CLOUD_RUNTIME CloudRuntime = "none" +# EnablePprof specifies if the pprof endpoints should be exposed. +# Note that this option is not meant to be activated forever on a server +# and should be desactivated once not needed. +EnablePprof = false + +# PprofPort specifies the port on which pprof will be exposed if activated. +PprofPort = ":3001" + # The filename for the include exclude filter. # Env override: ATHENS_FILTER_FILE # diff --git a/pkg/config/config.go b/pkg/config/config.go index 874a88d0..34586fa8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -25,6 +25,8 @@ type Config struct { ProtocolWorkers int `validate:"required" envconfig:"ATHENS_PROTOCOL_WORKERS"` LogLevel string `validate:"required" envconfig:"ATHENS_LOG_LEVEL"` CloudRuntime string `validate:"required" envconfig:"ATHENS_CLOUD_RUNTIME"` + EnablePprof bool `envconfig:"ATHENS_ENABLE_PPROF"` + PprofPort string `envconfig:"ATHENS_PPROF_PORT"` FilterFile string `envconfig:"ATHENS_FILTER_FILE"` TraceExporterURL string `envconfig:"ATHENS_TRACE_EXPORTER_URL"` TraceExporter string `envconfig:"ATHENS_TRACE_EXPORTER"` @@ -78,6 +80,8 @@ func defaultConfig() *Config { ProtocolWorkers: 30, LogLevel: "debug", CloudRuntime: "none", + EnablePprof: false, + PprofPort: ":3001", StatsExporter: "prometheus", TimeoutConf: TimeoutConf{Timeout: 300}, StorageType: "memory", diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 94c8ca32..4528a4ed 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -78,6 +78,8 @@ func TestEnvOverrides(t *testing.T) { StorageType: "minio", GlobalEndpoint: "mytikas.gomods.io", Port: ":7000", + EnablePprof: false, + PprofPort: ":3001", BasicAuthUser: "testuser", BasicAuthPass: "testpass", ForceSSL: true, @@ -256,6 +258,8 @@ func TestParseExampleConfig(t *testing.T) { StorageType: "memory", GlobalEndpoint: "http://localhost:3001", Port: ":3000", + EnablePprof: false, + PprofPort: ":3001", BasicAuthUser: "", BasicAuthPass: "", Storage: expStorage, @@ -297,6 +301,8 @@ func getEnvMap(config *Config) map[string]string { envVars["ATHENS_STORAGE_TYPE"] = config.StorageType envVars["ATHENS_GLOBAL_ENDPOINT"] = config.GlobalEndpoint envVars["ATHENS_PORT"] = config.Port + envVars["ATHENS_ENABLE_PPROF"] = strconv.FormatBool(config.EnablePprof) + envVars["ATHENS_PPROF_PORT"] = config.PprofPort envVars["BASIC_AUTH_USER"] = config.BasicAuthUser envVars["BASIC_AUTH_PASS"] = config.BasicAuthPass envVars["PROXY_FORCE_SSL"] = strconv.FormatBool(config.ForceSSL)