However, the application (using DBus code that works on other platforms) is unable to access the NetworkManager DBus, with the following error:
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] 2025-09-15 08:37:50.460 ERROR : Error: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at new module.exports (/home/node/webthings/gateway/node_modules/dbus/lib/bus.js:20:27)
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at DBus.getBus (/home/node/webthings/gateway/node_modules/dbus/lib/dbus.js:39:9)
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at NetworkManager.start (/home/node/webthings/gateway/build/platforms/utilities/network-manager.js:23:45)
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at NetworkManager.getDevices (/home/node/webthings/gateway/build/platforms/utilities/network-manager.js:40:14)
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at NetworkManager.getWifiDevices (/home/node/webthings/gateway/build/platforms/utilities/network-manager.js:113:36)
[Logs] [2025-09-15T15:37:50.461Z] [webthings-gateway] at LinuxBalenaOSPlatform.getNetworkAddressesAsync (/home/node/webthings/gateway/build/platforms/linux-balena-os.js:55:65)
Is there anything else I might need to set on the container to gain access to NetworkManager on the host via DBus?
I tried setting privileged: true on the service in docker-compose.yml and it didn’t make any difference, which suggested it might not be an issue with missing capabilities.
If I log into the Debian-based container and install the network-manager package using apt I note that the root user can access network settings using nmcli, but the node user (which is being used to run the application) can not.
So is the issue that the node user can not access the DBus system bus in order to communicate with NetworkManager on the host?
If so, is there a safe way to give a non-root user access to the system bus from inside the container, or should I be taking another approach? If I can’t create a DBus policy on the host OS, is my only option to run my application as root inside the container?
I’m disappointed nobody has been able to reply to this
I’ve been digging into this a bit more and from what I can tell the default DBus configuration for NetworkManager on balenaOS (/usr/share/dbus-1/system.d/org.freedesktop.NetworkManager.conf) appears to allow non-root users to modify most network settings, but only if PolicyKit allows them to.
I haven’t been able to find a PolicyKit configuration for NetworkManager in /usr/share/polkit-1/actions, so my assumption is that non-root users will be blocked.
Since I can’t modify the host OS this seems to indicate that I would have to run my application as root inside its container so that the UID matches when communicating with NetworkManager outside the container.
Is the only option really to run the application as root inside the container?
If I install network-manager inside the container then I can see that nmcli is able to communicate with the host’s NetworkManager when running as root, but not as the non-root node user.
# DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket nmcli c s
NAME UUID TYPE DEVICE
Wired connection 1 2d5077f7-6797-33b8-a594-5ae52221012e ethernet eno2
Sub-Etha d0e865ac-ef94-4c28-aa44-dd71cb7ba11d wifi wlo1
lo 454ed9d5-93b3-400d-bb9a-bb72fce80e81 loopback lo
supervisor0 b76fbc2e-4c25-4f05-9029-332643ab4ceb bridge supervisor0
# su node
node@3c865c3:~/webthings/gateway$ DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket nmcli c s
Error: Could not create NMClient object: The connection is closed.
I can also confirm that if I reconfigure my Docker image to run the application as root, the network settings web interface works.
So other than re-architecting my entire application into separate services, is my only option to run my application as root inside its container?
I can confirm that dbus access only seems to work with root access inside the container, but it doesn’t require that the container is privileged or that it has host networking which should provide some assurance. For instance, this works
root@66a4545a8f96:/# useradd me
root@66a4545a8f96:/# su - me
su: warning: cannot change directory to /home/me: No such file or directory
$ DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
dbus-send \
--system \
--print-reply \
--reply-timeout=2000 \
--type=method_call \
--dest=org.freedesktop.timedate1 \
/org/freedesktop/timedate1 \> > > > > > >
org.freedesktop.DBus.Properties.GetAll \
string:"org.freedesktop.timedate1"> >
Failed to open connection to "system" message bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
Having the same issue. Need to run an Electron app and Chromium requires non-root execution for sandboxing, but my app needs access to host Network Manager via D-Bus.
@gmerciel In the end I gave up and had the application running as root inside the Docker container, using a fork of our Docker image specifically for balenaOS.
In the long term I think we will try creating a custom host OS which exposes network settings to the container via an HTTP/WebSocket API.
You could probably achieve the same thing on balenaOS by having a separate (“side-car”) Docker image dedicated to communicating with the system DBus, and exposing network settings over HTTP/WebSocket/TCP socket, with your main application running as a non-root user in the main container.
Thanks @benfrancis, that’s exactly what I did, plus only binding that Web Service to 127.0.0.1, but I need to set network as host for both the dbus container and the container that access it. I guess I could get the internal ip and bind the service to that one, so it will only have access from the internal network, or if I don’t expose the port, I guess nothing of this is needed. What do you think?
Yes only binding the service to 127.0.01 is a good start, but there may still be security risks.
Depending on what else is running on that machine you may also want to use some form of authentication, validate the host header and possibly use CSRF protection.
The approach I was considering was having the host OS provide an authentication token to the container via an environment variable like the balena supervisor API does, but that’s a bit trickier on balenaOS when you can’t modify the host OS. I suppose you could provide the same token to both containers…