c730cfaa45
Add flexible DNS management to Docker Watcher. By default, wildcard DNS is assumed (current behavior). When disabled, users can configure a Cloudflare DNS provider with API token and zone selection. DNS A records are automatically created/updated/deleted in sync with proxy consumers (deployed instances and standalone proxies). - Settings: wildcard_dns toggle, dns_provider, cloudflare credentials - Cloudflare client: Provider interface with EnsureRecord/DeleteRecord/ListRecords - DNS lifecycle hooks in deployer and proxy manager (best-effort) - Settings UI: DNS config section with provider picker, zone selector, test button - DNS Records page at /dns with filtering, sync status, reconciliation - Records visible in both wildcard and managed modes - Cleanup on provider change: removes old records when switching modes
3.1 KiB
3.1 KiB
Phase 3: DNS Lifecycle Hooks
Status: ⬜ Not Started Parent plan: PLAN.md Domain: backend
Objective
Hook DNS record management into the deployer and standalone proxy manager so that DNS records are automatically created/updated/deleted in sync with proxy consumers.
Tasks
- Task 1: Create
dns_recordstable for tracking managed records- Columns: id, fqdn, provider_record_id, consumer_type (instance/standalone), consumer_id, created_at, updated_at
- Store queries: CreateDNSRecord, DeleteDNSRecord, GetDNSRecordByFQDN, ListDNSRecords, GetDNSRecordsByConsumer
- Task 2: Add DNS provider to
Deployerstruct- Accept
dns.Providerin constructor (can be nil for wildcard mode) - Helper:
ensureDNS(ctx, fqdn, deployID)— calls provider.EnsureRecord + saves to dns_records - Helper:
removeDNS(ctx, fqdn, deployID)— calls provider.DeleteRecord + removes from dns_records
- Accept
- Task 3: Hook into deployer — instance creation
- After
configureProxysucceeds indeployer.goandbluegreen.go→ callensureDNS - FQDN =
subdomain + "." + settings.Domain
- After
- Task 4: Hook into deployer — instance removal
- In
removeInstanceafter NPM proxy deletion → callremoveDNS - In
rollbackafter NPM proxy deletion → callremoveDNS
- In
- Task 5: Hook into standalone proxy manager
CreateProxy→ after NPM host created, callensureDNSUpdateProxy→ if domain changed,removeDNS(old)+ensureDNS(new)DeleteProxy→ callremoveDNS
- Task 6: Wire DNS provider into main.go
- Read settings on startup, create provider if non-wildcard
- Pass provider to Deployer and proxy Manager constructors
- Handle provider being nil (wildcard mode = no DNS ops)
- Task 7: Add
DNSRecordmodel tointernal/store/models.go
Files to Modify/Create
internal/store/models.go— add DNSRecord structinternal/store/store.go— add dns_records table migrationinternal/store/dns_records.go— CRUD queriesinternal/deployer/deployer.go— add DNS hooksinternal/deployer/bluegreen.go— add DNS hooksinternal/deployer/rollback.go— add DNS cleanupinternal/proxy/manager.go— add DNS hookscmd/server/main.go— wire DNS provider
Acceptance Criteria
- DNS records created when proxy consumers are created (if non-wildcard mode)
- DNS records deleted when proxy consumers are removed
- DNS records updated when standalone proxy domain changes
- All DNS operations are best-effort (log warning on failure, don't block)
- dns_records table tracks all managed records
- Wildcard mode (default) skips all DNS operations
Notes
- DNS operations must be wrapped in error handling that logs but doesn't fail the deploy
- The dns_records table is the local source of truth for reconciliation (Phase 6)
- Provider can be nil — all hooks must check for nil before calling
Review Checklist
- All tasks completed
- Code follows project conventions
- No unintended side effects
- Build passes
- Tests pass (new + existing)