Summary
nextdeploy ship writes a DNS guide instructing the operator to point an A record at the deployment server's config nickname instead of its address. On a config with name: production, dns.md reads:
Server IP: **production**
The generated A @ production record is not a record. The same value also lands in the HTML deployment report as "Server IP", and in the 🚨 DNS ACTION REQUIRED banner printed at the end of a successful ship.
Cause
GetDeploymentServer returns the server's Name — correct for its primary purpose, since that is the key ServerStruct.sshClients is indexed by and what every ExecuteCommand / UploadFile call needs:
// cli/internal/server/server.go:120
func (s *ServerStruct) GetDeploymentServer() (string, error) {
...
first := s.config.Servers[0]
...
return first.Name, nil
}
shipVPS then passes that same value into three user-facing places that mean address, not identifier:
cli/cmd/ship.go:158 — dns.GenerateVPSGuide(cfg.App.Domain.Name, deploymentServer), whose second parameter is declared serverIP string (cli/internal/dns/guide.go:122)
cli/cmd/ship.go:249 — VPSResourceMap{ ServerIP: deploymentServer }
cli/cmd/ship.go:262 — the DNS-action banner
It only reads correctly when servers[0].name happens to be spelled the same as servers[0].host.
Reproduction
# nextdeploy.yml
target_type: vps
app:
name: demo
domain: example.com
servers:
- name: production
host: 203.0.113.10
username: deploy
key_path: ~/.ssh/id_ed25519
$ nextdeploy ship
$ grep 'Server IP' dns.md
Server IP: **production**
Expected 203.0.113.10.
Impact
Low severity, high friction. Nothing breaks in the deploy itself — but dns.md is the artifact a first-time user follows to get their domain working, and it is wrong in exactly the step where they have the least context to notice. The HTML report repeats it.
Suggested fix
Keep GetDeploymentServer returning the name (its callers need it), and add a lookup for the address:
// ServerHost returns the network address configured for the named server.
func (s *ServerStruct) ServerHost(name string) (string, error)
Then resolve once in shipVPS and use the result for the DNS guide, the resource map, and the banner. Erroring rather than falling back to the name keeps a misconfigured servers: entry from silently reintroducing the bug.
A fix along these lines is prepared locally (adds ServerHost + unit tests, rewires the three call sites) and is not yet pushed.
Summary
nextdeploy shipwrites a DNS guide instructing the operator to point anArecord at the deployment server's config nickname instead of its address. On a config withname: production,dns.mdreads:The generated
A @ productionrecord is not a record. The same value also lands in the HTML deployment report as "Server IP", and in the🚨 DNS ACTION REQUIREDbanner printed at the end of a successful ship.Cause
GetDeploymentServerreturns the server'sName— correct for its primary purpose, since that is the keyServerStruct.sshClientsis indexed by and what everyExecuteCommand/UploadFilecall needs:shipVPSthen passes that same value into three user-facing places that mean address, not identifier:cli/cmd/ship.go:158—dns.GenerateVPSGuide(cfg.App.Domain.Name, deploymentServer), whose second parameter is declaredserverIP string(cli/internal/dns/guide.go:122)cli/cmd/ship.go:249—VPSResourceMap{ ServerIP: deploymentServer }cli/cmd/ship.go:262— the DNS-action bannerIt only reads correctly when
servers[0].namehappens to be spelled the same asservers[0].host.Reproduction
Expected
203.0.113.10.Impact
Low severity, high friction. Nothing breaks in the deploy itself — but
dns.mdis the artifact a first-time user follows to get their domain working, and it is wrong in exactly the step where they have the least context to notice. The HTML report repeats it.Suggested fix
Keep
GetDeploymentServerreturning the name (its callers need it), and add a lookup for the address:Then resolve once in
shipVPSand use the result for the DNS guide, the resource map, and the banner. Erroring rather than falling back to the name keeps a misconfiguredservers:entry from silently reintroducing the bug.A fix along these lines is prepared locally (adds
ServerHost+ unit tests, rewires the three call sites) and is not yet pushed.