mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-07-26 07:48:13 +00:00
feat(backend,helm)!: bind to IPv6 wildcard by default for dual-stack support
* fix: Enable Garage UI to work on IPv6-based clusters. * fix: building on nonstandard-uid machines. * fix: Enable Garage UI to work on IPv6-based clusters.
This commit is contained in:
+1
-2
@@ -48,7 +48,7 @@ RUN addgroup -g 1000 garageui && \
|
|||||||
adduser -D -u 1000 -G garageui garageui
|
adduser -D -u 1000 -G garageui garageui
|
||||||
|
|
||||||
COPY --from=backend-builder --chown=garageui:garageui /app/garage-ui .
|
COPY --from=backend-builder --chown=garageui:garageui /app/garage-ui .
|
||||||
COPY --from=frontend-builder /app/frontend/dist ./frontend/dist
|
COPY --from=frontend-builder --chown=garageui:garageui /app/frontend/dist ./frontend/dist
|
||||||
|
|
||||||
USER garageui
|
USER garageui
|
||||||
|
|
||||||
@@ -58,4 +58,3 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
CMD ["./garage-ui"]
|
CMD ["./garage-ui"]
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,16 @@ garage:
|
|||||||
region: "garage"
|
region: "garage"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Server bind host is configured by `server.host` (default: `::`). IPv6 literals like `::` and `::1` are supported.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
server:
|
||||||
|
host: "::" # IPv6 wildcard (dual-stack-preferred)
|
||||||
|
port: 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
If your environment needs explicit IPv4-only binding, set `server.host: "0.0.0.0"`.
|
||||||
|
|
||||||
See [config.example.yaml](config.example.yaml) for all options including authentication, CORS, and logging.
|
See [config.example.yaml](config.example.yaml) for all options including authentication, CORS, and logging.
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -160,7 +162,7 @@ func Load(configPath string, opts ...LoadOption) (*Config, error) {
|
|||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yaml")
|
||||||
|
|
||||||
// Built-in defaults (lowest priority)
|
// Built-in defaults (lowest priority)
|
||||||
viper.SetDefault("server.host", "0.0.0.0")
|
viper.SetDefault("server.host", "::")
|
||||||
viper.SetDefault("server.port", 8080)
|
viper.SetDefault("server.port", 8080)
|
||||||
viper.SetDefault("server.environment", "production")
|
viper.SetDefault("server.environment", "production")
|
||||||
viper.SetDefault("garage.force_path_style", true)
|
viper.SetDefault("garage.force_path_style", true)
|
||||||
@@ -383,7 +385,7 @@ func (c *Config) Validate() error {
|
|||||||
|
|
||||||
// GetAddress returns the full server address (host:port)
|
// GetAddress returns the full server address (host:port)
|
||||||
func (c *Config) GetAddress() string {
|
func (c *Config) GetAddress() string {
|
||||||
return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
|
return net.JoinHostPort(c.Server.Host, strconv.Itoa(c.Server.Port))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDevelopment returns true if running in development mode
|
// IsDevelopment returns true if running in development mode
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ func TestLoad_EnvOnly_MissingFile(t *testing.T) {
|
|||||||
if cfg.Server.Port != 9090 {
|
if cfg.Server.Port != 9090 {
|
||||||
t.Errorf("Server.Port = %d, want 9090 (from env)", cfg.Server.Port)
|
t.Errorf("Server.Port = %d, want 9090 (from env)", cfg.Server.Port)
|
||||||
}
|
}
|
||||||
|
if cfg.Server.Host != "::" {
|
||||||
|
t.Errorf("Server.Host = %q, want :: (default)", cfg.Server.Host)
|
||||||
|
}
|
||||||
if cfg.Garage.AdminToken != "env-token" {
|
if cfg.Garage.AdminToken != "env-token" {
|
||||||
t.Errorf("Garage.AdminToken = %q, want env-token", cfg.Garage.AdminToken)
|
t.Errorf("Garage.AdminToken = %q, want env-token", cfg.Garage.AdminToken)
|
||||||
}
|
}
|
||||||
@@ -367,6 +370,8 @@ func TestGetAddress(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"localhost", 8080, "localhost:8080"},
|
{"localhost", 8080, "localhost:8080"},
|
||||||
{"0.0.0.0", 80, "0.0.0.0:80"},
|
{"0.0.0.0", 80, "0.0.0.0:80"},
|
||||||
|
{"::", 80, "[::]:80"},
|
||||||
|
{"::1", 443, "[::1]:443"},
|
||||||
{"", 443, ":443"},
|
{"", 443, ":443"},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|||||||
+2
-1
@@ -219,11 +219,12 @@ func main() {
|
|||||||
addr := cfg.GetAddress()
|
addr := cfg.GetAddress()
|
||||||
logger.Info().
|
logger.Info().
|
||||||
Str("address", addr).
|
Str("address", addr).
|
||||||
|
Str("network", fiber.NetworkTCP).
|
||||||
Str("health_endpoint", fmt.Sprintf("http://%s/health", addr)).
|
Str("health_endpoint", fmt.Sprintf("http://%s/health", addr)).
|
||||||
Str("api_docs", fmt.Sprintf("http://%s/api/v1/", addr)).
|
Str("api_docs", fmt.Sprintf("http://%s/api/v1/", addr)).
|
||||||
Msg("Server starting")
|
Msg("Server starting")
|
||||||
|
|
||||||
if err := app.Listen(addr); err != nil {
|
if err := app.Listen(addr, fiber.ListenConfig{ListenerNetwork: fiber.NetworkTCP}); err != nil {
|
||||||
logger.Fatal().Err(err).Msg("Failed to start server")
|
logger.Fatal().Err(err).Msg("Failed to start server")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Server configuration
|
# Server configuration
|
||||||
server:
|
server:
|
||||||
host: "0.0.0.0"
|
host: "::" # IPv6 wildcard; dual-stack behavior depends on OS/runtime socket settings
|
||||||
port: 8080
|
port: 8080
|
||||||
environment: "development" # development, production
|
environment: "development" # development, production
|
||||||
domain: "localhost" # Domain name for the application
|
domain: "localhost" # Domain name for the application
|
||||||
|
|||||||
@@ -69,8 +69,8 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"host": {
|
"host": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Network interface to bind to (0.0.0.0 for all interfaces)",
|
"description": "Network interface to bind to (use :: for IPv6 wildcard / dual-stack-preferred, or 0.0.0.0 for IPv4 wildcard)",
|
||||||
"default": "0.0.0.0"
|
"default": "::"
|
||||||
},
|
},
|
||||||
"port": {
|
"port": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ extraObjects: []
|
|||||||
|
|
||||||
config:
|
config:
|
||||||
server:
|
server:
|
||||||
host: "0.0.0.0"
|
host: "::"
|
||||||
port: 8080
|
port: 8080
|
||||||
environment: "production"
|
environment: "production"
|
||||||
domain: "garage-ui.example.com"
|
domain: "garage-ui.example.com"
|
||||||
|
|||||||
Reference in New Issue
Block a user