stack/scripts/configure-usenet.sh
tim 3bf1726a99 Centralize demo config in .env and add bootstrap-stack.sh
Expand .env.example with ports, AI, Usenet, WireGuard, demo logins, and
bootstrap flags. One script creates dirs, downloads the model, starts
compose, heals gluetun, and configures SABnzbd from the same file.
2026-07-22 13:06:08 -07:00

177 lines
6.3 KiB
Bash
Executable file

#!/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; }
# Prefer secrets/.env; fall back to root .env (tech-demo: everything in one file)
if [[ ! -f "$SECRETS_FILE" && -f "$STACK_DIR/.env" ]]; then
SECRETS_FILE="$STACK_DIR/.env"
log "using $SECRETS_FILE (no secrets/.env)"
fi
[[ -f "$SECRETS_FILE" ]] || die "missing $SECRETS_FILE (see secrets/.env.example or .env.example)"
# shellcheck disable=SC1090
set -a
# shellcheck disable=SC1091
source "$SECRETS_FILE"
set +a
# Accept clean names AND the variable names used in secrets/.env
# NZBgeek
NZBGEEK_API_KEY="${NZBGEEK_API_KEY:-${NZBKEEPKEY:-${NZBGEEKKEY:-}}}"
NZBGEEK_URL="${NZBGEEK_URL:-${NZBGEEKAPI:-https://api.nzbgeek.info/}}"
NZBGEEK_USERNAME="${NZBGEEK_USERNAME:-${NZBGEEKUSERNAME:-}}"
# Newshosting (provider host often in NEWSHOSTINGAPI)
NEWSHOSTING_HOST="${NEWSHOSTING_HOST:-${NEWSHOSTINGAPI:-news.newshosting.com}}"
NEWSHOSTING_PORT="${NEWSHOSTING_PORT:-${NEWSHOSTINGSSLPORT:-563}}"
[[ "$NEWSHOSTING_PORT" == "653" ]] && NEWSHOSTING_PORT=563 # common typo for 563
NEWSHOSTING_USER="${NEWSHOSTING_USER:-${NEWSHOSTINGUSER:-}}"
NEWSHOSTING_PASS="${NEWSHOSTING_PASS:-${HNEWSHOSTINGPASS:-${NEWSHOSTINGPASS:-${NEWSHOSTINGPASSWORD:-}}}}"
NEWSHOSTING_CONNECTIONS="${NEWSHOSTING_CONNECTIONS:-${NEWSHOSTINGCONNECTIONS:-20}}"
# Tweaknews (secrets use TWEAKNEWSLOGIN / TWEAKNEWSPASSWORD / TWEAKNEWSAPI as host)
TWEAKNEWS_HOST="${TWEAKNEWS_HOST:-${TWEAKNEWSAPI:-${TWEAKNEWSHOST:-news.tweaknews.eu}}}"
TWEAKNEWS_PORT="${TWEAKNEWS_PORT:-${TWEAKNEWSSSLPORT:-${TWEAKNEWSPORT:-563}}}"
TWEAKNEWS_USER="${TWEAKNEWS_USER:-${TWEAKNEWSLOGIN:-${TWEAKNEWSUSER:-${TWEAKNEWSUSERNAME:-}}}}"
TWEAKNEWS_PASS="${TWEAKNEWS_PASS:-${TWEAKNEWSPASSWORD:-${TWEAKNEWSPASS:-}}}"
TWEAKNEWS_CONNECTIONS="${TWEAKNEWS_CONNECTIONS:-${TWEAKNEWSCONNECTIONS:-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