docs: daylog 2026-09-25 qbittorrent bt-net + scripts/prime apply-koopa-bt-fix wrappers
This commit is contained in:
parent
e01fbedcd8
commit
08b1676b19
7 changed files with 180 additions and 1 deletions
39
2026/2026-09-25--qbittorrent-bt-net.md
Normal file
39
2026/2026-09-25--qbittorrent-bt-net.md
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
# 2026-09-25 — qBittorrent BT net (flame / firewalled)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
Inbound BT listen **6881** tcp+udp reachable so WebUI connection status leaves the firewalled (flame) state.
|
||||||
|
|
||||||
|
## Live on koopa
|
||||||
|
- CTR `koopa-prime-qbittorrent` (linuxserver): host **6881** tcp+udp, WebUI **9023**→8080 → `bt.hacktivism.ch`
|
||||||
|
- Conf: `Session\Port=6881`, `PortForwardingEnabled=true`, `Connection\UPnP=true`
|
||||||
|
- Temp: `/downloads/incomplete/` (abc / host uid 100999)
|
||||||
|
- Durable apply: `scripts/prime/apply-qbittorrent-bt-net.sh` (+ wrapper `koopa-bt-fix.sh`)
|
||||||
|
- Clone on host: `~/koopa-admin-log/scripts/prime/`
|
||||||
|
|
||||||
|
## firewalld
|
||||||
|
- Doc: `configs/firewalld/public-ports.md` — **6881/tcp+udp**
|
||||||
|
- Agent cannot list without sudo/polkit; human opens with:
|
||||||
|
```bash
|
||||||
|
sudo firewall-cmd --permanent --add-port=6881/tcp
|
||||||
|
sudo firewall-cmd --permanent --add-port=6881/udp
|
||||||
|
sudo firewall-cmd --reload
|
||||||
|
```
|
||||||
|
- WAN probe success (below) implies the path through host firewall is open.
|
||||||
|
|
||||||
|
## VeciGate (2026-09-25)
|
||||||
|
- wan `dstnat` tcp+udp **6881** → `192.168.100.95:6881`
|
||||||
|
- hairpin LAN `192.168.100.0/24` and LAN2 `192.168.88.0/24` → `212.51.151.254:6881` tcp+udp
|
||||||
|
- Comments: `koopa: qBittorrent BT …` / `hairpin: LAN[2] qBittorrent BT …`
|
||||||
|
- Detail: vecigate-admin-log `2026/2026-09-25--qbittorrent-bt-dnat.md`
|
||||||
|
|
||||||
|
## Verify (2026-09-25, from magikoopa)
|
||||||
|
| Probe | Result |
|
||||||
|
|-------|--------|
|
||||||
|
| `nc -vz 192.168.100.95 6881` | LAN_TCP_OK |
|
||||||
|
| `nc -vz 212.51.151.254 6881` | WAN_TCP_OK |
|
||||||
|
| `nc -zu 212.51.151.254 6881` | WAN_UDP_OK |
|
||||||
|
|
||||||
|
WebUI API (`/api/v2/…`) still auth-gated from agent — human glance at connection icon on `bt.hacktivism.ch`.
|
||||||
|
|
||||||
|
## Freigabe
|
||||||
|
Session Freigabe covered podman conf/restart + VeciGate NAT. No git push of admin-log unless asked.
|
||||||
|
|
@ -18,6 +18,7 @@ sudo firewall-cmd --list-ports
|
||||||
| 8080/tcp | Tor OR | — |
|
| 8080/tcp | Tor OR | — |
|
||||||
| 23235/tcp | (legacy list; host SSH is :22, WAN via VeciGate 23235→22) | — |
|
| 23235/tcp | (legacy list; host SSH is :22, WAN via VeciGate 23235→22) | — |
|
||||||
| **9200/tcp** | **Forgejo git-SSH** (podman rootlessport) | **OK** after add+reload |
|
| **9200/tcp** | **Forgejo git-SSH** (podman rootlessport) | **OK** after add+reload |
|
||||||
|
| **6881/tcp+udp** | qBittorrent BT listen (`koopa-prime-qbittorrent`) | apply: `scripts/prime/apply-qbittorrent-bt-net.sh` |
|
||||||
|
|
||||||
### Not opened on purpose
|
### Not opened on purpose
|
||||||
|
|
||||||
|
|
@ -61,6 +62,7 @@ Forgejo advertises `SSH_PORT=9200`. Traffic hits **host:9200** (not Caddy). With
|
||||||
|------|--------|
|
|------|--------|
|
||||||
| 2026-07-09 | 443/tcp re-added for IPv6 |
|
| 2026-07-09 | 443/tcp re-added for IPv6 |
|
||||||
| 2026-07-10 | **9200/tcp** for Forgejo git-SSH (verified LAN + hairpin + SSH auth) |
|
| 2026-07-10 | **9200/tcp** for Forgejo git-SSH (verified LAN + hairpin + SSH auth) |
|
||||||
|
| 2026-09-25 | **6881/tcp+udp** for qBittorrent BT (`scripts/prime/apply-qbittorrent-bt-net.sh`); VeciGate wan+hairpin DNAT live; WAN/LAN `nc` OK |
|
||||||
|
|
||||||
## Nym (`koopa-nym`, nym.com)
|
## Nym (`koopa-nym`, nym.com)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
| 9020 | `koopa-castopod` → `castopod.hacktivism.ch` |
|
| 9020 | `koopa-castopod` → `castopod.hacktivism.ch` |
|
||||||
| 9021 | `koopa-bonfire` → `bonfire.hacktivism.ch` |
|
| 9021 | `koopa-bonfire` → `bonfire.hacktivism.ch` |
|
||||||
| 9022 | `koopa-prime` (Jellyfin) → `prime.hacktivism.ch` |
|
| 9022 | `koopa-prime` (Jellyfin) → `prime.hacktivism.ch` |
|
||||||
| 9023 | qBittorrent → `bt.hacktivism.ch` |
|
| 9023 | qBittorrent WebUI → `bt.hacktivism.ch` |
|
||||||
|
| **6881** | qBittorrent BT listen (tcp+udp; firewalld + VeciGate DNAT) |
|
||||||
| **9024** | `koopa-forgejo` (HTTP) → **`git.hacktivism.ch`** |
|
| **9024** | `koopa-forgejo` (HTTP) → **`git.hacktivism.ch`** |
|
||||||
| **9025** | `koopa-paivana` → `paivana.hacktivism.ch` |
|
| **9025** | `koopa-paivana` → `paivana.hacktivism.ch` |
|
||||||
| **9026** | `koopa-lemmy-proxy` → `lemmy.hacktivism.ch` |
|
| **9026** | `koopa-lemmy-proxy` → `lemmy.hacktivism.ch` |
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
| Compose | `compose.yml` (this dir; **no secret values**) |
|
| Compose | `compose.yml` (this dir; **no secret values**) |
|
||||||
| Jellyfin | **9022** → Caddy `prime.hacktivism.ch` |
|
| Jellyfin | **9022** → Caddy `prime.hacktivism.ch` |
|
||||||
| qBittorrent | **9023** → Caddy `bt.hacktivism.ch` |
|
| qBittorrent | **9023** → Caddy `bt.hacktivism.ch` |
|
||||||
|
| BT listen | **6881** tcp+udp (firewalld + VeciGate DNAT); apply `scripts/prime/apply-qbittorrent-bt-net.sh` |
|
||||||
| Topic | `2026/2026-07-09--koopa-prime-jellyfin.md` |
|
| Topic | `2026/2026-07-09--koopa-prime-jellyfin.md` |
|
||||||
|
|
||||||
`WEBUI_PASSWORD` is `${WEBUI_PASSWORD}` in the mirror — live value only in
|
`WEBUI_PASSWORD` is `${WEBUI_PASSWORD}` in the mirror — live value only in
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
| `taler-wallet-cli/` | thin wrappers; **benchmarks live in** `../benchmarks/` |
|
| `taler-wallet-cli/` | thin wrappers; **benchmarks live in** `../benchmarks/` |
|
||||||
| `castopod/` | host `hernani` podman-compose `~/koopa-castopod` — see `castopod/README.md` |
|
| `castopod/` | host `hernani` podman-compose `~/koopa-castopod` — see `castopod/README.md` |
|
||||||
| `lemmy/` | host `hernani` podman-compose `~/koopa-lemmy` — see `configs/lemmy/README.md` |
|
| `lemmy/` | host `hernani` podman-compose `~/koopa-lemmy` — see `configs/lemmy/README.md` |
|
||||||
|
| `prime/` | qBittorrent BT net apply (`apply-qbittorrent-bt-net.sh`; wrapper `koopa-bt-fix.sh`) — incomplete dir, UPnP/PF, firewalld **6881** |
|
||||||
|
|
||||||
**Secrets:** never in this tree — sibling **`../koopa-admin-secrets`** (`koopa/host-root/<service>/` ↔ `/root/` on host; `containers/…/secrets/` for in-container).
|
**Secrets:** never in this tree — sibling **`../koopa-admin-secrets`** (`koopa/host-root/<service>/` ↔ `/root/` on host; `containers/…/secrets/` for in-container).
|
||||||
|
|
||||||
|
|
|
||||||
132
scripts/prime/apply-qbittorrent-bt-net.sh
Executable file
132
scripts/prime/apply-qbittorrent-bt-net.sh
Executable file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Apply qBittorrent BT net fixes on koopa (flame / firewalled inbound).
|
||||||
|
#
|
||||||
|
# Supersedes session one-shot /tmp/koopa-bt-fix.sh (2026-09-25).
|
||||||
|
#
|
||||||
|
# On koopa (hernani; firewalld needs sudo):
|
||||||
|
# bash /path/to/koopa-admin-log/scripts/prime/apply-qbittorrent-bt-net.sh
|
||||||
|
# # or after clone:
|
||||||
|
# bash ~/koopa-admin-log/scripts/prime/apply-qbittorrent-bt-net.sh
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1) /downloads/incomplete/ as container user abc (host uid 100999)
|
||||||
|
# 2) PortForwardingEnabled + Connection\UPnP = true (edit inside container)
|
||||||
|
# 3) firewalld public: 6881/tcp + 6881/udp (sudo)
|
||||||
|
# 4) podman restart koopa-prime-qbittorrent + STATUS= lines
|
||||||
|
#
|
||||||
|
# WAN inbound: VeciGate DNAT 6881 tcp+udp → koopa:6881 (+ hairpin LAN/LAN2)
|
||||||
|
# applied 2026-09-25 (comment~qBittorrent). Re-check with script footer STATUS.
|
||||||
|
#
|
||||||
|
# Freigabe: podman + firewalld (session Freigabe required for live apply).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CTR=koopa-prime-qbittorrent
|
||||||
|
CONF_IN=/config/qBittorrent/qBittorrent.conf
|
||||||
|
BT_PORT="${BT_PORT:-6881}"
|
||||||
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
|
||||||
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
command -v podman >/dev/null || die "podman missing"
|
||||||
|
podman container exists "$CTR" || die "container $CTR missing"
|
||||||
|
|
||||||
|
echo "===1_INCOMPLETE==="
|
||||||
|
podman exec -u abc "$CTR" sh -c '
|
||||||
|
set -e
|
||||||
|
mkdir -p /downloads/incomplete
|
||||||
|
ls -lad /downloads /downloads/incomplete
|
||||||
|
touch /downloads/incomplete/.writeok && rm /downloads/incomplete/.writeok
|
||||||
|
echo incomplete_write=OK
|
||||||
|
'
|
||||||
|
|
||||||
|
echo "===2_CONF_UPNP_PF==="
|
||||||
|
# Host hernani cannot write config (owned by mapped abc/100999). Edit as abc.
|
||||||
|
podman exec -u abc "$CTR" sh -c "
|
||||||
|
set -e
|
||||||
|
CONF='$CONF_IN'
|
||||||
|
test -f \"\$CONF\" || { echo missing_conf; exit 1; }
|
||||||
|
cp -a \"\$CONF\" \"\${CONF}.bak-btfix-$STAMP\"
|
||||||
|
echo bak=\${CONF}.bak-btfix-$STAMP
|
||||||
|
python3 - \"\$CONF\" <<'PY'
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
p = Path(sys.argv[1])
|
||||||
|
text = p.read_text()
|
||||||
|
orig = text
|
||||||
|
repls = [
|
||||||
|
('PortForwardingEnabled=false', 'PortForwardingEnabled=true'),
|
||||||
|
('Connection\\\\UPnP=false', 'Connection\\\\UPnP=true'),
|
||||||
|
]
|
||||||
|
changed = False
|
||||||
|
for a, b in repls:
|
||||||
|
if a in text:
|
||||||
|
text = text.replace(a, b)
|
||||||
|
changed = True
|
||||||
|
if not changed:
|
||||||
|
# Already true, or unexpected keys — report and continue if already OK
|
||||||
|
keys = [ln for ln in text.splitlines() if 'UPnP' in ln or 'PortForward' in ln]
|
||||||
|
if any('=true' in ln for ln in keys) and not any('=false' in ln for ln in keys if 'UPnP' in ln or 'PortForward' in ln):
|
||||||
|
print('already_ok')
|
||||||
|
for ln in keys:
|
||||||
|
print(ln)
|
||||||
|
raise SystemExit(0)
|
||||||
|
print('no_keys_replaced')
|
||||||
|
for ln in keys:
|
||||||
|
print(ln)
|
||||||
|
raise SystemExit(2)
|
||||||
|
p.write_text(text)
|
||||||
|
print('replaced_ok')
|
||||||
|
for ln in text.splitlines():
|
||||||
|
if 'UPnP' in ln or 'PortForward' in ln:
|
||||||
|
print(ln)
|
||||||
|
PY
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "===3_FIREWALLD==="
|
||||||
|
fw_ok=0
|
||||||
|
if command -v firewall-cmd >/dev/null 2>&1; then
|
||||||
|
if sudo -n true 2>/dev/null; then
|
||||||
|
SUDO=(sudo -n)
|
||||||
|
elif [[ "$(id -u)" -eq 0 ]]; then
|
||||||
|
SUDO=()
|
||||||
|
else
|
||||||
|
# Interactive sudo (Freigabe path)
|
||||||
|
SUDO=(sudo)
|
||||||
|
fi
|
||||||
|
if "${SUDO[@]}" firewall-cmd --permanent --add-port="${BT_PORT}/tcp" \
|
||||||
|
&& "${SUDO[@]}" firewall-cmd --permanent --add-port="${BT_PORT}/udp" \
|
||||||
|
&& "${SUDO[@]}" firewall-cmd --reload; then
|
||||||
|
echo "firewalld_ports=$("${SUDO[@]}" firewall-cmd --list-ports 2>/dev/null || true)"
|
||||||
|
echo "firewalld=OK"
|
||||||
|
fw_ok=1
|
||||||
|
else
|
||||||
|
echo "firewalld=FAIL"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "firewalld=MISSING_CMD"
|
||||||
|
fi
|
||||||
|
if [[ "$fw_ok" -ne 1 ]]; then
|
||||||
|
echo "HINT: sudo firewall-cmd --permanent --add-port=${BT_PORT}/tcp"
|
||||||
|
echo "HINT: sudo firewall-cmd --permanent --add-port=${BT_PORT}/udp"
|
||||||
|
echo "HINT: sudo firewall-cmd --reload"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "===4_RESTART==="
|
||||||
|
podman restart "$CTR"
|
||||||
|
sleep 4
|
||||||
|
podman ps --filter "name=$CTR" --format '{{.Names}} {{.Status}} {{.Ports}}'
|
||||||
|
|
||||||
|
echo "===5_POST==="
|
||||||
|
podman exec -u abc "$CTR" sh -c "
|
||||||
|
grep -E 'UPnP|PortForward' $CONF_IN || true
|
||||||
|
ls -lad /downloads/incomplete
|
||||||
|
"
|
||||||
|
ss -lntup 2>/dev/null | grep -E "${BT_PORT}|9023" || true
|
||||||
|
ss -lnup 2>/dev/null | grep "${BT_PORT}" || true
|
||||||
|
|
||||||
|
echo "STATUS=apply_done ctr=$CTR bt_port=$BT_PORT firewalld_ok=$fw_ok stamp=$STAMP"
|
||||||
|
# VeciGate DNAT live 2026-09-25: wan dstnat tcp+udp 6881 → 192.168.100.95:6881
|
||||||
|
# + hairpin LAN 192.168.100.0/24 and LAN2 192.168.88.0/24 to 212.51.151.254:6881
|
||||||
|
echo "STATUS=vecigate_dnat live wan+hairpin LAN/LAN2 → 192.168.100.95:$BT_PORT (comment~qBittorrent)"
|
||||||
|
echo "STATUS=verify WAN: nc -vz 212.51.151.254 $BT_PORT ; LAN: nc -vz 192.168.100.95 $BT_PORT"
|
||||||
|
echo "STATUS=verify WebUI connection icon (flame=firewalled) at bt.hacktivism.ch"
|
||||||
3
scripts/prime/koopa-bt-fix.sh
Executable file
3
scripts/prime/koopa-bt-fix.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Compat wrapper: session name koopa-bt-fix.sh → durable apply.
|
||||||
|
exec "$(cd "$(dirname "$0")" && pwd)/apply-qbittorrent-bt-net.sh" "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue