Merge pull request #1883 from versity/ben/gateways-config

feat: add cli options to specify webui gateway/admin listing
This commit is contained in:
Ben McClelland
2026-02-23 12:34:33 -08:00
committed by GitHub
2 changed files with 139 additions and 5 deletions
+121 -5
View File
@@ -21,6 +21,7 @@ import (
"net"
"net/http"
_ "net/http/pprof"
"net/url"
"os"
"strconv"
"strings"
@@ -97,6 +98,8 @@ var (
webuiPorts []string
webuiCertFile, webuiKeyFile string
webuiNoTLS bool
webuiGateways []string
webuiAdminGateways []string
)
var (
@@ -150,6 +153,8 @@ documentation can be found in the GitHub wiki.`,
ports = ctx.StringSlice("port")
webuiPorts = ctx.StringSlice("webui")
admPorts = ctx.StringSlice("admin-port")
webuiGateways = ctx.StringSlice("webui-gateways")
webuiAdminGateways = ctx.StringSlice("webui-admin-gateways")
return nil
},
Action: func(ctx *cli.Context) error {
@@ -203,6 +208,16 @@ func initFlags() []cli.Flag {
EnvVars: []string{"VGW_WEBUI_NO_TLS"},
Destination: &webuiNoTLS,
},
&cli.StringSliceFlag{
Name: "webui-gateways",
Usage: "override auto-detected S3 gateway URLs for WebUI (e.g. 'http://localhost:7070', 'https://s3.example.com'; can be specified multiple times)",
EnvVars: []string{"VGW_WEBUI_GATEWAYS"},
},
&cli.StringSliceFlag{
Name: "webui-admin-gateways",
Usage: "override auto-detected admin gateway URLs for WebUI (e.g. 'http://localhost:7080', 'https://admin.example.com'; can be specified multiple times)",
EnvVars: []string{"VGW_WEBUI_ADMIN_GATEWAYS"},
},
&cli.StringFlag{
Name: "access",
Usage: "root user access key",
@@ -1023,16 +1038,37 @@ func runGateway(ctx context.Context, be backend.Backend) error {
}
var gateways []string
for _, p := range ports {
urls, err := buildServiceURLs(p, sslEnabled)
if len(webuiGateways) > 0 {
// Use explicitly provided gateway URLs if specified
// Validate explicitly provided URLs
validGateways, err := validateGatewayURLs(webuiGateways, "webui gateway")
if err != nil {
return fmt.Errorf("webui: build gateway URLs: %w", err)
return err
}
gateways = append(gateways, urls...)
gateways = validGateways
} else {
// Auto-detect from configured ports
for _, p := range ports {
urls, err := buildServiceURLs(p, sslEnabled)
if err != nil {
return fmt.Errorf("webui: build gateway URLs: %w", err)
}
gateways = append(gateways, urls...)
}
// Sort so localhost/127.0.0.1 URLs appear last
sortGatewayURLs(gateways)
}
adminGateways := gateways
if len(admPorts) > 0 {
if len(webuiAdminGateways) > 0 {
// Validate explicitly provided admin gateway URLs
validAdminGateways, err := validateGatewayURLs(webuiAdminGateways, "webui admin gateway")
if err != nil {
return err
}
adminGateways = validAdminGateways
} else if len(admPorts) > 0 {
// Auto-detect from configured admin ports
adminGateways = nil
for _, admPort := range admPorts {
urls, err := buildServiceURLs(admPort, admSSLEnabled)
@@ -1041,6 +1077,8 @@ func runGateway(ctx context.Context, be backend.Backend) error {
}
adminGateways = append(adminGateways, urls...)
}
// Sort so localhost/127.0.0.1 URLs appear last
sortGatewayURLs(adminGateways)
}
if quiet {
@@ -1462,6 +1500,84 @@ func buildServiceURLs(spec string, ssl bool) ([]string, error) {
return urls, nil
}
// isLocalhost checks if a URL contains a localhost address
func isLocalhost(url string) bool {
return strings.Contains(url, "localhost") ||
strings.Contains(url, "127.0.0.1") ||
strings.Contains(url, "[::1]")
}
// validateGatewayURLs validates a list of gateway URLs and returns only valid ones.
// It prints warnings for invalid URLs and returns an error if the input list is non-empty
// but contains no valid URLs after filtering.
func validateGatewayURLs(urls []string, urlType string) ([]string, error) {
if len(urls) == 0 {
return urls, nil
}
var validURLs []string
for _, urlStr := range urls {
// Skip empty strings
if strings.TrimSpace(urlStr) == "" {
continue
}
parsedURL, err := url.Parse(urlStr)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: %v\n", urlType, urlStr, err)
continue
}
// Ensure the URL has a scheme (http or https)
if parsedURL.Scheme == "" {
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: missing scheme (must be http:// or https://)\n", urlType, urlStr)
continue
}
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: unsupported scheme %q (must be http or https)\n", urlType, urlStr, parsedURL.Scheme)
continue
}
// Ensure the URL has a host
if parsedURL.Host == "" {
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: missing host\n", urlType, urlStr)
continue
}
validURLs = append(validURLs, urlStr)
}
if len(validURLs) == 0 {
return nil, fmt.Errorf("%s URLs specified but none are valid", urlType)
}
return validURLs, nil
}
// sortGatewayURLs sorts a list of URLs so that localhost and 127.0.0.1 URLs appear last
func sortGatewayURLs(urls []string) {
if len(urls) <= 1 {
return
}
// Partition URLs into two groups: non-localhost and localhost
var nonLocal []string
var local []string
for _, url := range urls {
if isLocalhost(url) {
local = append(local, url)
} else {
nonLocal = append(nonLocal, url)
}
}
// Rebuild the slice with non-localhost first, then localhost
copy(urls, nonLocal)
copy(urls[len(nonLocal):], local)
}
// validatePortConflicts checks for port conflicts across s3 api, admin, and webui ports.
// A bare port spec (e.g., ":7071") binds to all interfaces and will conflict with any other
// binding on the same port, whether it's ":7071" or "ip:7071".
+18
View File
@@ -245,6 +245,24 @@ ROOT_SECRET_ACCESS_KEY=
# 'https://webui.example.com') to improve security.
#VGW_CORS_ALLOW_ORIGIN=
# The VGW_WEBUI_GATEWAYS option allows you to override the auto-detected S3
# gateway URLs that are provided to the Web GUI. By default, the gateway
# auto-detects URLs based on the configured VGW_PORT settings. Use this option
# to specify custom URLs when the auto-detected values are incorrect (e.g., when
# running behind a reverse proxy or load balancer). Multiple URLs can be
# specified as a comma-separated list.
# Example: VGW_WEBUI_GATEWAYS=https://s3.example.com,http://192.168.1.100:7070
#VGW_WEBUI_GATEWAYS=
# The VGW_WEBUI_ADMIN_GATEWAYS option allows you to override the auto-detected
# admin gateway URLs that are provided to the Web GUI. By default, the gateway
# auto-detects URLs based on the configured VGW_ADMIN_PORT settings (or uses the
# same URLs as VGW_WEBUI_GATEWAYS if no admin ports are configured). Use this
# option to specify custom admin URLs when the auto-detected values are incorrect.
# Multiple URLs can be specified as a comma-separated list.
# Example: VGW_WEBUI_ADMIN_GATEWAYS=https://admin.example.com,http://192.168.1.100:7080
#VGW_WEBUI_ADMIN_GATEWAYS=
#######################
# Debug / Diagnostics #
#######################