feat: NodeHostField — dial NodesKey peers by name, not raw IP - #71
Merged
Conversation
Add an opt-in Config.NodeHostField: when set, parseNodeAddr uses that JSON field of a node entry as the dial host (combined with the entry's port) instead of "ip", falling back to ip per-entry when the field is absent or blank. Empty (default) preserves the historical ip:port behavior byte-for-byte. This lets a leader dial nodes by a DNS name so a name-only TLS leaf (no IP SAN) validates under standard hostname verification — the leader→node health check and trigger-sync no longer fail with "tls: bad certificate" when SSL is on. Threaded through nodesCache and makeGetNodes; new TestParseNodeAddr covers override, per-entry fallback, and defaults. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
benitogf
approved these changes
Jun 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #72
Problem
When
SSLis on, the leader dials eachNodesKeypeer over HTTPS for the health-check (/_pivot/version) and trigger-sync (/_pivot/synchronize/pivot).parseNodeAddrbuilds that URL from the entry'sip+port, so the dial ishttps://<ip>:<port>/…. A peer whose TLS leaf is name-only (no IP SAN — the common case for an internally-enrolled, DNS-named device) can't satisfy standard hostname verification against an IP literal, so the handshake fails and the peer floods its log withtls: bad certificate. The peer is perfectly reachable and verifiable by name — only the raw-IP dial is wrong.Fix
Add an opt-in
Config.NodeHostField string:parseNodeAddrreturnsip:portexactly as before."host"): the named JSON field of each node entry is used as the dial host (combined with the entry's port). Resolution is per-entry: an entry missing or blank in that field falls back to itsip, so a mixed fleet stays reachable.The consumer writes a DNS name into that field; the leader then dials
https://<name>:<port>/…, which resolves to the peer and validates against its name-only leaf under ordinary hostname verification. NoInsecureSkipVerify, no mTLS plumbing — just dial by the name the cert actually bears.Threaded through
nodesCacheandmakeGetNodes(the onlyparseNodeAddrcall sites).Tests
New
TestParseNodeAddrcovers: defaultip/IPextraction, field-ignored-when-unconfigured, override-when-present, per-entry fallback when blank/absent, quoted-string port, and the empty/invalid cases. Full suite green;go vetandgofmtclean.Compatibility
Fully backward-compatible: callers that don't set
NodeHostFieldsee identical behavior.🤖 Generated with Claude Code