Skip to main content

Node networking

This article refers to SDK version v0.5.0. The current SDK version is N/A.

Overview

client.nodes.network covers the Networking card on a node's detail page in Panel: physical Ethernet, WiFi, and Mobile interfaces, VLANs, the node's hostname, VPN, Proxy, Standalone Mode, IPTables, and NTP servers. Every write is checked, best-effort and non-blocking, against the caller's token role before being sent.

Every method below takes a node_id, the internal id from client.nodes.resolve(node_name). See Getting started for how to get one. None of the examples that follow re-derive it, assume node = client.nodes.resolve("<barbara-id>") has already run.

Concept

Standalone Mode. A fallback Wi-Fi/Ethernet access point Barbara Panel can enable on a node, so an operator can reach it directly on-site even if its normal network connection is down.

Learn more

Read the current network state

network = client.nodes.network.get(node.id)

get(node_id) returns a NodeNetwork, a snapshot of every physical interface plus VPN/Proxy state, the data behind the Networking card as a whole. Read individual fields off it, or .raw for anything the SDK hasn't typed yet.

Adjust the hostname

hostname = client.nodes.network.get_hostname(node.id)
client.nodes.network.set_hostname(node.id, "floor-2-gateway")

set_hostname(node_id, hostname) mirrors Panel's Adjust the hostname action. There's no dedicated GET endpoint for the hostname alone, so get_hostname(node_id) reads it back from the node's own document instead.

Adjust a physical interface

Each interface kind has its own update method, matching Panel's Adjust a physical interface popup and its per-kind tabs.

Ethernet

client.nodes.network.update_ethernet_interface(
node.id, "eno1", dhcp=False, ip="10.0.0.5", gateway="10.0.0.1"
)

update_ethernet_interface(node_id, iface_name, *, dhcp=None, ip=None, gateway=None, auto_dns=None, dns=None, ip_aliases=None, dns_aliases=None, metric=None, rollback=True) only changes the parameters you pass; anything left as None keeps its current value.

Keep rollback on

rollback reverts the change automatically if the node becomes unreachable after applying it, the same safety net Panel's own wizard relies on. Leave it True unless you have a specific reason to disable it.

WiFi

client.nodes.network.update_wifi_interface(
node.id, "wlan0",
ssid="factory-floor", psk="s3cr3t", hidden=False,
dhcp=True, ip="", gateway="", dns="", auto_dns=True,
ip_aliases=[], dns_aliases=[], metric=100,
)

Unlike Ethernet or Mobile, update_wifi_interface has no partial-update form: the API requires the full configuration on every call, so pass every parameter even when you're only changing the ssid or psk. psk is base64-encoded internally.

Mobile

client.nodes.network.update_mobile_interface(node.id, "wwan0", apn="iot.provider.com")

update_mobile_interface(node_id, iface_name, *, apn=None, user=None, password=None, metric=None, rollback=True) behaves like the Ethernet call: only the parameters given are changed. password is base64-encoded internally.

Configure a VLAN

client.nodes.network.create_vlan_interface(
node.id, "eno1",
vlan_id=10, name="floor2vlan",
dhcp=False, ip="10.10.0.5", dns="10.10.0.1", gateway="10.10.0.1",
metric=100, auto_dns=False, ip_aliases=[], dns_aliases=[],
)

create_vlan_interface takes the physical Ethernet interface (parent_iface_name, for example "eno1") the VLAN sits on, a vlan_id between 1 and 4094, and a name for the new VLAN interface itself, letters and digits only, no spaces or special characters, matching Panel's own field hint. It also accepts optional 802.1Q tuning parameters (mtu, reorder_headers, loose_binding, gvrp, mvrp); leave them unset unless your network setup specifically requires them.

Two different "path segments"

name, not parent_iface_name, is what vlan_interface_exists and delete_vlan_interface expect afterwards. The two methods key off different things despite both looking like "the path segment" on the wire, so track the VLAN's own name, not the parent interface, if you need to check or remove it later.

exists = client.nodes.network.vlan_interface_exists(node.id, "floor2vlan")
client.nodes.network.delete_vlan_interface(node.id, "floor2vlan")

Enable or disable the Proxy

client.nodes.network.enable_proxy(node.id, url="http://proxy.internal:3128")
client.nodes.network.disable_proxy(node.id)

enable_proxy(node_id, *, url, user=None, password=None, rollback=True) mirrors Panel's Enable the proxy action; only HTTP and Socks5 proxies are supported. user/password are base64-encoded internally, and both are required by the underlying API, so an empty string is sent when you don't pass them. disable_proxy(node_id, *, rollback=True) mirrors Disable the proxy.

Reboot required

Both changes take effect only after the node reboots.

Manage the VPN

client.nodes.network.enable_vpn(node.id)
client.nodes.network.start_vpn(node.id)
client.nodes.network.stop_vpn(node.id)

enable_vpn(node_id) provisions the node's VPN identity, Panel's Activate VPN one-time step, and must be called once before start_vpn/stop_vpn. start_vpn and stop_vpn toggle the VPN ON/OFF switch in the Advanced section.

Configure Standalone Mode

client.nodes.network.enable_standalone_mode(
node.id, ip="192.168.100.1", netmask="255.255.255.0", metric=100,
)
client.nodes.network.disable_standalone_mode(node.id)

enable_standalone_mode mirrors Configure and enable Standalone Mode: an empty iface_name means Any Interface, and empty ssid/psk means no WiFi, Ethernet-only. Unlike the WiFi interface's psk, this one is sent as plain text.

client.nodes.network.renew_standalone_credentials(node.id)

renew_standalone_credentials(node_id) is the Regenerate button next to the Standalone Mode credentials in the Show Credentials popup.

Configure IPTables

iptables = client.nodes.network.get_iptables(node.id)

client.nodes.network.update_iptables(
node.id, iptables_conf="-A INPUT -p tcp --dport 22 -j ACCEPT",
)

get_iptables(node_id) has no dedicated GET endpoint either, and reads the rules back from the node's own document. update_iptables(node_id, *, iptables_conf, iptables_id=None, rollback=True) mirrors Panel's Configure IPTables; iptables_conf is the raw rules text, base64-encoded internally.

The "not set" sentinel

get_iptables returns "000000000000000000000000" for iptables_id when no custom rules have ever been set on the node, not None or an absent key. Pass that value straight through to update_iptables either way, whether you're setting rules for the first time or replacing existing ones.

Manage NTP servers

client.nodes.network.create_ntp_server(node.id, "pool.ntp.org")
client.nodes.network.update_ntp_server(node.id, "<ntp-id>", "time.google.com")
client.nodes.network.delete_ntp_server(node.id, "<ntp-id>")

create_ntp_server(node_id, server) base64-encodes server internally. The response doesn't include the created entry's id, read it back from client.nodes.get(node_id) if you need it before calling update_ntp_server/delete_ntp_server.

Summary

You configured a node's network from the same fields as the Networking card: physical interfaces, VLANs, hostname, VPN, Proxy, Standalone Mode, IPTables, and NTP, without clicking through Panel by hand.

Scripting network changes across a fleet, instead of visiting each node's Networking card individually, is what turns a one-off reconfiguration into a repeatable rollout: the same VLAN, proxy, or NTP change applies identically everywhere you run it.

Continue to Node & cluster secrets for the next node-level resource, or see client.nodes.network in the Reference for the full method list.