I have a custom wireguard script that is checking several different remote wireguard "servers" and will then automatically enable a single wireguard interface on my router based on which one has the lowest server load/ttl/speed/etc... It is protonvpn and routes all my traffic through the enabled one... it mainly to keep my ISP from snooping on me. For now, I am writing UCI commands in the scripts to automate everything but if I happen to enable a wireguard interface manually in Luci, instead of changing the option auto '0' to option auto '1' it will just delete the option completely and just falls back to the default value of 1. This is good and all but I used that value to tell my script which interface was active. I did this workaround
for key in "${!server_loads[@]}"; do
# the key names in server_loads array match the wg interface names
auto_config="network.${key}.auto"
if ! auto_config_value=$(uci -S get $auto_config); then
if [[ $dryrun = 1 ]]; then
log_msg "protonvpn: network uci 'auto' config not set on wg interface, but dry-run option was given so ignoring..."
else
log_msg "protonvpn: network uci 'auto' config not set on wg interface, setting..."
uci add_list ${auto_config}=1
uci commit
auto_config_value=$(uci get $auto_config)
fi
elif [[ $auto_config_value -eq 1 ]]; then
export active_wg="$key"
export active_load=${server_loads[$key]}
break
fi
done
which works as best I can tell but it is rather clunky and dirty and I would rather just change the behavior of Luci. I have looked around but can't find what is handling that. Any help would be appreciated. Thanks.
I am not a dev and do not use a vpn on openwrt but take a look in the following directories on your OpenWrt device. You may find what you are looking for or else see some clues to help you.
In general, look in /www/ and various sub-directories like /www/luci-static/resources/
Also /www/cgi-bin/ and /usr/libexec/
Some/all? menu item configurations are under /usr/share/luci/
EDIT: ucode files may be under /usr/share/rpcd/ucode/.
Many of the files are html, json, ucode, or javascript so you can edit them.
Keep in mind that modifying files provided by the system or package installation will get overwritten with upgrades etc and future versions may have differing syntax so you may need to patch/edit files in a different way then.
I'm not real clear on what you're trying to accomplish, but if you are using the standard LuCI buttons, uci commits happen in the uci_apply function here:
In addition to the fine response from @efahl, I'm thinking there might be application specific handling in the luci module that you are using. If it is luci module luci-proto-wireguard then the github page for it might help as well. https://github.com/openwrt/luci/tree/master/protocols/luci-proto-wireguard . Change the branch from master to 24.10.x or which ever matches your installation as these do sometimes get modified between releases.
Another thought is rather than modifying the behaviour of luci to fit your script methodology, look into querying the active wireguard interface. The scripts in the github page might reveal If wireguard is query-able via ubus or another method.
You can see what is available from ubus with ubus list. Then you can show the calls that are available with verbose mode. A random example for session is: ubus -v list session which outputs:
Think I figured it out with a little help searching from Grok.
I edited the 'interfaces.js' file in /www/luci-statci/resources/view/network
(starting at line: 250)
o = s.taboption('general', form.Flag, 'auto', _('Bring up on boot'));
o.modalonly = true;
o.default = o.enabled;
// I added the line below
o.rmempty = false;
Have not had time to test it yet. Also saw a few other new replies above. Thanks, everyone I will check those out this afternoon (at work currently) and, test my solution. If it works I will mark as answered. If someone thinks my solution is not sufficient please let me know.
So, it is most def "application" specific. Not sure if you read my OP but it is morw "script specific". Here is a a good part of the script minus several functions and command line parameter handling
watchdog_function
if [[ "$nofetch" == 1 ]]; then
if [[ -f $load_array_file ]];then
if [[ -f $server_loads_file ]];then
hash_test_value="$(md5sum $server_loads_file | cut -d' ' -f1)"
source $load_array_file
if [[ $load_file_hash != $hash_test_value ]];then
log_msg "protonvpn:calculated array does not match most recent ${server_loads_file}, recalculating"
calc_loads
else
log_msg "server load array file already exists, no need to calculate a new one"
fi
else
log_msg "protonvpn:calculated array exists but no ${server_loads_file}, exists,recalculating to be safe"
calc_loads
fi
else
if [[ -f $server_loads_file ]]; then
calc_loads
else
log_msg -e "protonvpn: cannot use existing data, no server_loads_file ${server_loads_file} to use"
error_quit
fi
fi
log_msg "Using old server load info because the -n or --no-fetch option was given in command"
else
fetch_loads
calc_loads
fi
source $load_array_file
for key in "${!server_loads[@]}"; do
if [[ -z "$min_load" || "${server_loads[$key]}" < "$min_load" ]]; then
min_load="${server_loads[$key]}"
min_load_server="$key"
fi
done
for key in "${!server_loads[@]}"; do
loads_display="${loads_display} ${key}=${server_loads[$key]}%"
done
log_msg "protonvpn INFO: server with lowest load is $min_load_server with a load of ${min_load}% . Other loads are ${loads_display}"
# Hint: the array key labels are also the names of each wireguard interface name
for key in "${!server_loads[@]}"; do
auto_config="network.${key}.auto"
if ! auto_config_value=$(uci -S get $auto_config); then
if [[ $dryrun = 1 ]]; then
log_msg "protonvpn: network uci 'auto' config not set on wg interface, but dry-run option was given so ignoring..."
else
log_msg "protonvpn: network uci 'auto' config not set on wg interface, setting..."
uci add_list ${auto_config}=1
uci commit
auto_config_value=$(uci get $auto_config)
fi
elif [[ $auto_config_value -eq 1 ]]; then
export active_wg="$key"
export active_load=${server_loads[$key]}
break
fi
done
if [[ $active_wg == $min_load_server ]] || [[ -n $active_load && $active_load -lt 50 ]]; then
log_msg "protonvpn: current active wireguard server=${active_wg} Load=${active_load}%"
log_msg "protonvpn INFO: server with lowest load already running, or load is less than 50 percent exiting."
update_leds $active_load
exit 0
elif [[ -z $active_load ]]; then
log_msg -e "protonvpn: '${active_load}' variable is not set, someting is wrong, exiting"
error_quit
else
if [[ "$dryrun" = 1 ]]; then
echo "active wg interface is: $active_wg and load is $active_load, would be changed to $min_load_server" >&2
echo "DEBUG: not actually changing interfaces... exiting" >&2
exit 0
fi
log_msg "active wg interface is: $active_wg and load is $active_load, changing to $min_load_server"
uci set network.${active_wg}.auto=0
uci set network.${min_load_server}.auto=1
uci commit
update_leds $active_load
log_msg "protonvpn: restarting network..."
/etc/init.d/network restart
log_msg "protonvpn: wireguard protonvpn server now set to $min_load_server"
fi
Hopefully you can get a rough Idea from that.
Anyways, the wireguard specific settings do not include the "catch all" options present on all interfaces. As you can see in my script there was already an effective workaround but I wanted something cleaner.
the only side effect is it will start explicitly declaring the auto '1' for every interface in the uci config file, not just the wiregurard ones but I see no way this could cause problems