docs(dns): add an operator guide for forward and reverse DNS#3652
Conversation
NICo has served forward A/AAAA, reverse PTR, derived reverse zones, and overlay-instance records for a while now with zero coverage in docs/ -- this adds `docs/configuration/dns.md`, the operator guide for the whole name story. It catalogs the four record forms (`<hostname>.<domain>`, the `adm`/`bmc` machine-id forms, and IP-derived instance names), explains `initial_domain_name` seeding and per-segment subdomains (`--subdomain-id`, required for host-inband, unset means no DNS), walks the reverse-zone lifecycle (derived per aligned prefix at segment create, removed at delete, RFC 2317 out of scope) and the PTR round-trip rules, and closes with server behavior (A/AAAA/PTR only, live answers, NXDomain-for-NODATA, 300s TTL), resolver advertisement, and a troubleshooting table. Writing it against the code surfaced real errors in the existing DNS section of `ip-and-network-configuration.md`, fixed here so the two pages agree: the "PowerDNS remote backend (default)" mode it documents does not exist anywhere in the repo (`carbide-dns` is standalone-only), the Kea hook parameter is `carbide-nameservers` (the documented `nico-nameserver` is silently ignored), and the compiled service-name TLD is `.forge` with `carbide-*` names (the section claimed `.nico` twice). `host-naming.md` and the section now cross-link the new page. This supports NVIDIA#3641 Signed-off-by: Chet Nichols III <chetn@nvidia.com>
|
@coderabbitai full_review, thanks! |
|
🐇🔍 ✅ Action performedFull review finished. |
Summary by CodeRabbit
WalkthroughAdds a DNS configuration guide and navigation entry, updates resolver and DHCP documentation, clarifies ChangesDNS documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
🌿 Preview your docs: https://nvidia-preview-pull-request-3652.docs.buildwithfern.com/infra-controller |
🔍 Container Scan SummaryNo Grype artifacts were found to aggregate. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/configuration/dns.md`:
- Line 49: Update the DHCP option description in the DNS documentation to
distinguish option 12 as the host name and option 15 as the domain name, stating
that clients compose the FQDN from those values where applicable. Avoid implying
either option independently carries the full FQDN.
In `@docs/provisioning/ip-and-network-configuration.md`:
- Around line 279-282: Rewrite section 3.3 to use the single .nico endpoint
naming convention consistently across its prose, table, verification steps, and
references to deploy/DNS.md. Remove the .forge alternative and correct any
duplicated TLD in the note so operators provision only records queried by the
documented binaries.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 9c84c82a-c3c4-487c-83e9-2998cb35afaa
📒 Files selected for processing (4)
docs/configuration/dns.mddocs/configuration/host-naming.mddocs/index.ymldocs/provisioning/ip-and-network-configuration.md
| - `nico-dns` answers A, AAAA, and PTR queries only; every other type answers "not implemented". It never recurses, and it serves no SOA or NS records and no zone transfers, so put it behind your recursive resolver (a forward zone works best) rather than in a client's resolver list. | ||
| - Answers reflect the database live: there is no positive cache and no zone-serial machinery. A record change is visible on the next query. | ||
| - A name that exists with only the other address family answers NXDomain rather than an empty answer, and negative answers are cached at the edge briefly (120 seconds by default). | ||
| - Hosts learn their own FQDN over DHCP option 12 on every path; hosts served by a DPU also receive it as DHCP option 15. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== docs/configuration/dns.md (around line 49) ==\n'
nl -ba docs/configuration/dns.md | sed -n '1,120p'
printf '\n== search for DHCP option / FQDN references ==\n'
rg -n --hidden --glob 'docs/**' --glob '!**/.git/**' 'option 12|option 15|FQDN|host name|domain name|DHCP' .
printf '\n== file list for DNS docs ==\n'
git ls-files 'docs/**' | rg 'dns|dhcp|configuration'Repository: NVIDIA/infra-controller
Length of output: 251
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== docs/configuration/dns.md (around line 49) ==\n'
sed -n '1,120p' docs/configuration/dns.md | cat -n
printf '\n== search for DHCP option / FQDN references in docs ==\n'
rg -n --hidden --glob 'docs/**' --glob '!**/.git/**' 'option 12|option 15|FQDN|host name|domain name|DHCP' docs
printf '\n== DNS-related docs files ==\n'
git ls-files 'docs/**' | rg 'dns|dhcp|configuration'Repository: NVIDIA/infra-controller
Length of output: 50382
Clarify DHCP option 12/15 wording. Option 12 is the host name and option 15 is the domain name. This reads as if both carry the FQDN; state the exact payloads, or note that clients compose the FQDN from the two values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/configuration/dns.md` at line 49, Update the DHCP option description in
the DNS documentation to distinguish option 12 as the host name and option 15 as
the domain name, stating that clients compose the FQDN from those values where
applicable. Avoid implying either option independently carries the full FQDN.
Sources: Path instructions, MCP tools
| - **`.forge`** is the compiled default in `crates/agent/src/util.rs` and the host PXE loader scripts. The agent resolves `carbide-pxe.forge`, `carbide-ntp.forge`, etc. at startup. This is the TLD used by deployments built from the current binaries. | ||
| - **`.nico`** is the rebranded TLD documented in [`deploy/DNS.md`](https://github.com/NVIDIA/infra-controller/blob/main/deploy/DNS.md). New deployments may use this convention, but only if the agent and PXE images have been rebuilt with the new TLD. | ||
|
|
||
| Choose the convention that matches your binaries — do not mix. Verify by checking what the agent actually resolves at startup (`kubectl exec -n nico-system <agent-pod> -- getent hosts nico-pxe.nico` or the `.nico` equivalent). | ||
| Choose the convention that matches your binaries — do not mix. Verify by checking what the agent actually resolves at startup (`kubectl exec -n nico-system <agent-pod> -- getent hosts carbide-pxe.forge` or the `.nico` equivalent). |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## docs/provisioning/ip-and-network-configuration.md\n'
sed -n '240,330p' docs/provisioning/ip-and-network-configuration.md | cat -n
printf '\n## deploy/DNS.md\n'
sed -n '1,260p' deploy/DNS.md | cat -n
printf '\n## repository search\n'
rg -n --hidden --glob '!**/.git/**' -e 'carbide-pxe\.forge|carbide-ntp\.forge|nico-\*|nico-system|carbide-nameservers|nico-nameserver|\.forge|\.nico' .Repository: NVIDIA/infra-controller
Length of output: 50380
🌐 Web query:
NVIDIA infra-controller deploy/DNS.md nico-nameserver carbide-nameservers forge nico endpoints
💡 Result:
The terms you referenced relate to the rebranding of the NVIDIA Infrastructure Controller (NICo) [1][2]. Previously, the project was known as Carbide (for core infrastructure components) and Forge (for the REST API and related management services) [3][4][5]. Key details regarding the transition: 1. Rebranding: As of mid-2026, all references to carbide and forge have been renamed to NICo (NVIDIA Infrastructure Controller) across source code, Helm charts, container images, and documentation [1][3][6][5]. 2. Deployment Documentation: The file deploy/DNS.md serves as the canonical reference for NICo service hostnames, ports, and DNS configuration [7]. 3. Legacy Compatibility: While the rebranding is comprehensive, some legacy naming persists in specific areas for backward compatibility, such as the forge.nvidia.io API group in Custom Resource Definitions (CRDs) and internal gRPC service names [6][5]. 4. Infrastructure Components: The transition replaced previous naming conventions (e.g., carbide-nsm, carbide-psm, carbide-rest-api) with new NICo-prefixed equivalents (e.g., nico-nsm, nico-psm, nico-rest-api) [1][4]. For up-to-date deployment instructions and configuration, you should consult the official NVIDIA Infra Controller documentation, which provides the current standards for NICo-based environments [7][2][8].
Citations:
- 1: NVIDIA/infra-controller-rest@a398665
- 2: https://github.com/NVIDIA/infra-controller
- 3: Remove/rename old well-known hostnames to NICo branding #2600
- 4: https://github.com/NVIDIA/infra-controller-rest
- 5: https://github.com/NVIDIA/infra-controller-rest/blob/main/CHANGELOG.md
- 6: feat: Rename carbide/forge to NVIDIA Infrastructure Controller (NICo) infra-controller-rest#432
- 7: https://docs.nvidia.com/infra-controller/documentation/provisioning-day-0/ip-and-network-configuration
- 8: https://docs.nvidia.com/infra-controller/documentation/architecture/overview-and-components
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## docs/provisioning/ip-and-network-configuration.md (around disputed lines)\n'
sed -n '270,295p' docs/provisioning/ip-and-network-configuration.md | cat -n
printf '\n## deploy/DNS.md (top + hostname section)\n'
sed -n '1,220p' deploy/DNS.md | cat -n
printf '\n## focused term search in the two docs\n'
rg -n --no-heading '\.forge|\.nico|carbide-nameservers|nico-nameserver|carbide-pxe|carbide-ntp|nico-' docs/provisioning/ip-and-network-configuration.md deploy/DNS.mdRepository: NVIDIA/infra-controller
Length of output: 49101
Use one endpoint naming contract in section 3.3. The current text mixes .forge and .nico, while the table, verification loop, and deploy/DNS.md are .nico-only. Rewrite the whole section to one convention and fix the duplicated TLD in the note, or operators will provision DNS records their binaries never query.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/provisioning/ip-and-network-configuration.md` around lines 279 - 282,
Rewrite section 3.3 to use the single .nico endpoint naming convention
consistently across its prose, table, verification steps, and references to
deploy/DNS.md. Remove the .forge alternative and correct any duplicated TLD in
the note so operators provision only records queried by the documented binaries.
Sources: Coding guidelines, Path instructions, MCP tools
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/configuration/dns.md`:
- Line 48: Update the DNS response handling described in the configuration
documentation so an existing name with no records for the requested address
family returns NOERROR/NODATA rather than NotFound/NXDOMAIN. Ensure qtype
filtering does not convert an empty result into a negative name lookup or apply
the 120-second NXDOMAIN cache; reserve NotFound/NXDOMAIN for names absent
entirely.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: fe1e67fe-ca37-4180-9843-4b1fc8ad15b6
📒 Files selected for processing (4)
docs/configuration/dns.mddocs/configuration/host-naming.mddocs/index.ymldocs/provisioning/ip-and-network-configuration.md
|
|
||
| - `nico-dns` answers A, AAAA, and PTR queries only; every other type answers "not implemented". It never recurses, and it serves no SOA or NS records and no zone transfers, so put it behind your recursive resolver (a forward zone works best) rather than in a client's resolver list. | ||
| - Answers reflect the database live: there is no positive cache and no zone-serial machinery. A record change is visible on the next query. | ||
| - A name that exists with only the other address family answers NXDomain rather than an empty answer, and negative answers are cached at the edge briefly (120 seconds by default). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the documentation and any implementation/docs references for the DNS behavior.
git ls-files 'docs/configuration/dns.md' 'docs/**' '**/*' | sed -n '1,200p'
printf '\n--- dns.md context ---\n'
wc -l docs/configuration/dns.md
sed -n '1,120p' docs/configuration/dns.md
printf '\n--- search for NXDOMAIN / NODATA / negative caching references ---\n'
rg -n --hidden --glob '!**/.git/**' -S 'NXDomain|NXDOMAIN|NODATA|negative cache|negative caching|A record|AAAA record|other address family|nico-dns|DNS' docs . || true
printf '\n--- map likely DNS implementation files ---\n'
fd -t f -i 'dns' . || true
fd -t f -i 'resolver' . || true
fd -t f -i 'name server' . || trueRepository: NVIDIA/infra-controller
Length of output: 50382
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- docs/configuration/dns.md around the cited line ---'
cat -n docs/configuration/dns.md | sed -n '35,60p'
printf '\n%s\n' '--- targeted search for DNS response behavior ---'
rg -n -S -m 50 'NXDOMAIN|NODATA|NOERROR|negative caching|negative cache|AAAA|A record|other address family|dns' \
--glob '!**/.git/**' \
docs . || true
printf '\n%s\n' '--- likely DNS implementation files (names only) ---'
fd -t f -i 'dns' . || true
fd -t f -i 'resolver' . || true
fd -t f -i 'name' . || trueRepository: NVIDIA/infra-controller
Length of output: 50380
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- exact dns.md line context ---'
cat -n docs/configuration/dns.md | sed -n '42,52p'
printf '\n%s\n' '--- direct mentions of nico-dns / NXDOMAIN in repo ---'
rg -n -S -m 50 'nico-dns|NXDOMAIN|NXDomain|NODATA|NOERROR|negative answers|negative caching|edge briefly|other address family|AAAA|A record' \
docs README.md .github . || true
printf '\n%s\n' '--- filenames that look DNS-related ---'
fd -t f -i 'dns' . || true
fd -t f -i 'resolver' . || true
fd -t f -i 'zone' . || trueRepository: NVIDIA/infra-controller
Length of output: 50380
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- docs/configuration/dns.md ---'
cat -n docs/configuration/dns.md | sed -n '40,55p'
printf '\n%s\n' '--- repo files with dns in the path/name ---'
git ls-files | rg '(^|/)(dns|DNS|resolver|Resolver|zone|Zone)(/|\.|$)' || true
printf '\n%s\n' '--- direct mentions of nico-dns in tracked files ---'
rg -n -S -m 20 'nico-dns' docs .github README.md . || trueRepository: NVIDIA/infra-controller
Length of output: 43262
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- outline: crates/dns/src/main.rs ---'
ast-grep outline crates/dns/src/main.rs --view expanded || true
printf '\n%s\n' '--- outline: crates/dns/src/negative_cache.rs ---'
ast-grep outline crates/dns/src/negative_cache.rs --view expanded || true
printf '\n%s\n' '--- targeted search in DNS crate for response semantics ---'
rg -n -S -m 200 'NXDOMAIN|NXDomain|NODATA|NoData|NOERROR|negative cache|negative_cache|SOA|rcode|ResponseCode|QueryType|AAAA|Aaaa|A record|AAAA record|not implemented' \
crates/dns/src crates/dns/tests crates/dns/src/test crates/api-core/src/tests/dns.rs || true
printf '\n%s\n' '--- show relevant slices from implementation files ---'
for f in crates/dns/src/main.rs crates/dns/src/negative_cache.rs crates/dns/src/lib.rs; do
if [ -f "$f" ]; then
echo "FILE: $f"
wc -l "$f"
fi
done
# print focused regions if file size is reasonable
sed -n '1,260p' crates/dns/src/negative_cache.rs 2>/dev/null || true
sed -n '1,260p' crates/dns/src/main.rs 2>/dev/null || trueRepository: NVIDIA/infra-controller
Length of output: 37542
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- crates/dns/src/lib.rs around query handling ---'
sed -n '320,440p' crates/dns/src/lib.rs
printf '\n%s\n' '--- crates/dns/src/lib.rs around tests / expected rcodes ---'
sed -n '640,830p' crates/dns/src/lib.rs
printf '\n%s\n' '--- crates/dns/src/config.rs negative-cache defaults ---'
sed -n '60,120p' crates/dns/src/config.rsRepository: NVIDIA/infra-controller
Length of output: 16170
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- retrieve_records implementation and call sites ---'
rg -n -S -m 50 'fn retrieve_records|retrieve_records\(' crates/dns/src/lib.rs crates/dns/src/*.rs crates/api-core/src/**/*.rs || true
printf '\n%s\n' '--- api-core DNS lookup contract / tests ---'
rg -n -S -m 100 'LookupRecord|lookup_record|NotFound|NXDomain|AAAA|A record|other address family|dns_records|dns_records_shortname_combined' \
crates/api-core/src crates/api-model/src crates/rpc/src || true
printf '\n%s\n' '--- focused slices around any lookup_record handlers ---'
sed -n '1,260p' crates/api-core/src/handlers/dns.rs 2>/dev/null || true
sed -n '1,260p' crates/api-db/src/dns/resource_record.rs 2>/dev/null || trueRepository: NVIDIA/infra-controller
Length of output: 50379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- crates/dns/src/lib.rs retrieve_records ---'
sed -n '492,620p' crates/dns/src/lib.rs
printf '\n%s\n' '--- any DNS tests around missing-address-family behavior ---'
rg -n -S -m 50 'AAAA.*NXDomain|NXDomain.*AAAA|A.*NXDomain|other address family|empty answer|NoError|not found|missing.*family|family.*missing' crates/dns/src/lib.rs crates/dns/src/test crates/api-core/src/tests/dns.rs || trueRepository: NVIDIA/infra-controller
Length of output: 6041
Return NODATA, not NXDOMAIN, for missing address-family lookups
A name that exists with only A or only AAAA should answer NOERROR/NODATA. This path filters the API result by qtype, turns an empty set into NotFound/NXDOMAIN, and caches it for 120s, which makes a valid name look nonexistent to recursive resolvers.
🧰 Tools
🪛 LanguageTool
[style] ~48-~48: ‘that exists with’ might be wordy. Consider a shorter alternative.
Context: ... is visible on the next query. - A name that exists with only the other address family answers N...
(EN_WORDINESS_PREMIUM_THAT_EXISTS_WITH)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/configuration/dns.md` at line 48, Update the DNS response handling
described in the configuration documentation so an existing name with no records
for the requested address family returns NOERROR/NODATA rather than
NotFound/NXDOMAIN. Ensure qtype filtering does not convert an empty result into
a negative name lookup or apply the 120-second NXDOMAIN cache; reserve
NotFound/NXDOMAIN for names absent entirely.
Source: Path instructions
Adds
docs/configuration/dns.md-- the operator guide for NICo name resolution: the record catalog (hostname,adm/bmcmachine-id, and instance forms),initial_domain_nameand per-segment subdomains, the derived reverse-zone lifecycle and PTR round-trip rules, server behavior, resolver advertisement, and troubleshooting.Writing it against the code surfaced real errors in
ip-and-network-configuration.md's DNS section, fixed here so the pages agree: the documented "PowerDNS remote backend (default)" mode does not exist in the repo, the Kea hook parameter iscarbide-nameservers(notnico-nameserver), and the compiled service-name TLD is.forge(the section said.nicotwice).host-naming.mdcross-links the new page.This supports #3641