#!/bin/bash # Linux service installation script for Media Server set -e SERVICE_NAME="media-server" INSTALL_DIR="/opt/media-server" SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}@.service" CURRENT_USER=$(whoami) # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color echo_info() { echo -e "${GREEN}[INFO]${NC} $1" } echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } echo_error() { echo -e "${RED}[ERROR]${NC} $1" } check_root() { if [[ $EUID -ne 0 ]]; then echo_error "This script must be run as root (use sudo)" exit 1 fi } install_dependencies() { echo_info "Installing system dependencies..." if command -v apt-get &> /dev/null; then apt-get update apt-get install -y python3 python3-pip python3-venv python3-dbus python3-gi libdbus-1-dev libglib2.0-dev elif command -v dnf &> /dev/null; then dnf install -y python3 python3-pip python3-dbus python3-gobject dbus-devel glib2-devel elif command -v pacman &> /dev/null; then pacman -S --noconfirm python python-pip python-dbus python-gobject else echo_warn "Unknown package manager. Please install dependencies manually:" echo " - python3, python3-pip, python3-venv" echo " - python3-dbus, python3-gi" echo " - libdbus-1-dev, libglib2.0-dev" fi } install_service() { echo_info "Installing Media Server..." # Create installation directory mkdir -p "$INSTALL_DIR" # Resolve the source-tree root (two levels up from this script: # media_server/service/install_linux.sh → repo root). SOURCE_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" # Copy the source tree (pyproject.toml + media_server/ package) cp -r "$SOURCE_ROOT/." "$INSTALL_DIR/" # Create virtual environment echo_info "Creating Python virtual environment..." python3 -m venv "$INSTALL_DIR/venv" # Install Python dependencies from pyproject.toml (with linux extra). # cd into the install dir so pip resolves `.[linux]` against the local # pyproject — passing a path-with-extras (`$INSTALL_DIR[linux]`) trips # the requirement-spec parser on some pip versions. echo_info "Installing Python dependencies..." "$INSTALL_DIR/venv/bin/pip" install --upgrade pip (cd "$INSTALL_DIR" && "$INSTALL_DIR/venv/bin/pip" install ".[linux]") # Install systemd service file (templated unit) echo_info "Installing systemd service..." cp "$INSTALL_DIR/media_server/service/media-server.service" "$SERVICE_FILE" # Reload systemd systemctl daemon-reload # Pre-create writable state dirs so the unit's ReadWritePaths grant # actually has something to grant. sudo -u "$SUDO_USER" mkdir -p \ "/home/$SUDO_USER/.config/media-server" \ "/home/$SUDO_USER/.cache/media-server" # Generate config if not exists if [[ ! -f "/home/$SUDO_USER/.config/media-server/config.yaml" ]]; then echo_info "Generating configuration file..." sudo -u "$SUDO_USER" "$INSTALL_DIR/venv/bin/python" -m media_server.main --generate-config fi echo_info "Installation complete!" echo "" echo "To enable and start the service for user '$SUDO_USER':" echo " sudo systemctl enable ${SERVICE_NAME}@${SUDO_USER}" echo " sudo systemctl start ${SERVICE_NAME}@${SUDO_USER}" echo "" echo "To view the API token:" echo " cat ~/.config/media-server/config.yaml" echo "" echo "To view logs:" echo " journalctl -u ${SERVICE_NAME}@${SUDO_USER} -f" } uninstall_service() { echo_info "Uninstalling Media Server..." # Stop and disable service systemctl stop "${SERVICE_NAME}@*" 2>/dev/null || true systemctl disable "${SERVICE_NAME}@*" 2>/dev/null || true # Remove service file rm -f "$SERVICE_FILE" systemctl daemon-reload # Remove installation directory rm -rf "$INSTALL_DIR" echo_info "Uninstallation complete!" echo "Note: Configuration files in ~/.config/media-server were not removed." } show_usage() { echo "Usage: $0 [install|uninstall|deps]" echo "" echo "Commands:" echo " install Install the Media Server as a systemd service" echo " uninstall Remove the Media Server service" echo " deps Install system dependencies only" } # Main case "${1:-}" in install) check_root install_dependencies install_service ;; uninstall) check_root uninstall_service ;; deps) check_root install_dependencies ;; *) show_usage exit 1 ;; esac