From 6d5bfe447f67c5496a82ae3b8cffbf89ae560834 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Mon, 15 Jun 2026 09:15:40 +0300 Subject: [PATCH] Add proxy support for GARM This change adds the ability to set proxy config for the GARM daemon. The same settings will also apply to external providers when they are invoked. Signed-off-by: Gabriel Adrian Samfira --- config/config.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++ config/external.go | 20 +++++++++++++++--- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index 62c809535..832a3af0c 100644 --- a/config/config.go +++ b/config/config.go @@ -77,6 +77,11 @@ func NewConfig(cfgFile string) (*Config, error) { if err := config.Validate(); err != nil { return nil, fmt.Errorf("error validating config: %w", err) } + // Set proxy environment variables process wide if they are set + // in the config. This overrides any environment variables already set + // by the environment from which GARM was invoked. + config.Proxy.populateEnv() + return &config, nil } @@ -88,6 +93,7 @@ type Config struct { Providers []Provider `toml:"provider,omitempty" json:"provider,omitempty"` JWTAuth JWTAuth `toml:"jwt_auth" json:"jwt-auth"` Logging Logging `toml:"logging" json:"logging"` + Proxy Proxy `toml:"proxy" json:"proxy"` } // Validate validates the config @@ -111,6 +117,10 @@ func (c *Config) Validate() error { return fmt.Errorf("error validating logging config: %w", err) } + if err := c.Proxy.Validate(); err != nil { + return fmt.Errorf("failed to validate proxy settings: %w", err) + } + providerNames := map[string]int{} for _, provider := range c.Providers { @@ -150,6 +160,47 @@ func (c *Config) GetLoggingConfig() Logging { return logging } +type Proxy struct { + HTTPProxy string `toml:"http_proxy" json:"http_proxy"` + HTTPSProxy string `toml:"https_proxy" json:"https_proxy"` + NoProxy string `toml:"no_proxy" json:"no_proxy"` +} + +func (p *Proxy) Validate() error { + if p.HTTPProxy != "" { + _, err := url.ParseRequestURI(p.HTTPProxy) + if err != nil { + return fmt.Errorf("invalid http_proxy: %w", err) + } + } + + if p.HTTPSProxy != "" { + _, err := url.ParseRequestURI(p.HTTPSProxy) + if err != nil { + return fmt.Errorf("invalid https_proxy: %w", err) + } + } + + return nil +} + +func (p *Proxy) populateEnv() { + if p.HTTPProxy != "" { + os.Setenv("http_proxy", p.HTTPProxy) + os.Setenv("HTTP_PROXY", p.HTTPProxy) + } + + if p.HTTPSProxy != "" { + os.Setenv("https_proxy", p.HTTPSProxy) + os.Setenv("HTTPS_PROXY", p.HTTPSProxy) + } + + if p.NoProxy != "" { + os.Setenv("no_proxy", p.NoProxy) + os.Setenv("NO_PROXY", p.NoProxy) + } +} + type Logging struct { // LogFile is the location of the log file. LogFile string `toml:"log_file,omitempty" json:"log-file"` diff --git a/config/external.go b/config/external.go index ca98bdfb6..cbb8978ef 100644 --- a/config/external.go +++ b/config/external.go @@ -52,16 +52,30 @@ type External struct { func (e *External) GetEnvironmentVariables() []string { envVars := []string{} + seen := map[string]struct{}{} + proxyVars := []string{ + "http_proxy", + "https_proxy", + "no_proxy", + "HTTP_PROXY", + "HTTPS_PROXY", + "NO_PROXY", + } + lookups := e.EnvironmentVariables + lookups = append(lookups, proxyVars...) - for _, configuredEnvVars := range e.EnvironmentVariables { + for _, configuredEnvVars := range lookups { + if _, ok := seen[configuredEnvVars]; ok { + continue + } // discover environment variables for _, k := range os.Environ() { variable := strings.SplitN(k, "=", 2) - if strings.HasPrefix(variable[0], configuredEnvVars) && - !strings.HasPrefix(variable[0], EnvironmentVariablePrefix) { + if strings.HasPrefix(variable[0], configuredEnvVars) && !strings.HasPrefix(variable[0], EnvironmentVariablePrefix) { envVars = append(envVars, k) } } + seen[configuredEnvVars] = struct{}{} } return envVars }