Best way to automate OpenWrt configuration

I'm looking to set up 100's of OpenWrt routers to go into kits and need to be able to configure them uniquely. I found a thread about using SSH to modify conf files but it isn't clear if that is the best way to automate configuration or if it was just what that person was trying to do.

Ultimately these will all be configured as WiFi extenders and the host network will be different for each. Everything else will be identical between them.

Any thoughts?

You are looking for /etc/uci-defaults. I am configuring several routers this way: they are idiot proof now. When a router is refreshed it fully programs itself. If any changes are made, then a factory reset restores them to the original working config. I have also disabled the ability to keep the existing configuration, so every re-flash is a freshly installed router with everything working as I configured.

4 Likes

Also, you can add any file of your choice to the images with the image builder.

Yes. However, you need to provide more detailed info. I.e. how the individual config to be applied. Does the end user need to do it, is it pre-determined before delivery to installation site, do you want to do it manually for every device (then you can use the uci-defaults mentioned already) .... Anyway, as this sounds like a commercial system.... for commercial support send me a PM.

Thank you all for the replies. @reinerotto, I'll send you a PM.

Would you share your idea, how you maintain and distribute device specific settings (ie. hostname, ip-settings to maintain connectivity etc.) for scripts in uci-defaults?

I have a goal/idea to produce images per target device with a config (uci-defaults + a file containing device specific settings) inserted to the images. The scripts will find device settings by a mac-address from the file.

The file could be a combination of already existing files (/etc/ethers, /etc/hosts) just containing information for all managed devices. Some internal voice tells to create the config management (the file) totally independent from the system settings files.

I have a set of global files and device specific files and during a build the proper files are copied over into an image. I generate one firmware per a device, not one firmware for all devices.

1 Like

Place the file(s) you want to set defaults in subdir:

package/base-files/files/etc/uci-defaults/

basic syntax is (example):

#!/bin/sh
uci batch <<EOF
#custom settings start
add dhcp host
set dhcp.@host[-1].name='ROOTSERVER'
set dhcp.@host[-1].dns='1'
set dhcp.@host[-1].mac='xx:xx:xx:xx:xx:xx'
set dhcp.@host[-1].ip='192.168.1.100'
set dhcp.@host[-1].leasetime='24h'
#custom settings end
commit
EOF

UCI syntax you can adopt from:

https://openwrt.org/docs/guide-user/base-system/uci

You can place within this files all the other stuff you need also (hostname, ip-settings to maintain connectivity etc.).

Personally I'm not going to share my scripts. Simply I'm to lazy to strip them (names, macs, ips, prefixes). But maybe some other will do it or search Google/Github. I'm sure there are basic scripts outside. But your individual stuff you have to craft by yourself anyway. It's not that hard. Just time consuming. :wink:

1 Like

If using the UCI script approach, is this something that can be done with off-the-shelf devices? Or is this something that should be done when building a custom firmware for a device? Also, is it as simple as using scp to put them in place? At the very least it seems they would need to be marked as executable.

Thanks!

It all depends on the parameter you have.

If I would have to modify 100 identical units I would compile my own build (or you could use automated image builder; I never tried it) and place the scripts (package/base-files/files/etc/uci-defaults/). Advantage: If you have to reset a unit everything is available at once again.

If they are unique/different units I would push the script via ssh to the units and execute it over ssh. For this choose /tmp as target.

It all depends on the parameter you have.

I assume you mean it depends on which parameter I need to change?

Regarding the devices in my situation, they will be set up as wifi extenders. So the WAN wifi (or whatever it is called?) SSID and password would be different for each one. Otherwise they would be configured the same way.

If they are unique/different units I would push the script via ssh to the units and execute it over ssh. For > this choose /tmp as target.

Ok, I think I understand what you mean. If I were to build my own image / firmware, then I would place my unique configuration in the UCI defaults directory? If I will use an unmodified image then I just need to run the UCI commands once, but if someone resets the devices then the custom configuration would be lost.

Do I have that right?

No, I should have written the parameters of your project (modifying 100 routers). That what I meant in this specific case. But overall the more details ppl get the better the help can be.

Exactly.

Great. Thank you! The UCI defaults documentation that @fantom-x linked above seems to lay out how to do this well (I obviously didn't follow / read that previously - sorry!). This definitely gives me some direction.

Some more ideas for you:

You can also use uci-defaults to sniff out the MAC of the device, serial number, or whatever the OEM stored in the readable flash (art, sysinfo, syscfg partition) and use that as basis of configuring something.

I did that to be WNDR3700/3700v2/3800 routers a few years ago (well 8 years ago).
I set wifi options based on of the MAC address, as the MAC was part of the wifi definition at that time.

See the last script in this message from year 2012.
https://forum.archive.openwrt.org/viewtopic.php?id=28392&p=14#p185418

The last part of the script uses "dd" to read the MAC from art partition:

# Almost the same settings can be used for all my three routers
# Use hardware id to set wireless MAC address and Ipv6 segment
local name
[ -f /tmp/sysinfo/model ] && name=$(cat /tmp/sysinfo/model)
radio0=`dd if=/dev/mtdblock5 bs=1 skip=0 count=6 2>/dev/null \
  | hexdump -v -e '5/1 "%02x:" 1/1 "%02x" '`
radio1=`dd if=/dev/mtdblock5 bs=1 skip=12 count=6 2>/dev/null \
  | hexdump -v -e '5/1 "%02x:" 1/1 "%02x" '`
echo -e "------\nSet wireless MACs for $name"
echo -e "2.4 Ghz radio: $radio0\n5   GHz radio: $radio1"
uci set wireless.radio0.macaddr=$radio0
uci set wireless.radio1.macaddr=$radio1
uci commit wireless

The script also shows the approach that I still use: I include my own personal config, only a few files, in encrypted tar file to the image I compile and place available as a community build. So I can apply my own personal settings after a reset simply by running that script and giving the password, although the basic image only contains the public defaults as defaults after reset.

Similarly, you could do a script that selects based on MAC the correct config items from a database file included in the image.

If randomness would be allowed, you could

  • ship tailored default common config files in the common firmware image.
  • use uci-defaults (run at the first boot) to
    • sniff the MAC or serial number with "dd" or something
    • calculate the unique "host network name" from that. E.g. "wifi" + first 8 chars MD5 hash of serial (wifi13f72a23) or directly "wifi" + last 8 chars of MAC (wifi87c65d54)
    • set that uci option to the wifi config file.

If you need pre-determined unique network names & passwords (for each individual device), then you need to do a bit more complex lookup from shipped/fetched database file, but you could still use MAC or serial to uniquely identify the devices in the database file.

What is your plan to upgrade the firmware? Would you send an image and someone would manually deploy it? I have been toying with an idea of using syncthing to distribute the images to the routers, but never actually got to implementing it. There could also be a script to automatically flash the image once a new one is discovered and checksum is verified.

What is your plan to upgrade the firmware?

We really haven't thought that far ahead yet. Right now we are trying to solve our issues without using a repeater so this was more of a fact finding mission. I chatted with @reinerotto a bit and he has an interesting option we may use if we plan to move forward with an OpenWrt solution. I think it would involve deploying an image but we would want to do that in-house and not have our customers do that. Since our solution involves leasing kits, we would probably swap out hardware rather than having them perform an upgrade. But like I said we aren't really ready to tackle that yet.