Changing NetworkManager configuration in the field

I’m trying to figure out a way to change the NetworkManager configuration for a cellular connection while the device is in the field. In the event that the premade configuration’s APN is wrong, I want to be able to change the APN, test that the new APN works, and have that change applied permanently.

The obvious way is to change the config on the SD card with the ResinOS image and re-flash the board (Beaglebone Black), but I’m trying to steer away from that as the person that would be doing this isn’t technical (and it’s a large time overhead if we need to try a bunch of different APNs).

I’ve thought of include using the Beaglebone’s debug serial port, and writing a Python script to copy over a config file. The problem is that the root filesystem is read-only, so any config I copy over could only be placed in /etc/NetworkManager/system-connections, which would be overwritten on reboot. Further, I’m reading that the serial port is disabled (or at least, no TTY session is attached to it) on prod images, so this wouldn’t work anyways.

The method mentioned in the docs for runtime configuration changes involves using DBUS, which is a reasonable solution except there’s no good way of allowing a user to input a new APN to a device that isn’t online. The serial port doesn’t work, so they can’t input data through that, and since the device isn’t network connected I can’t use the dashboard to pass in data through an environment variable.

The only way I’ve thought of that sounds like it could work is reading from a text file placed on an SD card, and using a script that runs in my container’s to configure the connection using the DBUS API.

I’m starting to feel like my situation is very niche, but if anyone has experience dealing with this kind of thing or has any suggestions as to possible solutions, I’m all ears.

Thanks in advance!

1 Like

Hi @alexland,

your are right: the problem is that if the device is not connected to a network, you need to use some wired-signal to use the DBUS and modify the network configuration.

The project resin-wifi-manager uses the following approach:

  • If there is not WiFi connection, change to AP mode. In this mode, when a client is connected to this AP, it can browse to a captive portal where it can specify the WiFi SSID and password to the device (the Beaglebone Black in your case).
  • Once the device is connected, the AP mode is disabled (until WiFi connection is lost again).

The backend of this project uses DBUS as you might guess. I hope that this project, or at least this idea, help you to solve your problem.

The approach of using a Captive Portal UI onto the DBUS backend certainly does sound like it has potential for your use case, and should be able to be developed using the linked project as a starting point.
I for one would be interested in hearing how you get on, so would you mind updating us here when you’ve tried some things?

@jcozar I have looked in to resin-wifi-connect, and it’s a really solid solution for WiFi, but I’m a bit apprehensive about trying to fork it and modify it for cellular mostly because of my unfamiliarity with Rust (the project I’m working on right now is using Python).

I’ve been playing with the NetworkManager DBUS API a bit, and noticed that you can’t actually modify the cellular connection directly. You can add a new cellular connection, but to modify an existing one it looks like you need to use the ModemManager DBUS API. I’m going to investigate that further, and try to get connection modification working in a Python script before diving in to using a captive portal/WiFi hotspot to allow user configuration.

@alexland hi i’m in the same situation with trying to get cellular connectivity to a beaglebone have you come any further on that python script?

@JoachimLindborg I started playing with DBUS but didn’t get very far. I realized that my current workaround (putting a text file with APNs on a micro SD card, and having my application read the file/apply the connection settings) is very similar to just modifying the text config file on the ResinOS image itself, and reflashing the image. The additional downside is that I’m in a bit of a crunch for time and wouldn’t be able to troubleshoot or test my solution to the level that I’d want to. Considering that added riskiness of rolling my own script versus just reflashing every time, I’m just going to focus on good documentation and perhaps a Python script to help change the config file on the ResinOS image, and get someone to reflash the image to try other APNs.

Sorry to have such an anticlimactic solution, but I hope you figure something good out for yourself!

I tried to change the files on the SD image in the /system-connections/ folder, and then reflashing the beaglebone but the files are not copied to the local flash in the beaglebone.

If I understood @alexland well

I’ve been playing with the NetworkManager DBUS API a bit, and noticed that you can’t actually modify the cellular connection directly. You can add a new cellular connection, but to modify an existing one…

you were able to add new cellular connections but cannot edit existing entries.

Why don’t just delete an existing connection and create a new one with the new configuration?

@jcozar that would definitely work, and I’m kicking myself a bit for getting caught up in details and missing such an obvious solution.

At the time my thought process was that initially NetworkManager will make a connection for the config in system-connections, and so I’d need to find and delete that one before making a new one (I was having trouble figuring out how to identify the connection reliably, so this was a problem). Thinking about it now after reading your comment, I could have just removed the config from system-connections and delete/create them myself on each container spawn.

I totally agree with you @alexland. That seems a good solution!