This tool enables the modification of RSTP/STP per-port cost on UniFi switches and provides a method to keep the configuration quasi-persistent.
Ubiquiti does not provide an official method to adjust RSTP/STP per-port costs on UniFi switches.
While it is possible to connect via SSH and use well-known commands to modify these values, such changes are not persistent: they are lost after a reboot or reprovisioning.
To date, no native mechanism ensures persistence of these settings.
- Install dependencies
pip3 install requests
- Clone or copy the script to your server (can be the UniFi Controller host).
- Update script configuration with your UniFi Controller URL, username, password, and site:
self.controller_url = "https://localhost:8443" self.username = "admin" self.password = "password" self.site = "default"
- Ensure SSH key authentication works to the target switch.
Test with: - Run the script manually:
rstphack <switch_mac> <port_idx> <required_stp_cost> <user@ip_address>
Example:
rstphack -q 00:11:22:33:44:55 3 200000 [email protected]
- Automate with cron (recommended)
Open the crontab for editing:
crontab -e
Add a line to run the script every 5 minutes (adjust as needed):
*/5 * * * * /usr/local/bin/rstphack -q 00:11:22:33:44:55 3 200000 [email protected]
This ensures the preferred STP cost is enforced automatically after reboots or reprovisioning. Also, multiple ports can have their cost altered using multiple crontab lines, provided they are managed by the same controller and are on the same site.
- Alternative: Automate with systemd
Instead of using cron, you can use systemd timers for better integration with modern Linux systems.
Create a service file /etc/systemd/system/rstphack.service
:
[Unit]
Description=RSTPHack UniFi STP Port Cost Enforcer
[Service]
Type=oneshot
ExecStart=/usr/local/bin/rstphack -q 00:11:22:33:44:55 3 200000 [email protected]
Create a timer file /etc/systemd/system/rstphack.timer
:
[Unit]
Description=Run RSTPHack every 5 minutes
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Unit=rstphack.service
[Install]
WantedBy=timers.target
This will run rstphack.service
automatically every 5 minutes (as defined in the timer). Multiple ports can have their cost altered using multiple ÈXecStart`lines, provided they are managed by the same controller and are on the same site.
Two unit files are provided as examples:
Place both files in /etc/systemd/system/
:
Enable and start the timer:
sudo systemctl daemon-reload
sudo systemctl enable --now rstphack.timer
To check status:
systemctl status rstphack.timer
And to see logs of the service runs:
journalctl -u rstphack.service
Note: Not all UniFi switches support programmatic per-port cost changes. See Prerequisites.
This workaround is not straightforward to implement but provides a practical solution to make per-port cost settings “quasi-persistent.”
The method relies on a Python script that:
- Queries the UniFi Controller for per-port configuration.
- Compares the actual STP cost with the desired one.
- If different, connects directly to the switch (not the controller) via SSH to apply the change.
The script must run on a Unix-based system (including the UniFi Controller itself). Any scheduling mechanism (e.g., cron
) can be used to execute the script periodically.
Important Considerations:
- Scheduling requires care: the verification happens at the controller level, but the configuration change occurs at the switch level.
- There is no reliable programmatic method to confirm changes directly on the switch. It can take several minutes for updates to appear in the controller.
- Typically, per-port costs are adjusted to influence path preference in spanning-tree calculations. If a switch reboots, the initial path may not be the preferred one until the script executes again.
The scheduling interval must balance:
- The propagation delay of configuration changes from switch to controller.
- The maximum tolerable time that traffic flows over the non-preferred path.
The script interacts with the unpublished UniFi Controller API and uses SSH to apply changes on the switch:
- Authenticate with the Controller.
- Retrieve port configurations using the switch MAC address.
- Extract STP cost (
stp_pathcost
) and port media type. - Compare current and desired costs.
- If changes are needed, generate the correct port identifier (based on media type).
- Execute the required commands on the switch via SSH:
cli -c "configure" -c "interface {if_id}" -c "spanning-tree cost {required_cost}"
Note: There is no programatically way to ensure the command executed correctly on the switch, except for waiting for the new state to propagate to the UniFi Controller.
- Target switch must support the
cli
command with the-c
option - Python 3.6 or later
- Python
requests
package - Access to the UniFi Controller (username and password)
- SSH access to UniFi switches enabled, using private key authentication
- Optional: Python virtual environment
- Choose an installation directory (e.g.,
/usr/local/bin
on a controller). - (Optional) Create and activate a virtual environment:
python3 -m venv .venv . .venv/bin/activate
- Install dependencies:
pip3 install requests
- Clone or download the script.
If installing on a UniFi Controller, pip
and venv
may need to be installed first (python3
is usually included).
Update the hardcoded Controller settings in rstphack
:
# Change these values to match your environment
self.controller_url = "https://localhost:8443"
self.username = "admin"
self.password = "password"
self.site = "default"
The script includes two shebangs at the top:
- One for running inside a virtual environment without activation.
- One for using the system-wide Python installation.
Select or adapt as required.
Note: The virtual environment shebang may not work on all systems (notably macOS, due to
env
inconsistencies). Verified to work on UniFi OS 4.3.6 (UCKG2).
rstphack [-q|--quiet] [-d|--dryrun] <switch_mac> <port_idx> <required_stp_cost> <user@ip_address>
-q, --quiet
– Suppress informational messages (errors are still shown)-d, --dryrun
– Show the intended SSH command without executing it
switch_mac
– Switch MAC address (e.g.,00:11:22:33:44:55
)port_idx
– Port index to modifyrequired_stp_cost
– Desired RSTP/STP path cost (1–200000000)user@ip_address
– SSH target (e.g.,[email protected]
)
rstphack -q 00:11:22:33:44:55 3 200000 [email protected]
This will:
- Connect to the Controller.
- Locate the switch with the specified MAC.
- Check the cost of port
3
. - If not
200000
, connect via SSH and update the configuration.
Changes are verified only via the Controller API. Although the switch applies the modification immediately, the Controller may take 5 minutes or more to reflect the update.
The script maps ports automatically:
- Gigabit Ethernet (GE) →
gi{port_idx}
(e.g.,gi1
,gi2
) - 10 Gigabit Ethernet (XG) →
te{port_idx}
(e.g.,te1
,te2
)
When not run with --quiet
, the script outputs status messages with:
- ✓ for success
- ✗ for failure
Exit codes:
0
– Success1
– Failure
Authentication with the switch uses SSH keys. Use the UniFi Controller UI to set it up (Device→Device Updates and Settings
on the top right corner).
- SSL Verification is disabled for Controller access. This avoids connection issues and complex settings.
- Support switches where
cli
is only an alias totelnet localhost
. - Add direct verification of port cost on the switch.
- Use of a configuration file for Controller and switches information
- 0.9.1 – Added systemd unit files and instructions.
- 0.9 – Initial release with cron example.
This script is provided under the MIT License, without warranty, for educational and operational purposes.