Add SABnzbd for Usenet NZB search and download
Wire Newshosting/Tweaknews via secrets-driven configure script, NZBgeek through Prowlarr, and /data/usenet paths for hardlinks with the Arrs.
This commit is contained in:
parent
0601de7217
commit
07ae1c0c71
8 changed files with 223 additions and 1 deletions
|
|
@ -73,6 +73,9 @@ OPENHANDS_MODEL=openai/local
|
||||||
FLARESOLVERR_LOG_LEVEL=info
|
FLARESOLVERR_LOG_LEVEL=info
|
||||||
FLARESOLVERR_CAPTCHA_SOLVER=none
|
FLARESOLVERR_CAPTCHA_SOLVER=none
|
||||||
|
|
||||||
|
# SABnzbd (Usenet) — credentials in secrets/.env, not here
|
||||||
|
SABNZBD_PORT=8085
|
||||||
|
|
||||||
# Forgejo — self-hosted Git (web + SSH clone)
|
# Forgejo — self-hosted Git (web + SSH clone)
|
||||||
FORGEJO_HTTP_PORT=3002
|
FORGEJO_HTTP_PORT=3002
|
||||||
FORGEJO_SSH_PORT=2222
|
FORGEJO_SSH_PORT=2222
|
||||||
|
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -12,6 +12,8 @@ models/bonsai/*.gguf
|
||||||
models/bonsai/*.partial
|
models/bonsai/*.partial
|
||||||
.openhands-state/
|
.openhands-state/
|
||||||
# secrets / local runtime
|
# secrets / local runtime
|
||||||
|
secrets/*
|
||||||
|
!secrets/.env.example
|
||||||
**/wg0.conf
|
**/wg0.conf
|
||||||
wireguard/wg0.conf
|
wireguard/wg0.conf
|
||||||
workspace/*
|
workspace/*
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ for the **Beelink SER5 PRO** (Ryzen 7 7735HS + Radeon 680M).
|
||||||
| Radarr | http://host:7878 | Movies |
|
| Radarr | http://host:7878 | Movies |
|
||||||
| Bazarr | http://host:6767 | Subtitles |
|
| Bazarr | http://host:6767 | Subtitles |
|
||||||
| Lidarr | http://host:8686 | Music |
|
| Lidarr | http://host:8686 | Music |
|
||||||
|
| SABnzbd | http://host:8085 | Usenet NZB downloads |
|
||||||
| **Forgejo** | http://host:3002 | Self-hosted Git (SSH :2222) |
|
| **Forgejo** | http://host:3002 | Self-hosted Git (SSH :2222) |
|
||||||
| **Open WebUI** | http://host:3000 | Chat UI, RAG, tools, code interpreter |
|
| **Open WebUI** | http://host:3000 | Chat UI, RAG, tools, code interpreter |
|
||||||
| **Bonsai API** | http://host:8081/v1 | OpenAI-compatible llama-server |
|
| **Bonsai API** | http://host:8081/v1 | OpenAI-compatible llama-server |
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,7 @@ ufw_lan_tcp_ports:
|
||||||
- { port: 3001, comment: "OpenHands (optional)" }
|
- { port: 3001, comment: "OpenHands (optional)" }
|
||||||
- { port: 3002, comment: "Forgejo HTTP" }
|
- { port: 3002, comment: "Forgejo HTTP" }
|
||||||
- { port: 2222, comment: "Forgejo Git SSH" }
|
- { port: 2222, comment: "Forgejo Git SSH" }
|
||||||
|
- { port: 8085, comment: "SABnzbd" }
|
||||||
|
|
||||||
# WireGuard peer hostname for gluetun-endpoint-watch
|
# WireGuard peer hostname for gluetun-endpoint-watch
|
||||||
wireguard_endpoint_host: las-183-wg.whiskergalaxy.com
|
wireguard_endpoint_host: las-183-wg.whiskergalaxy.com
|
||||||
|
|
@ -231,3 +232,7 @@ media_subdirs:
|
||||||
- torrents/movies
|
- torrents/movies
|
||||||
- torrents/tv
|
- torrents/tv
|
||||||
- torrents/music
|
- torrents/music
|
||||||
|
- usenet/incomplete
|
||||||
|
- usenet/complete/movies
|
||||||
|
- usenet/complete/tv
|
||||||
|
- usenet/complete/music
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ name: arr-stack
|
||||||
# Arr stack
|
# Arr stack
|
||||||
# gluetun WireGuard VPN client + firewall killswitch
|
# gluetun WireGuard VPN client + firewall killswitch
|
||||||
# qbittorrent torrent client, lives INSIDE gluetun's network namespace
|
# qbittorrent torrent client, lives INSIDE gluetun's network namespace
|
||||||
# prowlarr indexer manager
|
# prowlarr indexer manager (torrents + NZB/Usenet indexers)
|
||||||
|
# sabnzbd Usenet NZB download client (Newshosting, Tweaknews, …)
|
||||||
# sonarr TV radarr movies bazarr subtitles
|
# sonarr TV radarr movies bazarr subtitles
|
||||||
# jellyfin media server
|
# jellyfin media server
|
||||||
#
|
#
|
||||||
|
|
@ -80,6 +81,21 @@ services:
|
||||||
- ${CONFIG_DIR}/qbittorrent:/config
|
- ${CONFIG_DIR}/qbittorrent:/config
|
||||||
- ${DATA_DIR}:/data # single shared tree -> hardlinks
|
- ${DATA_DIR}:/data # single shared tree -> hardlinks
|
||||||
|
|
||||||
|
# ---------------------------------------------------------- usenet / NZB #
|
||||||
|
# SABnzbd talks to Usenet providers over SSL (no VPN required).
|
||||||
|
# Incomplete + complete under /data/usenet so Sonarr/Radarr can hardlink.
|
||||||
|
sabnzbd:
|
||||||
|
image: lscr.io/linuxserver/sabnzbd:latest
|
||||||
|
container_name: sabnzbd
|
||||||
|
restart: unless-stopped
|
||||||
|
networks: [arr-net]
|
||||||
|
ports:
|
||||||
|
- "${SABNZBD_PORT:-8085}:8080"
|
||||||
|
environment: *arr-env
|
||||||
|
volumes:
|
||||||
|
- ${CONFIG_DIR}/sabnzbd:/config
|
||||||
|
- ${DATA_DIR}:/data
|
||||||
|
|
||||||
# -------------------------------------------------------------- indexers #
|
# -------------------------------------------------------------- indexers #
|
||||||
prowlarr:
|
prowlarr:
|
||||||
image: lscr.io/linuxserver/prowlarr:latest
|
image: lscr.io/linuxserver/prowlarr:latest
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ LAN URLs (UFW allows **`192.168.8.0/24`**). Replace host if needed.
|
||||||
| Radarr | http://192.168.8.123:7878 |
|
| Radarr | http://192.168.8.123:7878 |
|
||||||
| Bazarr | http://192.168.8.123:6767 |
|
| Bazarr | http://192.168.8.123:6767 |
|
||||||
| Lidarr | http://192.168.8.123:8686 |
|
| Lidarr | http://192.168.8.123:8686 |
|
||||||
|
| SABnzbd | http://192.168.8.123:8085 |
|
||||||
| Open WebUI | http://192.168.8.123:3000 |
|
| Open WebUI | http://192.168.8.123:3000 |
|
||||||
| Bonsai API | http://192.168.8.123:8081/v1 |
|
| Bonsai API | http://192.168.8.123:8081/v1 |
|
||||||
| OpenHands | http://192.168.8.123:3001 |
|
| OpenHands | http://192.168.8.123:3001 |
|
||||||
|
|
|
||||||
167
scripts/configure-usenet.sh
Executable file
167
scripts/configure-usenet.sh
Executable file
|
|
@ -0,0 +1,167 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Bootstrap SABnzbd folders + Usenet servers from secrets/.env
|
||||||
|
# Run on the stack host after: docker compose up -d sabnzbd
|
||||||
|
#
|
||||||
|
# ./scripts/configure-usenet.sh
|
||||||
|
# SECRETS_FILE=./secrets/.env SAB_URL=http://127.0.0.1:8085 ./scripts/configure-usenet.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
STACK_DIR="${STACK_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
||||||
|
SECRETS_FILE="${SECRETS_FILE:-$STACK_DIR/secrets/.env}"
|
||||||
|
SAB_URL="${SAB_URL:-http://127.0.0.1:8085}"
|
||||||
|
|
||||||
|
log() { echo "[configure-usenet] $*"; }
|
||||||
|
die() { log "ERROR: $*"; exit 1; }
|
||||||
|
|
||||||
|
[[ -f "$SECRETS_FILE" ]] || die "missing $SECRETS_FILE (see secrets/.env.example)"
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source "$SECRETS_FILE"
|
||||||
|
set +a
|
||||||
|
|
||||||
|
# Accept both clean names and the keys already in secrets/.env
|
||||||
|
NZBGEEK_API_KEY="${NZBGEEK_API_KEY:-${NZBKEEPKEY:-}}"
|
||||||
|
NZBGEEK_URL="${NZBGEEK_URL:-${NZBGEEKAPI:-https://api.nzbgeek.info/}}"
|
||||||
|
NEWSHOSTING_HOST="${NEWSHOSTING_HOST:-${NEWSHOSTINGAPI:-news.newshosting.com}}"
|
||||||
|
NEWSHOSTING_PORT="${NEWSHOSTING_PORT:-${NEWSHOSTINGSSLPORT:-563}}"
|
||||||
|
[[ "$NEWSHOSTING_PORT" == "653" ]] && NEWSHOSTING_PORT=563 # common typo
|
||||||
|
NEWSHOSTING_USER="${NEWSHOSTING_USER:-${NEWSHOSTINGUSER:-}}"
|
||||||
|
NEWSHOSTING_PASS="${NEWSHOSTING_PASS:-${HNEWSHOSTINGPASS:-${NEWSHOSTINGPASS:-}}}"
|
||||||
|
NEWSHOSTING_CONNECTIONS="${NEWSHOSTING_CONNECTIONS:-20}"
|
||||||
|
|
||||||
|
TWEAKNEWS_HOST="${TWEAKNEWS_HOST:-news.tweaknews.eu}"
|
||||||
|
TWEAKNEWS_PORT="${TWEAKNEWS_PORT:-563}"
|
||||||
|
TWEAKNEWS_USER="${TWEAKNEWS_USER:-${TWEAKNEWSUSER:-}}"
|
||||||
|
TWEAKNEWS_PASS="${TWEAKNEWS_PASS:-${TWEAKNEWSPASS:-}}"
|
||||||
|
TWEAKNEWS_CONNECTIONS="${TWEAKNEWS_CONNECTIONS:-10}"
|
||||||
|
|
||||||
|
find_api_key() {
|
||||||
|
local f
|
||||||
|
for f in \
|
||||||
|
"${CONFIG_DIR:-$STACK_DIR/config}/sabnzbd/sabnzbd.ini" \
|
||||||
|
"$STACK_DIR/config/sabnzbd/sabnzbd.ini" \
|
||||||
|
"/opt/stack/config/sabnzbd/sabnzbd.ini" \
|
||||||
|
; do
|
||||||
|
if [[ -f "$f" ]]; then
|
||||||
|
grep -E '^api_key[[:space:]]*=' "$f" | head -1 | cut -d= -f2- | tr -d '[:space:]'
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# docker exec fallback
|
||||||
|
if command -v docker >/dev/null 2>&1; then
|
||||||
|
docker exec sabnzbd sh -c 'grep -E "^api_key" /config/sabnzbd.ini 2>/dev/null | head -1' \
|
||||||
|
| cut -d= -f2- | tr -d '[:space:]' || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Waiting for SABnzbd at $SAB_URL ..."
|
||||||
|
for i in $(seq 1 90); do
|
||||||
|
if curl -fsS "$SAB_URL/api?mode=version&output=json" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
[[ $i -eq 90 ]] && die "SABnzbd not reachable — is the container up? (docker compose up -d sabnzbd)"
|
||||||
|
done
|
||||||
|
|
||||||
|
api_key="$(find_api_key)"
|
||||||
|
[[ -n "$api_key" ]] || die "no api_key yet — open $SAB_URL once to finish first-run, then re-run this script"
|
||||||
|
|
||||||
|
sab_set() {
|
||||||
|
# set_config: section + keyword + value OR servers with name= + fields
|
||||||
|
curl -fsS -G "${SAB_URL}/api" \
|
||||||
|
--data-urlencode "mode=set_config" \
|
||||||
|
--data-urlencode "apikey=${api_key}" \
|
||||||
|
--data-urlencode "output=json" \
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Folders: incomplete + complete under /data/usenet"
|
||||||
|
sab_set --data-urlencode "section=misc" --data-urlencode "keyword=download_dir" \
|
||||||
|
--data-urlencode "value=/data/usenet/incomplete" >/dev/null
|
||||||
|
sab_set --data-urlencode "section=misc" --data-urlencode "keyword=complete_dir" \
|
||||||
|
--data-urlencode "value=/data/usenet/complete" >/dev/null
|
||||||
|
|
||||||
|
# Relative category folders under complete_dir
|
||||||
|
add_category() {
|
||||||
|
local name="$1"
|
||||||
|
sab_set \
|
||||||
|
--data-urlencode "section=categories" \
|
||||||
|
--data-urlencode "name=${name}" \
|
||||||
|
--data-urlencode "dir=${name}" \
|
||||||
|
--data-urlencode "pp=3" \
|
||||||
|
>/dev/null || true
|
||||||
|
}
|
||||||
|
add_category movies
|
||||||
|
add_category tv
|
||||||
|
add_category music
|
||||||
|
|
||||||
|
add_server() {
|
||||||
|
local name="$1" host="$2" port="$3" user="$4" pass="$5" conns="$6"
|
||||||
|
if [[ -z "$user" || -z "$pass" ]]; then
|
||||||
|
log "skip server '$name' (missing user/password in secrets)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
log "Usenet server: $name → $host:$port (ssl, ${conns} conn)"
|
||||||
|
# https://sabnzbd.org/wiki/configuration/5.0/api — servers via set_config + name=
|
||||||
|
sab_set \
|
||||||
|
--data-urlencode "section=servers" \
|
||||||
|
--data-urlencode "name=${name}" \
|
||||||
|
--data-urlencode "displayline=${name}" \
|
||||||
|
--data-urlencode "host=${host}" \
|
||||||
|
--data-urlencode "port=${port}" \
|
||||||
|
--data-urlencode "username=${user}" \
|
||||||
|
--data-urlencode "password=${pass}" \
|
||||||
|
--data-urlencode "connections=${conns}" \
|
||||||
|
--data-urlencode "ssl=1" \
|
||||||
|
--data-urlencode "enable=1" \
|
||||||
|
--data-urlencode "priority=0" \
|
||||||
|
--data-urlencode "timeout=60" \
|
||||||
|
>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
add_server "Newshosting" \
|
||||||
|
"$NEWSHOSTING_HOST" "$NEWSHOSTING_PORT" \
|
||||||
|
"$NEWSHOSTING_USER" "$NEWSHOSTING_PASS" \
|
||||||
|
"$NEWSHOSTING_CONNECTIONS"
|
||||||
|
|
||||||
|
add_server "Tweaknews" \
|
||||||
|
"$TWEAKNEWS_HOST" "$TWEAKNEWS_PORT" \
|
||||||
|
"$TWEAKNEWS_USER" "$TWEAKNEWS_PASS" \
|
||||||
|
"$TWEAKNEWS_CONNECTIONS"
|
||||||
|
|
||||||
|
log "Restart SABnzbd to pick up servers"
|
||||||
|
if command -v docker >/dev/null 2>&1 && docker ps --format '{{.Names}}' | grep -qx sabnzbd; then
|
||||||
|
docker restart sabnzbd >/dev/null
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
log ""
|
||||||
|
log "=== SABnzbd ready ==="
|
||||||
|
log "UI: $SAB_URL"
|
||||||
|
log "API: (Config → General) — use this key in Prowlarr/*arr"
|
||||||
|
log ""
|
||||||
|
log "=== Prowlarr (NZBgeek) ==="
|
||||||
|
log "Indexers → Add Indexer → NZBgeek"
|
||||||
|
log " URL: ${NZBGEEK_URL}"
|
||||||
|
if [[ -n "$NZBGEEK_API_KEY" ]]; then
|
||||||
|
log " API Key: ${NZBGEEK_API_KEY}"
|
||||||
|
else
|
||||||
|
log " API Key: (set NZBKEEPKEY or NZBGEEK_API_KEY in secrets/.env)"
|
||||||
|
fi
|
||||||
|
log ""
|
||||||
|
log "Download Clients → Add → SABnzbd"
|
||||||
|
log " Host: sabnzbd Port: 8080 API Key: (from SABnzbd)"
|
||||||
|
log " (sync to apps so Sonarr/Radarr get SABnzbd too, or add per-app)"
|
||||||
|
log ""
|
||||||
|
log "=== Sonarr / Radarr / Lidarr ==="
|
||||||
|
log "Download Clients → SABnzbd → Host sabnzbd Port 8080"
|
||||||
|
log " Category: tv | movies | music"
|
||||||
|
log "Root folders still /data/media/{tv,movies,music} (hardlinks on same /data)"
|
||||||
|
log ""
|
||||||
|
if [[ -z "$TWEAKNEWS_USER" || -z "$TWEAKNEWS_PASS" ]]; then
|
||||||
|
log "NOTE: Tweaknews user/pass not in secrets — add TWEAKNEWS_USER / TWEAKNEWS_PASS and re-run."
|
||||||
|
fi
|
||||||
27
secrets/.env.example
Normal file
27
secrets/.env.example
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Copy to secrets/.env and fill in. NEVER commit secrets/.env
|
||||||
|
# Used by scripts/configure-usenet.sh and as a personal password vault.
|
||||||
|
|
||||||
|
# --- NZBgeek (indexer — wire in Prowlarr) ---
|
||||||
|
NZBGEEK_USERNAME=
|
||||||
|
NZBGEEK_EMAIL=
|
||||||
|
# API key from nzbgeek.info account (not the base URL)
|
||||||
|
NZBGEEK_API_KEY=
|
||||||
|
# Optional base URL (default https://api.nzbgeek.info/)
|
||||||
|
NZBGEEK_URL=https://api.nzbgeek.info/
|
||||||
|
|
||||||
|
# --- Newshosting (Usenet provider — SABnzbd server) ---
|
||||||
|
NEWSHOSTING_HOST=news.newshosting.com
|
||||||
|
NEWSHOSTING_PORT=563
|
||||||
|
NEWSHOSTING_SSL=1
|
||||||
|
NEWSHOSTING_USER=
|
||||||
|
NEWSHOSTING_PASS=
|
||||||
|
# Connections: start ~20 (plan-dependent)
|
||||||
|
NEWSHOSTING_CONNECTIONS=20
|
||||||
|
|
||||||
|
# --- Tweaknews (Usenet provider / fill-in block) ---
|
||||||
|
TWEAKNEWS_HOST=news.tweaknews.eu
|
||||||
|
TWEAKNEWS_PORT=563
|
||||||
|
TWEAKNEWS_SSL=1
|
||||||
|
TWEAKNEWS_USER=
|
||||||
|
TWEAKNEWS_PASS=
|
||||||
|
TWEAKNEWS_CONNECTIONS=10
|
||||||
Loading…
Add table
Add a link
Reference in a new issue