Media sites get Caddy forward_auth; Authentik scripts cover all proxy providers. BookStack OIDC and Plane admin routing fixes included, plus ops scripts for external auth on valhalla.
139 lines
4.1 KiB
Bash
139 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# TB-006 batch 2: disable local auth; Servarr -> External; skip tautulli.
|
|
# Run on valhalla as ginnoir.
|
|
|
|
set_servarr_external() {
|
|
local app="$1"
|
|
local cfg="/config/${app}/config.xml"
|
|
if [[ ! -f "$cfg" ]]; then
|
|
echo "SKIP ${app}: no ${cfg}"
|
|
return 0
|
|
fi
|
|
echo "=== ${app}: set External ==="
|
|
docker stop "$app" >/dev/null
|
|
python3 - "$cfg" <<'PY'
|
|
import sys
|
|
import xml.etree.ElementTree as ET
|
|
|
|
path = sys.argv[1]
|
|
tree = ET.parse(path)
|
|
root = tree.getroot()
|
|
|
|
auth_required = None
|
|
for el in list(root):
|
|
if el.tag == "AuthenticationRequired" and el.text:
|
|
auth_required = el.text.strip()
|
|
break
|
|
|
|
for el in list(root):
|
|
if el.tag in ("AuthenticationMethod", "AuthenticationRequired"):
|
|
root.remove(el)
|
|
|
|
ext = ET.SubElement(root, "AuthenticationMethod")
|
|
ext.text = "External"
|
|
req = ET.SubElement(root, "AuthenticationRequired")
|
|
req.text = auth_required or "Enabled"
|
|
|
|
tree.write(path, encoding="UTF-8", xml_declaration=True)
|
|
print(f" wrote External (AuthenticationRequired={req.text})")
|
|
PY
|
|
docker start "$app" >/dev/null
|
|
grep Authentication "$cfg"
|
|
}
|
|
|
|
for app in sonarr radarr prowlarr whisparr; do
|
|
set_servarr_external "$app"
|
|
done
|
|
|
|
echo "=== bazarr: verify auth disabled ==="
|
|
python3 - <<'PY'
|
|
import yaml
|
|
path = "/config/bazarr/config/config.yaml"
|
|
with open(path) as f:
|
|
d = yaml.safe_load(f)
|
|
auth = d.setdefault("auth", {})
|
|
changed = False
|
|
if auth.get("type") is not None:
|
|
auth["type"] = None
|
|
changed = True
|
|
if auth.get("username"):
|
|
auth["username"] = ""
|
|
changed = True
|
|
if auth.get("password"):
|
|
auth["password"] = ""
|
|
changed = True
|
|
if changed:
|
|
with open(path, "w") as f:
|
|
yaml.safe_dump(d, f, default_flow_style=False, sort_keys=False)
|
|
print(" updated bazarr auth -> type null")
|
|
else:
|
|
print(" already type null / no credentials")
|
|
PY
|
|
docker restart bazarr >/dev/null
|
|
|
|
echo "=== qbittorrent: disable WebUI auth (keep API key for *arr) ==="
|
|
QCONF="/config/qbittorrent/qBittorrent/qBittorrent.conf"
|
|
docker stop qbittorrent >/dev/null
|
|
python3 - "$QCONF" <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
path = Path(sys.argv[1])
|
|
lines = path.read_text().splitlines()
|
|
out = []
|
|
added = False
|
|
for line in lines:
|
|
if line.startswith("WebUI\\AuthenticationEnabled="):
|
|
out.append("WebUI\\AuthenticationEnabled=false")
|
|
added = True
|
|
continue
|
|
out.append(line)
|
|
if not added:
|
|
final = []
|
|
for line in out:
|
|
final.append(line)
|
|
if line.strip() == "[Preferences]":
|
|
final.append("WebUI\\AuthenticationEnabled=false")
|
|
added = True
|
|
out = final
|
|
path.write_text("\n".join(out) + "\n")
|
|
print(" WebUI\\AuthenticationEnabled=false")
|
|
PY
|
|
grep 'WebUI\\AuthenticationEnabled' "$QCONF" || true
|
|
docker start qbittorrent >/dev/null
|
|
|
|
echo "=== nzbget: disable form auth (API creds unchanged) ==="
|
|
NZB="/config/nzbget/nzbget.conf"
|
|
sed -i 's/^FormAuth=.*/FormAuth=no/' "$NZB"
|
|
sed -i 's/^SecureControl=.*/SecureControl=no/' "$NZB"
|
|
grep -E '^(FormAuth|SecureControl)=' "$NZB"
|
|
docker restart nzbget >/dev/null
|
|
|
|
echo "=== stash: external authwall (Authentik + internal_only) ==="
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
import re
|
|
path = Path("/config/stash/config.yml")
|
|
text = path.read_text()
|
|
text = re.sub(r'^dangerous_allow_public_without_auth:.*$', 'dangerous_allow_public_without_auth: "true"', text, flags=re.M)
|
|
text = re.sub(r'^username:.*$', 'username: ""', text, flags=re.M)
|
|
text = re.sub(r'^password:.*$', 'password: ""', text, flags=re.M)
|
|
text = re.sub(r'^security_tripwire_accessed_from_public_internet:.*\n', '', text, flags=re.M)
|
|
path.write_text(text)
|
|
print(" dangerous_allow_public_without_auth=true, cleared username/password")
|
|
PY
|
|
docker restart stash >/dev/null
|
|
|
|
echo "=== deluge: bypass web login (Authentik at edge; patch re-applies on recreate) ==="
|
|
if docker exec deluge grep -q 'homelab external auth' /lsiopy/lib/python3.12/site-packages/deluge/ui/web/auth.py 2>/dev/null; then
|
|
echo " already patched"
|
|
else
|
|
docker cp /tmp/patch-deluge-auth.py deluge:/tmp/patch-deluge-auth.py
|
|
docker exec deluge python3 /tmp/patch-deluge-auth.py
|
|
docker restart deluge >/dev/null
|
|
echo " patched and restarted"
|
|
fi
|
|
|
|
echo "=== done (tautulli untouched) ==="
|