Skip to content

fix(net): pass WireGuard endpoint to sly-net-client only when explicitly overridden - #125

Merged
tonybart1337 merged 1 commit into
masterfrom
fix/net-server-address-explicit-override
Jul 28, 2026
Merged

fix(net): pass WireGuard endpoint to sly-net-client only when explicitly overridden#125
tonybart1337 merged 1 commit into
masterfrom
fix/net-server-address-explicit-override

Conversation

@tonybart1337

@tonybart1337 tonybart1337 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Problem

_start_net_client always passed the WireGuard endpoint as the 3rd positional argument to sly-net-client:

command = [
    constants.TOKEN(),
    urljoin(constants.SERVER_ADDRESS(), "net/"),
    constants.NET_SERVER_ADDRESS(),   # always present
]

That argument is an override. When it is empty, the client instead uses the endpoint the server hands it during registration.

NET_SERVER_ADDRESS() never returned an empty value — when the env var was unset it synthesized <server hostname>:<NET_SERVER_PORT> (default 51822). Arg 3 was therefore always non-empty, the override was always in force, and the server-advertised endpoint could never take effect.

Consequence: changing the agent-facing endpoint requires recreating the net-client container on every host, rather than being a server-side setting.

Change

  • constants.NET_SERVER_ADDRESS() returns None when NET_SERVER_ADDRESS is unset or empty. When it is set, behaviour is unchanged, including the existing http://-prefixing normalization.
  • main._start_net_client appends arg 3 only when that value is truthy, and logs when it is omitted.

"Explicitly overridden" still covers both legitimate paths:

  • the server sending netClientOptions.netServerAddress via GetAgentOptions (agent_utils.update_env_param(constants._NET_SERVER_ADDRESS, ...))
  • an operator setting NET_SERVER_ADDRESS directly on the agent container

Only the agent-invented hostname:NET_SERVER_PORT fallback is dropped — that is what pins agents to a stale endpoint.

main.py:_start_net_client was the only caller of NET_SERVER_ADDRESS() (verified by grep over the whole repo), so no other consumer changes. The NET_SERVER_PORT() guard in _start_net_client is left untouched.

Verification

No test covers this path; the repo's suite is tests/clean_functions + tests/test_run_daemon.py and is unrelated. Baseline and post-change pytest results are identical (3 failed, 10 passed; the 3 failures are pre-existing FileNotFoundError: /sly_agent/apps_cache, i.e. they expect an agent-container filesystem). pylint (what CI runs) scores 10.00/10 on both changed files.

The real _start_net_client was executed with a fake docker API to capture the actual command:

NET_SERVER_ADDRESS before after
unset […, '<server-host>:51822'] 2 args, no override
"" / whitespace […, '<server-host>:51822'] 2 args, no override
vpn.example.com:51825 […, 'vpn.example.com:51825'] […, 'vpn.example.com:51825']
https://vpn.example.com:9999 […, 'vpn.example.com:9999'] […, 'vpn.example.com:9999']

Notes for the reviewer

  • Not retroactive. Agents that already have a baked arg 3 in their running net-client container keep using it; they still need one net-client recreation to adopt the new behaviour.
  • Omitting the argument is equivalent to passing an empty one. Checked against the net-client entrypoint: it reads the argument once and does not run with set -u, so with two arguments it expands to the empty string and the override is simply not applied. Worth re-confirming against whichever image tag you deploy.
  • Worth knowing: git log -S shows arg 3 has been unconditionally present since before NET_SERVER_ADDRESS was introduced (4db1a02, Sep 2024 — the pre-existing code synthesized the same hostname:port inline). The empty-arg path has effectively never been exercised by a released agent, so this is the first traffic through it.

🤖 Generated with Claude Code

The agent always passed the WireGuard endpoint as the 3rd positional argument
to sly-net-client. That argument is an *override*: when it is empty, the client
uses the endpoint the server returns to it at registration instead.

NET_SERVER_ADDRESS() never returned an empty value — when the env var was unset
it synthesized "<server hostname>:<NET_SERVER_PORT>" (default port 51822). So
arg 3 was always non-empty, the override was always in force, and the endpoint
advertised by the server could never take effect. Changing the agent-facing
endpoint therefore required recreating the net-client container on every host
instead of being a server-side setting.

NET_SERVER_ADDRESS() now returns None when the env var is unset or empty, and
main.py appends arg 3 only when it is truthy. A value is still returned — with
the existing http:// normalization — whenever the variable is actually set,
which covers both real override paths: the server sending
netClientOptions.netServerAddress via GetAgentOptions, and an operator setting
it directly on the agent container. Only the agent's own synthesized fallback
is dropped, since that is what pinned agents to a stale endpoint.

main.py:_start_net_client was the only caller of NET_SERVER_ADDRESS(), so no
other consumer is affected. The NET_SERVER_PORT() guard is left untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tonybart1337
tonybart1337 force-pushed the fix/net-server-address-explicit-override branch from 9f5221c to 257bb6f Compare July 28, 2026 18:23
@tonybart1337
tonybart1337 merged commit 9833598 into master Jul 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant