Commit Graph

9 Commits

Author SHA1 Message Date
Paul Payne
3c99d26830 Auto-detect Central domain for CORS allowed origins
Read the configured Central domain from state.yaml and add it as an
HTTPS origin so the web UI at e.g. https://central.payne.io works
without manually setting WILD_CENTRAL_CORS_ORIGINS.
2026-07-10 19:12:27 +00:00
Paul Payne
c18217944f feat: Add EnsureCentralService + improved tests
Linter-contributed improvements:
- EnsureCentralService() method: registers Central's own domain as a
  service from config, with cleanup on domain change
- Tests for EnsureCentralService: registration, idempotency, domain
  change cleanup, no-domain-is-noop
- Improved reconciliation tests with Central as a registered service
- Certbot handler cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 22:26:56 +00:00
Paul Payne
995d2cd7da fix: Run Reconcile after SetPort so Central routes to correct port
Reconcile() was called before SetPort(), so getRunningPort() returned
the default 5055 (Wild Cloud's port) instead of 15055. Moved
Reconcile() after SetPort(port) so Central's config-driven HAProxy
route points to the actual running port.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 20:57:59 +00:00
Paul Payne
e5cd6583f2 feat: Add comprehensive tests + fix startup reconciliation
Tests added (13 new):
- HAProxy ACL ordering: L7 before L4 wildcard, L4 exact before L4 wildcard
- HAProxy subdomains: false=exact only, true=wildcard+exact
- Reconciliation integration: HAProxy config from services, DNS config
  from services, Central config domain injection, correct DNS target IPs
- dnsmasq: reach:internal has local=/, reach:public does not
- Services: idempotent registration, no duplicates in list

Bug fix:
- Run initial reconciliation on startup so Central's own domain (from
  config) gets HAProxy + DNS routes even with zero registered services.
  Previously, Central only got routes after the first service was
  registered, causing 503 on fresh restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 20:55:27 +00:00
Paul Payne
548be903e7 feat: Fix HAProxy ACL ordering + Subdomains field
Rewrite HAProxy config generation with correct ACL ordering:
1. L7 HTTP exact matches first (central, wild-cloud app)
2. L4 exact matches (payne.io, civilsociety.dev)
3. L4 wildcard matches (*.cloud.payne.io) — only when subdomains:true
4. Default → L7 termination

Key changes:
- InstanceRoute: removed ExtraDomains, added Subdomains bool
- GenerateOpts: removed CentralDomain (Central is now just another
  HTTPRoute injected by reconciliation), renamed WildcardCert→CertsDir
- Central's domain comes from config, injected as HTTPRoute with
  the actual running port (no more hardcoded 5055)
- Added API.SetPort() so reconciliation knows the running port
- subdomains:false → exact match only (no *.domain shadowing)

New tests: TestGenerate_WithSubdomains, TestGenerate_ACLOrdering
(verifies L7 exact matches come before L4 wildcards).

Fixes: BUG 1 (central routing to wrong port), BUG 2 (wild-cloud
getting traefik cert), BUG 3 (*.payne.io too broad).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 20:29:30 +00:00
Paul Payne
57a597fe5a 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>
2026-07-09 05:40:27 +00:00
Paul Payne
2a09102e23 feat: Add configurable API port via WILD_CENTRAL_PORT env var
Allow overriding the default API port (5055) for development and
testing when the production daemon is already running.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 01:11:25 +00:00
Paul Payne
6b58ebb692 feat: Add embedded NATS JetStream coordination bus
Central now starts an embedded NATS JetStream server as its core
coordination bus. This provides:

- wild-services KV bucket: service registrations from Cloud/Works
- wild-presence KV bucket: node liveness with TTL-based keys
- wild-events stream: events from all sources (24h retention)

NATS is started in main.go before the API and shut down on SIGTERM.
Cloud and Works will connect to Central's NATS (port 4222) to register
services and maintain presence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-08 23:36:40 +00:00
Paul Payne
beb643f76f feat: Extract Wild Central as standalone Go service
Extract the Central networking functionality from wild-cloud/api into
a standalone service. Wild Central manages DNS (dnsmasq), gateway
(HAProxy), firewall (nftables), VPN (WireGuard), TLS (certbot),
security (CrowdSec), and DDNS — all the network appliance concerns.

All Cloud-specific code (instances, clusters, nodes, apps, backups,
operations, kubectl/talosctl tooling) has been removed. The API struct
and route registration contain only Central endpoints. Tests updated
to match the new API signature.

Builds and all tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-08 23:31:16 +00:00