From a6b00f4c39cae706531eae0f6508fedaf6559f77 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 14 Mar 2025 22:04:20 -0400 Subject: [PATCH] Add basic proxy scripting support. --- goolinux.json | 2 +- main.go | 68 ++++++++++++++++++++++++++++++++--- services/proxy/caddy.template | 11 ++++-- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/goolinux.json b/goolinux.json index 1481909..51d98f9 100644 --- a/goolinux.json +++ b/goolinux.json @@ -25,7 +25,7 @@ "volumes": [ "/data/docker/navidrome:/data", "/data/music:/music:ro" - ] + ], }, "forgejo": { "enable": "true", diff --git a/main.go b/main.go index 9480644..5595775 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "path" + "strconv" "strings" "text/template" @@ -25,6 +26,7 @@ type SystemConfig struct { } type NetworkingConfig struct { + proxy map[int]string } type ServiceConfig struct { @@ -36,6 +38,7 @@ type ServiceConfig struct { Src string Ports []string Volumes []string + Proxy string Provider string Packages []string @@ -84,10 +87,15 @@ func main() { mergo.Merge(&config, systemConfig, mergo.WithOverride) } - // Parse services + // Initialize any needed maps in the config + config.Networking.proxy = make(map[int]string) + + // Parse user services for name, service := range config.Services { var b strings.Builder - var s ServiceConfig + s := ServiceConfig{ + Config: make(map[string]interface{}), + } // If no provider specified, try system if service.Provider == "" { service.Provider = "system" } @@ -101,11 +109,14 @@ func main() { // No system config to merge // Rely solely on the user config fmt.Println(" Warning: No system config for service: " + name) + continue default: fmt.Println("Error reading service config: ", err) return } - } else { + } + + { // Parse service config err = hjson.Unmarshal(c, &s) if err != nil { @@ -114,13 +125,62 @@ func main() { return } mergo.Merge(&s, service, mergo.WithOverride) + +/* + // Initialize the config map if it wasn't already + if s.Config == map[string]interface{} { + s.Config = make(map[string]interface{}) + } +*/ + config.Services[name] = s // Add service packages to the global list config.System.Packages = append(config.System.Packages, s.Packages...) + + // If a proxy definition exists, append it + if s.Proxy != "" { + ports := strings.Split(s.Ports[0], ":") + if len(ports) == 0 { + fmt.Println("Error: No port defined for proxy to", s.Proxy) + return + } + port, err := strconv.Atoi(ports[0]) + if err != nil { + fmt.Println(err) + fmt.Printf("Error: proxy for %s has an invalid port definition: %s\n", s.Proxy, ports) + return + } + + conflict, exists := config.Networking.proxy[port] + if exists == true { + fmt.Println("Error: Conflicting proxy settings:") + fmt.Printf(" %s:%s\n", conflict, port) + fmt.Printf(" %s:%s\n", s.Proxy, port) + } + + config.Networking.proxy[port] = s.Proxy + } + } + } + + // Handle any special case (scripted) configs + { + // Expand Networking.proxy to Services.proxy.Config.scripted_proxy + type proxy struct { + Domain string + Port int + } + var p []proxy + for port, domain := range config.Networking.proxy { + p = append(p, proxy{Domain: domain, Port: port}) } - // Generate service config files + config.Services["proxy"].Config["scripted_proxy"] = p + } + + // Generate service config templates + for name, s := range config.Services { for _, f := range s.ConfigFiles { var b strings.Builder f := strings.Split(f, ":") diff --git a/services/proxy/caddy.template b/services/proxy/caddy.template index f10357f..b07bd6e 100644 --- a/services/proxy/caddy.template +++ b/services/proxy/caddy.template @@ -4,7 +4,14 @@ # https://caddyserver.com/docs/caddyfile/patterns {{range .Config.proxy}} -{{.domain}} { - reverse_proxy localhost:{{.port}} +{{.Domain}} { + reverse_proxy localhost:{{.Port}} +} +{{end}} + +# Proxied services +{{range .Config.scripted_proxy}} +{{.Domain}} { + reverse_proxy localhost:{{.Port}} } {{end}}