Installation
Get Bandwidth Manager running on your Docker host in under a minute. This guide covers the automated installer, a manual from‑source build, systemd setup, and common pitfalls.
Prerequisites
| Requirement | Minimum | Notes |
|---|---|---|
| Linux kernel | 4.x+ | tc htb and fq_codel qdiscs must be available. 5.x recommended. |
| Docker Engine | 20.10+ | Daemon needs access to the Docker socket (/var/run/docker.sock). |
| Root access | Yes | tc netlink operations and Docker socket access require CAP_NET_ADMIN. |
| Architecture | amd64 / arm64 | Pre‑built binaries for both. |
Quick Dependency Check
Run these commands to verify your host is ready:
# Kernel version
uname -r
# tc availability (should print qdisc list or "noqueue")
tc qdisc show 2>/dev/null | head -5
# Docker socket
docker info > /dev/null 2>&1 && echo "Docker OK" || echo "Docker not reachable"If all three pass, you're good to go.
One‑Liner Install
curl -sSL https://raw.githubusercontent.com/AnAverageBeing/Bandwidth-flow-maintainer/main/install.sh | sudo bashAlways inspect scripts before piping them to sudo.
View the installer source →
What the Installer Does (Step by Step)
The install script runs 7 steps in sequence. Each step is idempotent — you can re‑run the script safely.
Step 1 — OS & Kernel Validation
# Checks /etc/os-release; confirms kernel >= 4.0
# Exits early on unsupported distros or ancient kernelsStep 2 — Dependency Bootstrap
Installs any missing OS packages required for the build or runtime:
# Debian / Ubuntu
apt-get update && apt-get install -y curl tar iproute2
# RHEL / Fedora / Rocky
dnf install -y curl tar iproute-tcStep 3 — Binary Download
Fetches the latest release from GitHub, verifies the SHA256 checksum, and extracts:
curl -sSL "https://github.com/AnAverageBeing/Bandwidth-flow-maintainer/releases/latest/download/bwm_linux_amd64.tar.gz" \
| sudo tar xz -C /usr/local/binInstalled binaries:
| Binary | Purpose |
|---|---|
bwm-daemon | Background service, tc controller |
bwm | CLI client for querying and managing |
Step 4 — Configuration Directory
sudo mkdir -p /etc/bwm
sudo chmod 750 /etc/bwmA default config is written to /etc/bwm/config.yaml if none exists. See Configuration → for every available option.
Step 5 — Data Directory
sudo mkdir -p /var/lib/bwm
sudo chmod 750 /var/lib/bwmThe SQLite database (bandwidth.db) lives here. Keep this directory backed up if historical stats matter to you.
Step 6 — Systemd Unit File
A hardened unit is written to /etc/systemd/system/bwm.service:
[Unit]
Description=Bandwidth Manager — Docker traffic control daemon
Documentation=https://github.com/AnAverageBeing/Bandwidth-flow-maintainer
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/local/bin/bwm-daemon --config /etc/bwm/config.yaml
Restart=always
RestartSec=5
# Sandbox hardening
ProtectSystem=strict
ReadWritePaths=/var/lib/bwm /run/docker.sock
ProtectHome=true
NoNewPrivileges=true
PrivateTmp=true
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE
[Install]
WantedBy=multi-user.targetKey hardening directives:
| Directive | Effect |
|---|---|
ProtectSystem=strict | /usr, /boot, /etc are read‑only. Only whitelisted paths are writable. |
NoNewPrivileges=true | Prevents privilege escalation via setuid binaries. |
CapabilityBoundingSet | Drops every capability except CAP_NET_ADMIN (for tc) and CAP_DAC_OVERRIDE (for Docker socket). |
Step 7 — Start & Enable
sudo systemctl daemon-reload
sudo systemctl enable --now bwmAfter step 7, the daemon is running and will auto‑start on boot.
Manual Install from Source
Prefer to build from source or need a custom patch? Here's the full build chain.
Prerequisites
- Go 1.21 or later
- make
- gcc (for SQLite CGo bindings, if applicable)
Build Steps
# 1. Clone the repository
git clone https://github.com/AnAverageBeing/Bandwidth-flow-maintainer.git
cd Bandwidth-flow-maintainer
# 2. Build both binaries
make build
# Equivalent to:
# CGO_ENABLED=1 go build -ldflags="-s -w -X main.version=$(git describe --tags)" -o bin/bwm-daemon ./cmd/daemon
# CGO_ENABLED=1 go build -ldflags="-s -w -X main.version=$(git describe --tags)" -o bin/bwm ./cmd/cli
# 3. Install
sudo cp bin/bwm-daemon /usr/local/bin/
sudo cp bin/bwm /usr/local/bin/
sudo chmod 755 /usr/local/bin/bwm-daemon /usr/local/bin/bwmVerify the Build
bwm version
# Expected output:
# bwm version v1.2.3 (commit: a1b2c3d, built: 2025-06-15T10:30:00Z)Unit File (Manual)
If you built from source, write the systemd unit yourself:
sudo tee /etc/systemd/system/bwm.service << 'EOF'
[Unit]
Description=Bandwidth Manager — Docker traffic control daemon
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/local/bin/bwm-daemon --config /etc/bwm/config.yaml
Restart=always
RestartSec=5
ProtectSystem=strict
ReadWritePaths=/var/lib/bwm /run/docker.sock
ProtectHome=true
NoNewPrivileges=true
PrivateTmp=true
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now bwmSystemd Service Management
Everyday commands you'll need:
# Check status
sudo systemctl status bwm
# Follow logs
sudo journalctl -u bwm -f
# Reload after config change
sudo systemctl reload bwm
# Restart
sudo systemctl restart bwm
# Stop
sudo systemctl stop bwm
# Disable auto-start
sudo systemctl disable bwmLogging
All daemon output goes to the systemd journal. For structured logs, set log_format: json in your config:
# Pretty-print recent JSON logs
sudo journalctl -u bwm --since "5 min ago" -o cat | jq '.'Post‑Install Verification
Run these commands to confirm everything is wired up correctly:
1. Daemon Reachable
bwm pingExpected: pong (or daemon reachable).
2. Service Healthy
sudo systemctl is-active bwmExpected: active.
3. Docker Event Hook Working
bwm statusExpected: a table summarising the daemon uptime, tracked containers, and overall bandwidth in/out.
4. End‑to‑End Test
Spin up a test container with a label and verify the limit is enforced:
# Launch a container with a 1 Mbps upload cap
docker run -d --rm \
--name bwm-test \
--label bwm.limit.up=1mbps \
alpine:latest sleep 3600
# Wait 5 seconds for discovery
sleep 5
# Inspect the rules applied to this container
bwm container inspect bwm-testExpected: a tc class entry with a 1 Mbps ceiling on the container's veth.
# Cleanup
docker rm -f bwm-testTroubleshooting
Go Version Too Old
Symptom: make build fails with package slices is not in GOROOT or similar.
# Check version
go versionFix: Install Go 1.21+:
# Using the official tarball
curl -sSL https://go.dev/dl/go1.22.5.linux-amd64.tar.gz | sudo tar xz -C /usr/local
export PATH=/usr/local/go/bin:$PATHDocker Socket Permission Denied
Symptom: Daemon logs show permission denied when accessing /var/run/docker.sock.
Fix: Ensure the daemon runs as a user in the docker group, or use root:
# Option A: run as root (default with systemd)
sudo systemctl cat bwm | grep User
# Option B: add a dedicated user to the docker group
sudo usermod -aG docker bwm
sudo systemctl restart bwmtc Command Not Found
Symptom: Daemon logs show exec: "tc": executable file not found in $PATH.
Fix: Install iproute2 (or iproute on older distros):
# Debian / Ubuntu
sudo apt-get install -y iproute2
# RHEL / Fedora
sudo dnf install -y iproute-tcThen restart:
sudo systemctl restart bwmhtb or fq_codel Qdisc Missing
Symptom: Daemon logs show RTNETLINK answers: No such file or directory or Unknown qdisc "htb".
Fix: Your kernel was compiled without traffic‑control modules. Verify:
# Check if tc qdiscs are available
tc qdisc add dev lo root handle 1: htb 2>/dev/null && echo "htb OK" || echo "htb missing"
tc qdisc del dev lo root 2>/dev/nullIf missing, rebuild your kernel with:
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_FQ_CODEL=yAlternatively, switch to a stock distribution kernel (Ubuntu, Debian, Fedora all ship with these enabled).
Systemd Unit Fails to Start
Symptom: systemctl status bwm shows failed or inactive.
Diagnose step by step:
# 1. Check the unit file syntax
sudo systemd-analyze verify /etc/systemd/system/bwm.service
# 2. Inspect the last boot log
sudo journalctl -u bwm --boot -e --no-pager
# 3. Run the daemon manually to see raw output
sudo /usr/local/bin/bwm-daemon --config /etc/bwm/config.yaml --debugCommon causes:
| Error | Likely Cause |
|---|---|
exec format error | Downloaded the wrong architecture binary |
bind: address already in use | Another instance is already running |
config file not found | Missing /etc/bwm/config.yaml |
failed to create database | /var/lib/bwm not writable |
Containers Not Being Discovered
Symptom: bwm status shows zero tracked containers despite running containers.
Fix: The daemon needs access to the Docker event stream. Verify:
# Can the daemon reach Docker?
sudo -u bwm docker events --since 1s 2>&1 | head -5
# If that fails, check socket permissions
ls -la /var/run/docker.sock
# Expected: srw-rw---- 1 root dockerAdd the daemon user to the docker group, or set docker_socket_group: docker in the config.
Uninstall
To completely remove Bandwidth Manager from the host:
# 1. Stop and disable the service
sudo systemctl stop bwm
sudo systemctl disable bwm
# 2. Remove the unit file
sudo rm -f /etc/systemd/system/bwm.service
sudo systemctl daemon-reload
# 3. Remove binaries
sudo rm -f /usr/local/bin/bwm-daemon /usr/local/bin/bwm
# 4. (Optional) Remove config and data
sudo rm -rf /etc/bwm /var/lib/bwmRemoving /var/lib/bwm deletes all historical stats and quota counters. Back it up first if you plan to re‑install later.
Minimal Cleanup (Preserve Data)
sudo systemctl stop bwm
sudo systemctl disable bwm
sudo rm -f /etc/systemd/system/bwm.service
sudo rm -f /usr/local/bin/bwm-daemon /usr/local/bin/bwmThis leaves /etc/bwm and /var/lib/bwm intact so a future re‑install picks up the same database and config.
What's Next?
- Configuration → — Set up labels, quotas, webhooks, and daemon tuning.
- CLI Reference → — Explore every command:
bwm container,bwm stats,bwm quota. - TUI Guide → — Master the interactive terminal dashboard.
- GitHub Repo → — Star, fork, or open an issue.
