Hey everyone, Running a Hive Engine node at home is a great way to support the ecosystem, but it comes with a hidden cost: **Upload Bandwidth.** Most residential internet connections are asymmetric, you might have gigabit download speeds, but your upload is often a fraction of that. When a node starts syncing or serving API requests, it can easily saturate your entire upload link. When that happens, your ping skyrockets, your streams buffer, and everyone else in the house starts complaining. To keep the peace (and my internet usable), I had to play traffic cop. I wrote a set of scripts to strictly limit the bandwidth my node consumes using the Linux `tc` (Traffic Control) tool. Here is how I built the **TC-Engine**. ![traffic.jpg](https://files.peakd.com/file/peakd-hive/thecrazygm/23wMMcy9XqJJ7aNyFhEL6JBMFMZZTLfvFQpvacrBw9PPRXQGrDs3yQ9fhPAoEmrzz4mr8.jpg) ### 1. The Enforcer: The Start Script The heavy lifting is done by a bash script that utilizes **HTB (Hierarchical Token Bucket)**. This allows me to set a hard "ceiling" on how much data the node can send out. I specifically target the ports used by the Hive Engine node: **443 (HTTPS/API), 5001 (P2P), and 5002 (RPC)**. Here is the `start-tc-engine.sh`: ```bash #!/usr/bin/env bash set -euo pipefail DEV="enp0s31f6" # My specific network interface RATE="4mbit" # The Speed Limit PORTS=(443 5001 5002) # Clear existing rules to ensure a clean slate if /sbin/tc qdisc show dev "$DEV" | grep -q "htb 1:"; then /sbin/tc qdisc del dev "$DEV" root || true fi # 1. Create the Root Qdisc (Queueing Discipline) /sbin/tc qdisc add dev "$DEV" root handle 1: htb default 10 # 2. Create a Class with the Rate Limit # We set both rate and ceil to 4mbit to create a hard cap /sbin/tc class add dev "$DEV" parent 1: classid 1:10 htb rate "$RATE" ceil "$RATE" # 3. Filter Traffic into that Class # Any packet leaving on our target ports gets shoved into the limited class for PORT in "${PORTS[@]}"; do /sbin/tc filter add dev "$DEV" protocol ip parent 1:0 prio 1 u32 \ match ip sport "$PORT" 0xffff flowid 1:10 done ``` ### 2. The Cleanup Crew: The Stop Script If I need to turn off the limiter or restart the service, I need a clean way to remove the rules. This script simply checks if the rules exist and deletes them. ```bash #!/usr/bin/env bash set -euo pipefail DEV="enp0s31f6" if /sbin/tc qdisc show dev "$DEV" | grep -q "htb 1:"; then /sbin/tc qdisc del dev "$DEV" root echo "Success: Removed traffic control rules from $DEV." else echo "Info: No active HTB rules found on $DEV. Nothing to do." fi ``` ### 3. The Manager: Systemd Service To make sure this runs automatically when the server boots, I wrapped it all in a simple `systemd` unit. It's a "oneshot" service that remains active after exiting, ensuring the rules stay in place until I stop the service. **`/etc/systemd/system/tc-engine.service`** ```ini [Unit] Description=Traffic Control Bandwidth Limiter After=network.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/start-tc-engine.sh ExecStop=/usr/local/sbin/stop-tc-engine.sh [Install] WantedBy=multi-user.target ``` ### 4. The Watchdog: Udev Rules There is one "gotcha" with Traffic Control: if the network interface resets (like if the driver updates or the cable is unplugged and replugged), the kernel wipes all the `tc` rules attached to it. To fix this, I added a `udev` rule. This watches for the specific network interface (`enp0s31f6`) to be initialized and automatically triggers a restart of the service to re-apply the limits. **`/etc/udev/rules.d/99-tc-engine.rules`** ```bash ACTION=="add", SUBSYSTEM=="net", KERNEL=="enp0s31f6", RUN+="/bin/systemctl --no-block restart tc-engine.service" ``` ### The Result With this setup, my node is capped at **4Mbit upload**. It continues to serve the network and sync perfectly fine, but it can no longer hog the entire connection. The internet is fast, the family is happy, and the node keeps running. As always, Michael Garcia a.k.a. TheCrazyGM