#!/bin/sh # Run on the OpenWrt device (20.0.0.26) to install and configure NUT + snmpd # Also configures: bridge LAN ports, static IP, WiFi AP, DHCP on WiFi only # Usage: sh /tmp/ups-install.sh set -e echo "==> Updating package lists..." opkg update echo "==> Installing NUT..." opkg install nut nut-server nut-upsmon opkg install nut-driver-usbhid-ups || opkg install nut-usbhid-ups || true opkg install kmod-usb-hid 2>/dev/null || true echo "==> Installing LuCI NUT config page and web CGI status..." opkg install luci-app-nut echo "==> Installing snmpd (full NET-SNMP with extend support)..." /etc/init.d/mini_snmpd stop 2>/dev/null || true /etc/init.d/mini_snmpd disable 2>/dev/null || true opkg remove mini_snmpd 2>/dev/null || true opkg install snmpd luci-app-snmpd echo "==> Configuring NUT via UCI..." uci set nut_server.tripplite=driver uci set nut_server.tripplite.driver='usbhid-ups' uci set nut_server.tripplite.port='auto' uci set nut_server.tripplite.desc='Local UPS' uci set nut_server.tripplite.vendorid='09ae' # No productid filter — matches any Tripp Lite USB UPS (SMART1500RMXL2UA, SU1500RTXL2Ua, etc.) uci set nut_server.tripplite.pollinterval='5' uci set nut_server.listen1=listen_address uci set nut_server.listen1.address='127.0.0.1' uci set nut_server.upsmon_user=user uci set nut_server.upsmon_user.username='upsmon' uci set nut_server.upsmon_user.password='nutlocal' uci set nut_server.upsmon_user.upsmon='master' # Read-only passwordless monitor account for CGI stats page uci set nut_server.monitor_ro=user uci set nut_server.monitor_ro.username='monitor' uci set nut_server.monitor_ro.upsmon='slave' uci commit nut_server uci set nut_monitor.upsmon=upsmon uci set nut_monitor.upsmon.minsupplies='1' uci set nut_monitor.upsmon.shutdowncmd='/sbin/halt' uci set nut_monitor.upsmon.pollfreq='5' uci set nut_monitor.upsmon.pollfreqalert='5' uci set nut_monitor.upsmon.hostsync='15' uci set nut_monitor.upsmon.deadtime='15' uci set nut_monitor.upsmon.finaldelay='5' uci set nut_monitor.tripplite=master uci set nut_monitor.tripplite.upsname='tripplite' uci set nut_monitor.tripplite.hostname='localhost' uci set nut_monitor.tripplite.powervalue='1' uci set nut_monitor.tripplite.username='upsmon' uci set nut_monitor.tripplite.password='nutlocal' uci commit nut_monitor uci set nut_cgi.tripplite=host uci set nut_cgi.tripplite.upsname='tripplite' uci set nut_cgi.tripplite.hostname='localhost' uci set nut_cgi.tripplite.displayname='Local UPS' uci commit nut_cgi echo "==> Configuring snmpd community and UPS extend entries via UCI..." uci set snmpd.public.community='fsr' uci set snmpd.public6.community='fsr' for name in battery_charge battery_runtime ups_load input_voltage output_voltage ups_status battery_temp battery_voltage; do # Map UCI name back to NUT variable (underscores -> dots, battery_temp -> battery.temperature) nut_var=$(echo "$name" | tr '_' '.') [ "$name" = "battery_temp" ] && nut_var="battery.temperature" uci set snmpd.${name}=extend uci set snmpd.${name}.name="$name" uci set snmpd.${name}.prog='/usr/bin/upsc' uci set snmpd.${name}.args="tripplite@localhost $nut_var" done uci commit snmpd echo "==> Fixing /var/etc/nut directory permissions (persists via rc.local)..." mkdir -p /var/etc/nut chgrp nut /var/etc/nut chmod 750 /var/etc/nut grep -q 'var/etc/nut' /etc/rc.local 2>/dev/null || \ sed -i 's|^exit 0|mkdir -p /var/etc/nut\nchgrp nut /var/etc/nut\nchmod 750 /var/etc/nut\n\nexit 0|' /etc/rc.local echo "==> Creating /etc/nut symlinks to UCI-generated configs..." for f in ups.conf upsd.conf upsd.users nut.conf; do rm -f /etc/nut/$f ln -sf /var/etc/nut/$f /etc/nut/$f done echo "==> Enabling services..." /etc/init.d/nut-server enable /etc/init.d/nut-monitor enable /etc/init.d/nut-cgi enable /etc/init.d/snmpd enable echo "==> Writing USB hotplug script for automatic NUT restart on UPS connect/disconnect..." cat > /etc/hotplug.d/usb/99-nut-ups << 'HOTPLUG' #!/bin/sh # Auto-restart NUT when Tripp Lite UPS is plugged/unplugged UPS_VENDOR="09ae" case "$ACTION" in add) if echo "$PRODUCT" | grep -qi "^${UPS_VENDOR}"; then # Fix USB device permissions so NUT driver (nut user) can access it [ -n "$DEVNAME" ] && chmod 0660 "/dev/$DEVNAME" && chown root:nut "/dev/$DEVNAME" logger -t NUT "Tripp Lite UPS connected (PRODUCT=$PRODUCT) - restarting NUT" sleep 3 /etc/init.d/nut-server restart fi ;; remove) if echo "$PRODUCT" | grep -qi "^${UPS_VENDOR}"; then logger -t NUT "Tripp Lite UPS disconnected - restarting NUT" /etc/init.d/nut-server restart fi ;; esac HOTPLUG chmod +x /etc/hotplug.d/usb/99-nut-ups echo "==> Removing HTTP basic auth from NUT CGI path (upsstats.cgi accessible without login)..." # nut-web-cgi installs /etc/httpd.conf with auth on /cgi-bin/nut — clear it so upsstats.cgi # is viewable without a username/password (upsset.cgi still requires upsd credentials) > /etc/httpd.conf echo "==> Starting services..." /etc/init.d/nut-server restart sleep 10 /etc/init.d/nut-monitor restart sleep 2 /etc/init.d/nut-cgi restart /etc/init.d/snmpd restart echo "==> Configuring network (bridge eth0.1+eth1, static 20.0.0.26/24, WiFi AP 192.168.88.1/24)..." uci batch << 'EOF' delete network.wan delete network.wan6 set network.loopback=interface set network.loopback.device='lo' set network.loopback.proto='static' set network.loopback.ipaddr='127.0.0.1' set network.loopback.netmask='255.0.0.0' set network.globals=globals set network.globals.ula_prefix='fd6b:e811:df87::/48' set network.br_lan_dev=device set network.br_lan_dev.name='br-lan' set network.br_lan_dev.type='bridge' del_list network.br_lan_dev.ports='eth0.1' del_list network.br_lan_dev.ports='eth1' add_list network.br_lan_dev.ports='eth0.1' add_list network.br_lan_dev.ports='eth1' set network.lan=interface set network.lan.device='br-lan' set network.lan.proto='static' set network.lan.ipaddr='20.0.0.26' set network.lan.netmask='255.255.255.0' set network.lan.gateway='20.0.0.1' set network.lan.dns='20.0.0.1' set network.wifi_ap=interface set network.wifi_ap.proto='static' set network.wifi_ap.ipaddr='192.168.88.1' set network.wifi_ap.netmask='255.255.255.0' EOF uci commit network echo "==> Configuring switch VLAN (all wired ports on VLAN 1)..." uci set network.switch=switch uci set network.switch.name='switch0' uci set network.switch.reset='1' uci set network.switch.enable_vlan='1' uci set network.switch_vlan1=switch_vlan uci set network.switch_vlan1.device='switch0' uci set network.switch_vlan1.vlan='1' uci set network.switch_vlan1.ports='1 2 3 4 0t' uci commit network echo "==> Configuring wireless (SSID: fsr, WPA2, AP on wifi_ap interface)..." uci set wireless.radio0.disabled='0' uci set wireless.default_radio0=wifi-iface uci set wireless.default_radio0.device='radio0' uci set wireless.default_radio0.network='wifi_ap' uci set wireless.default_radio0.mode='ap' uci set wireless.default_radio0.ssid='First Step Internet' uci set wireless.default_radio0.encryption='psk2' uci set wireless.default_radio0.key='12345678' uci commit wireless echo "==> Configuring DHCP (disabled on lan, enabled on wifi_ap 192.168.88.100-199)..." uci set dhcp.lan.ignore='1' uci set dhcp.wifi_ap=dhcp uci set dhcp.wifi_ap.interface='wifi_ap' uci set dhcp.wifi_ap.start='100' uci set dhcp.wifi_ap.limit='100' uci set dhcp.wifi_ap.leasetime='12h' uci commit dhcp echo "==> Writing WiFi control CGI page..." mkdir -p /www/cgi-bin cat > /www/cgi-bin/wifi.cgi << 'CGISCRIPT' #!/bin/sh urldecode() { echo -e "$(echo "$1" | sed "s/+/ /g; s/%\([0-9A-Fa-f][0-9A-Fa-f]\)/\\\\x\1/g")" } if [ "$REQUEST_METHOD" = "POST" ]; then read -n "$CONTENT_LENGTH" POST_DATA 2>/dev/null action=$(echo "$POST_DATA" | tr "&" "\n" | grep "^action=" | cut -d= -f2-) new_ssid=$(echo "$POST_DATA" | tr "&" "\n" | grep "^ssid=" | cut -d= -f2-) new_key=$(echo "$POST_DATA" | tr "&" "\n" | grep "^key=" | cut -d= -f2-) new_ssid=$(urldecode "$new_ssid") new_key=$(urldecode "$new_key") case "$action" in toggle) disabled=$(uci get wireless.radio0.disabled 2>/dev/null || echo 0) if [ "$disabled" = "1" ]; then uci set wireless.radio0.disabled="0" uci commit wireless wifi up & else uci set wireless.radio0.disabled="1" uci commit wireless wifi down & fi ;; update) [ -n "$new_ssid" ] && uci set wireless.default_radio0.ssid="$new_ssid" [ -n "$new_key" ] && [ ${#new_key} -ge 8 ] && uci set wireless.default_radio0.key="$new_key" uci commit wireless wifi reload & ;; esac fi disabled=$(uci get wireless.radio0.disabled 2>/dev/null || echo 0) ssid=$(uci get wireless.default_radio0.ssid 2>/dev/null) [ "$disabled" = "1" ] && wstatus="Disabled" && wcolor="#dc2626" && toggle_lbl="Enable WiFi" \ || wstatus="Enabled" && wcolor="#16a34a" && toggle_lbl="Disable WiFi" echo "Content-Type: text/html" echo "" cat << HTML
Changes apply within ~5 seconds