diff --git a/internal/api/v1/handlers.go b/internal/api/v1/handlers.go index 7433271..ba85a64 100644 --- a/internal/api/v1/handlers.go +++ b/internal/api/v1/handlers.go @@ -97,6 +97,40 @@ func envOrDefault(key, defaultVal string) string { return defaultVal } +// RegisterSelf registers Wild Central's own UI as a service so it gets +// DNS + proxy + TLS via its own networking stack. Idempotent — safe to +// call on every startup. Skips silently if no domain is configured. +func (api *API) RegisterSelf(port int) { + globalConfigPath := filepath.Join(api.dataDir, "config.yaml") + globalCfg, err := config.LoadGlobalConfig(globalConfigPath) + if err != nil { + return + } + + domain := globalCfg.Cloud.Central.Domain + if domain == "" { + return + } + + svc := services.Service{ + Name: "wild-central", + Source: "wild-central", + Domain: domain, + Backend: services.Backend{ + Address: fmt.Sprintf("127.0.0.1:%d", port), + Type: services.BackendHTTP, + }, + Reach: services.ReachInternal, + TLS: services.TLSTerminate, + } + + if err := api.services.Register(svc); err != nil { + slog.Warn("failed to self-register", "domain", domain, "error", err) + } else { + slog.Info("registered wild-central", "domain", domain) + } +} + // StartDDNS loads DDNS config and starts the background goroutine. func (api *API) StartDDNS(ctx gocontext.Context) { api.ctx = ctx diff --git a/main.go b/main.go index 76c9457..8df1998 100644 --- a/main.go +++ b/main.go @@ -150,6 +150,9 @@ func main() { fmt.Sscanf(v, "%d", &port) } + // Self-register Wild Central's own domain (idempotent, skips if no domain configured) + api.RegisterSelf(port) + addr := fmt.Sprintf("%s:%d", host, port) slog.Info("wild-central started", "addr", addr, "version", Version)