feat: Self-register Wild Central on startup

On startup, Wild Central registers its own domain (from config
cloud.central.domain) as an HTTP service with itself. This creates
the DNS entry, proxy route, and TLS cert needed to access the
Central UI via its domain name.

Registration is idempotent — safe on every restart. Skips silently
if no domain is configured. Logs a warning if registration fails.

Verified: after startup, /api/v1/services shows wild-central
registered with domain central.payne.io.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 05:40:27 +00:00
parent 909527f060
commit 57a597fe5a
2 changed files with 37 additions and 0 deletions

View File

@@ -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

View File

@@ -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)