diff --git a/servers/legion/k8s/media/fornax-workers.yaml b/servers/legion/k8s/media/fornax-workers.yaml index 52eda94..102ac20 100644 --- a/servers/legion/k8s/media/fornax-workers.yaml +++ b/servers/legion/k8s/media/fornax-workers.yaml @@ -35,22 +35,52 @@ spec: securityContext: privileged: true - name: qbt-config-patch - image: busybox:latest + image: python:3-alpine command: - - sh + - python3 - -c - | - CONF=/config/qBittorrent/qBittorrent.conf - HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' - mkdir -p /config/qBittorrent - if [ -f "$CONF" ]; then - if grep -q "Password_PBKDF2" "$CONF"; then - sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF" - else - sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF" - fi - fi - echo "Password hash set." + import os, re + + CONF = '/config/qBittorrent/qBittorrent.conf' + os.makedirs('/config/qBittorrent', exist_ok=True) + + text = open(CONF).read() if os.path.exists(CONF) else '' + + def set_key(text, section, key, value): + """Set key=value under [section], inserting if missing.""" + key_pat = re.compile(r'^' + re.escape(key) + r'=.*', re.M) + if key_pat.search(text): + return key_pat.sub(key + '=' + value, text) + sec_pat = re.compile(r'^\[' + re.escape(section) + r'\]', re.M) + if sec_pat.search(text): + return sec_pat.sub('[' + section + ']\n' + key + '=' + value, text) + return text + f'\n[{section}]\n{key}={value}\n' + + HASH = '@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' + + # Preferences + text = set_key(text, 'Preferences', r'WebUI\Password_PBKDF2', f'"{HASH}"') + text = set_key(text, 'Preferences', r'WebUI\LocalhostAuthEnabled', 'false') + + # BitTorrent performance defaults (only applied when key absent — API updates persist) + bt_defaults = { + r'Session\MaxActiveDownloads': '50', + r'Session\MaxActiveTorrents': '100', + r'Session\MaxActiveUploads': '20', + r'Session\MaxConnections': '3000', + r'Session\MaxConnectionsPerTorrent': '300', + r'Session\MaxUploads': '-1', + r'Session\MaxUploadsPerTorrent': '10', + r'Session\GlobalDLSpeedLimit': '0', + r'Session\GlobalUPSpeedLimit': '0', + r'Session\DHTEnabled': 'true', + } + for key, val in bt_defaults.items(): + text = set_key(text, 'BitTorrent', key, val) + + open(CONF, 'w').write(text) + print('qBittorrent config patched.') volumeMounts: - name: config mountPath: /config @@ -211,22 +241,52 @@ spec: securityContext: privileged: true - name: qbt-config-patch - image: busybox:latest + image: python:3-alpine command: - - sh + - python3 - -c - | - CONF=/config/qBittorrent/qBittorrent.conf - HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' - mkdir -p /config/qBittorrent - if [ -f "$CONF" ]; then - if grep -q "Password_PBKDF2" "$CONF"; then - sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF" - else - sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF" - fi - fi - echo "Password hash set." + import os, re + + CONF = '/config/qBittorrent/qBittorrent.conf' + os.makedirs('/config/qBittorrent', exist_ok=True) + + text = open(CONF).read() if os.path.exists(CONF) else '' + + def set_key(text, section, key, value): + """Set key=value under [section], inserting if missing.""" + key_pat = re.compile(r'^' + re.escape(key) + r'=.*', re.M) + if key_pat.search(text): + return key_pat.sub(key + '=' + value, text) + sec_pat = re.compile(r'^\[' + re.escape(section) + r'\]', re.M) + if sec_pat.search(text): + return sec_pat.sub('[' + section + ']\n' + key + '=' + value, text) + return text + f'\n[{section}]\n{key}={value}\n' + + HASH = '@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' + + # Preferences + text = set_key(text, 'Preferences', r'WebUI\Password_PBKDF2', f'"{HASH}"') + text = set_key(text, 'Preferences', r'WebUI\LocalhostAuthEnabled', 'false') + + # BitTorrent performance defaults (only applied when key absent — API updates persist) + bt_defaults = { + r'Session\MaxActiveDownloads': '50', + r'Session\MaxActiveTorrents': '100', + r'Session\MaxActiveUploads': '20', + r'Session\MaxConnections': '3000', + r'Session\MaxConnectionsPerTorrent': '300', + r'Session\MaxUploads': '-1', + r'Session\MaxUploadsPerTorrent': '10', + r'Session\GlobalDLSpeedLimit': '0', + r'Session\GlobalUPSpeedLimit': '0', + r'Session\DHTEnabled': 'true', + } + for key, val in bt_defaults.items(): + text = set_key(text, 'BitTorrent', key, val) + + open(CONF, 'w').write(text) + print('qBittorrent config patched.') volumeMounts: - name: config mountPath: /config diff --git a/servers/legion/k8s/media/gluetun-qbittorrent.yaml b/servers/legion/k8s/media/gluetun-qbittorrent.yaml index b499e7f..f5f1a26 100644 --- a/servers/legion/k8s/media/gluetun-qbittorrent.yaml +++ b/servers/legion/k8s/media/gluetun-qbittorrent.yaml @@ -27,25 +27,54 @@ spec: command: ["sh", "-c", "mkdir -p /dev/net && [ -c /dev/net/tun ] || mknod /dev/net/tun c 10 200 && chmod 666 /dev/net/tun && sysctl -w net.ipv6.conf.all.disable_ipv6=1 || true && ip route flush table 51820 2>/dev/null || true && ip rule del priority 101 2>/dev/null || true && ip rule del table 51820 2>/dev/null || true"] securityContext: privileged: true - # Patch qBittorrent config before it starts so localhost auth is disabled from boot + # Patch qBittorrent config before it starts: set password hash + performance defaults - name: qbt-config-patch - image: busybox:latest + image: python:3-alpine command: - - sh + - python3 - -c - | - CONF=/config/qBittorrent/qBittorrent.conf - HASH='@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' - mkdir -p /config/qBittorrent - if [ -f "$CONF" ]; then - # Set known adminadmin password hash - if grep -q "Password_PBKDF2" "$CONF"; then - sed -i "s|WebUI\\\\Password_PBKDF2=.*|WebUI\\\\Password_PBKDF2=\"$HASH\"|" "$CONF" - else - sed -i "/^\[Preferences\]/a WebUI\\\\Password_PBKDF2=\"$HASH\"" "$CONF" - fi - fi - echo "Password hash set." + import os, re + + CONF = '/config/qBittorrent/qBittorrent.conf' + os.makedirs('/config/qBittorrent', exist_ok=True) + + text = open(CONF).read() if os.path.exists(CONF) else '' + + def set_key(text, section, key, value): + """Set key=value under [section], inserting if missing.""" + key_pat = re.compile(r'^' + re.escape(key) + r'=.*', re.M) + if key_pat.search(text): + return key_pat.sub(key + '=' + value, text) + sec_pat = re.compile(r'^\[' + re.escape(section) + r'\]', re.M) + if sec_pat.search(text): + return sec_pat.sub('[' + section + ']\n' + key + '=' + value, text) + return text + f'\n[{section}]\n{key}={value}\n' + + HASH = '@ByteArray(HqYj1eGsdXlQ4CSy597Y9A==:J9hsJIlU5FYfHb5rY5qQoIpVpTijryS/H+CE07oMtplL/ytneBVFd2tfVJtqGjhdht8tEi4wmqSSlqTgEu444w==)' + + # Preferences + text = set_key(text, 'Preferences', r'WebUI\Password_PBKDF2', f'"{HASH}"') + text = set_key(text, 'Preferences', r'WebUI\LocalhostAuthEnabled', 'false') + + # BitTorrent performance defaults (only applied when key absent — API updates persist) + bt_defaults = { + r'Session\MaxActiveDownloads': '50', + r'Session\MaxActiveTorrents': '100', + r'Session\MaxActiveUploads': '20', + r'Session\MaxConnections': '3000', + r'Session\MaxConnectionsPerTorrent': '300', + r'Session\MaxUploads': '-1', + r'Session\MaxUploadsPerTorrent': '10', + r'Session\GlobalDLSpeedLimit': '0', + r'Session\GlobalUPSpeedLimit': '0', + r'Session\DHTEnabled': 'true', + } + for key, val in bt_defaults.items(): + text = set_key(text, 'BitTorrent', key, val) + + open(CONF, 'w').write(text) + print('qBittorrent config patched.') volumeMounts: - name: config mountPath: /config