I have a couple routers in a development environment that I do some testing with from time to time. Back in November, I updated those routers to a rolling release built on November 29th, and at the time I did not realize that the API service did not come back up cleanly. Fast forward to today, when attempting to "fix" this issue, every time I would remove and recommit my API configuration, I would get an error about the port being consumed, despite the fact that netstat and ss reported no such conflict. I went ahead and built a new release based on the latest rolling, as of around 10:00 PM EST, and installed itWhen an HTTPS service is already running with a listen-address bound to a VRF interface, withadding or modifying the same impact.vrf configuration fails with:
The only way for me to restore API functionality was to change my previously "named" API key to a numerical key ID number[ service https ]
TCP port "443" is used by another service!
[[service https]] failed
Commit failed
This is also the case after a reboot of VyOS, where the https API previously configured with a VRF will fail to repopulate in the config and give errors about config parsing at boot.
No other service is using port 443. The same configuration works on older VyOS rolling builds (2025.11.29-1320-rolling).
For reference, the relevant configuration is as follows:Steps to Reproduce:
Configure HTTPS with a listen-address on a VRF interface:
set service https api keys id 1MYKEY key 'ApiKeyGoesHere'myapikey'
set service https api rest
set service https certificates ca-ccertificate 'CA'MYCERT
set service https certificates cca-certificate 'ssl-cert'MYCA
set service https enable-http-redirectlisten-address 192.168.140.21
set service https listen-address 'x.x.x.x'commit
Then add the VRF:
set service https vrf 'OOB-Management'
Changing the top line of that configuration to:ent
set service https api keys id NAMED key 'ApiKeyGoesHere'commit
The commit at step 2 fails. If listen-address is removed first, adding vrf alone succeeds.
Expected Behavior: The commit should succeed. The VRF and listen-address are compatible — nginx will bind inside the VRF namespace.
Results in the following errorActual Behavior: Commit fails with the port conflict error.
Root Cause Analysis:
The bug is in src/conf_mode/service_https.py in the verify() function (around line 93):
for address in listen_address:
[ service https ] if not check_port_availability(address, port, 'tcp') and \
TCP port "443" is used by another service! not is_listen_port_bind_service(port, 'nginx'):
[[service https]] failed raise ConfigError(f'TCP port "{port}" is used by another service!')
Two VRF-related issues combine:
check_port_availability() (python/vyos/utils/network.py) performs a socket.bind() test in the default VRF/namespace, regardless of the target VRF. When listen-address points to an IP on a VRF interface (e.g., 192.168.140.21 on OOB-Management), the address doesn't exist in the default namespace, so the bind fails with OSError. The function returns False (port unavailable), which is incorrect — the port isn't in use, the address simply isn't reachable from the default namespace.
is_listen_port_bind_service() uses psutil.net_connections() to check if nginx holds the port. If nginx is already running inside the VRF namespace, psutil may not see its sockets from the default namespace context. The function returns False (nginx not found), so the safety fallback fails too.
The combination of both returning False triggers the ConfigError incorrectly.
Suggested Fix:
Skip the port availability check when a VRF is configured, since the check runs in the wrong namespace and cannot produce a valid result:
# Skip port check when VRF is configured — the verify process runs
Commit failed
From a usability perspective# in the default namespace and cannot bind/see ports in other VRFs.
if 'vrf' not in https:
for address in listen_address:
if not check_port_availability(address, port, 'tcp') and \
not is_listen_port_bind_service(port, if this is the expected/desired behaviour'nginx'):
raise ConfigError(f'TCP port "{port}" is used by another service!')
A more comprehensive fix would be to make check_port_availability() VRF-aware (running the socket bind inside the target VRF via ip vrf exec), then certainly erroring when a user attempts to place a non-numerical ID in for a key name is preferable to throwing an error about an HTTPS port consumed that isn't actually consumed?but skipping the check for VRF-bound services is the simpler and safer approach.
Workaround:
Let me know what other info you need from meConfigure the VRF without a listen-address first, then add the listen-address in a subsequent commit. Or set both listen-address and vrf simultaneously in the same commit (order-dependent workaround) after already committing the HTTPS API.