#!/usr/bin/env bash # Discarr native installer # Installs Node.js 18+, ffmpeg, HandBrake CLI, and DVD libraries, # then optionally registers Discarr as a systemd service. # # Supported: Ubuntu/Debian (apt), Fedora/RHEL (dnf), Arch (pacman), macOS (brew) # Run as root or with sudo. set -euo pipefail DISCARR_INSTALL_DIR="${DISCARR_INSTALL_DIR:-/opt/discarr}" DISCARR_USER="${DISCARR_USER:-discarr}" DISCARR_PORT="${DISCARR_PORT:-8603}" REGISTER_SERVICE="${REGISTER_SERVICE:-ask}" # ask | yes | no # ── Colours ──────────────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' info() { echo -e "${CYAN}→${NC} $*"; } success() { echo -e "${GREEN}✓${NC} $*"; } warn() { echo -e "${YELLOW}⚠${NC} $*"; } die() { echo -e "${RED}✗${NC} $*" >&2; exit 1; } # ── Root check ───────────────────────────────────────────────────────────────── [[ $EUID -eq 0 ]] || die "Run as root or with sudo." SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # ── Detect package manager ───────────────────────────────────────────────────── detect_pm() { if command -v apt-get &>/dev/null; then echo "apt" elif command -v dnf &>/dev/null; then echo "dnf" elif command -v pacman &>/dev/null; then echo "pacman" elif command -v brew &>/dev/null; then echo "brew" else die "Unsupported package manager. Install deps manually and re-run with SKIP_DEPS=1." fi } PM=$(detect_pm) info "Package manager: $PM" # ── Node.js 18+ ──────────────────────────────────────────────────────────────── install_node() { if command -v node &>/dev/null; then local ver ver=$(node --version | sed 's/v//' | cut -d. -f1) if [[ $ver -ge 18 ]]; then success "Node.js $(node --version) already installed." return fi warn "Node.js $ver found but >=18 required. Upgrading via NodeSource." fi info "Installing Node.js 20 LTS via NodeSource..." case $PM in apt) curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs ;; dnf) curl -fsSL https://rpm.nodesource.com/setup_20.x | bash - dnf install -y nodejs ;; pacman) pacman -Sy --noconfirm nodejs npm ;; brew) brew install node@20 brew link --overwrite node@20 ;; esac success "Node.js $(node --version) installed." } # ── ffmpeg + ffprobe ─────────────────────────────────────────────────────────── install_ffmpeg() { if command -v ffmpeg &>/dev/null && command -v ffprobe &>/dev/null; then success "ffmpeg $(ffmpeg -version 2>&1 | head -1 | awk '{print $3}') already installed." return fi info "Installing ffmpeg..." case $PM in apt) apt-get install -y ffmpeg ;; dnf) # ffmpeg is in RPM Fusion — enable if not already if ! dnf repolist enabled | grep -q rpmfusion-free; then dnf install -y \ "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" \ "https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm" fi dnf install -y ffmpeg ;; pacman) pacman -Sy --noconfirm ffmpeg ;; brew) brew install ffmpeg ;; esac success "ffmpeg installed." } # ── HandBrake CLI (optional but recommended for HEVC encoding) ───────────────── install_handbrake() { if command -v HandBrakeCLI &>/dev/null || command -v handbrake-cli &>/dev/null; then success "HandBrake CLI already installed." return fi info "Installing HandBrake CLI..." case $PM in apt) # handbrake-cli is in universe on Ubuntu 20.04+ apt-get install -y handbrake-cli 2>/dev/null || { warn "handbrake-cli not found in apt — skipping. You can install it manually:" warn " https://handbrake.fr/downloads.php" } ;; dnf) # Requires RPM Fusion (already enabled for ffmpeg) dnf install -y HandBrake-cli 2>/dev/null || warn "HandBrake-cli not found — skipping." ;; pacman) pacman -Sy --noconfirm handbrake-cli 2>/dev/null || warn "handbrake-cli not found — skipping." ;; brew) brew install handbrake 2>/dev/null || warn "HandBrake not found in brew — skipping." ;; esac } # ── DVD libraries (libdvdcss, libdvdread, libdvdnav) ────────────────────────── install_dvd_libs() { info "Installing DVD libraries (libdvdcss, libdvdread, libdvdnav)..." case $PM in apt) apt-get install -y libdvd-pkg libdvdread8 libdvdnav4 2>/dev/null || \ apt-get install -y libdvdread-dev libdvdnav-dev 2>/dev/null || true # libdvd-pkg builds libdvdcss from source (legal in most jurisdictions) if dpkg -l libdvd-pkg &>/dev/null 2>&1; then DEBIAN_FRONTEND=noninteractive dpkg-reconfigure libdvd-pkg 2>/dev/null || true fi ;; dnf) if ! dnf repolist enabled | grep -q rpmfusion; then warn "RPM Fusion not enabled — skipping libdvdcss. Enable RPM Fusion and run: dnf install libdvdcss" else dnf install -y libdvdcss libdvdread libdvdnav 2>/dev/null || true fi ;; pacman) # libdvdcss is in extra; others in core pacman -Sy --noconfirm libdvdcss libdvdread libdvdnav 2>/dev/null || true ;; brew) brew install libdvdcss 2>/dev/null || warn "libdvdcss not available via brew — skipping." ;; esac success "DVD libraries done (some may need manual install — see README)." } # ── Install Discarr app files ────────────────────────────────────────────────── install_app() { info "Installing Discarr to $DISCARR_INSTALL_DIR..." mkdir -p "$DISCARR_INSTALL_DIR" cp -r "$SCRIPT_DIR"/server.js "$SCRIPT_DIR"/scanner.js "$SCRIPT_DIR"/public \ "$SCRIPT_DIR"/scripts "$SCRIPT_DIR"/api-keys.conf.example \ "$DISCARR_INSTALL_DIR"/ # Create a launcher wrapper cat > /usr/local/bin/discarr </dev/null; then useradd -r -s /bin/false -d "$DISCARR_INSTALL_DIR" "$DISCARR_USER" chown -R "$DISCARR_USER:$DISCARR_USER" "$DISCARR_INSTALL_DIR" fi cat > "$SERVICE_FILE" <