Files
music-orchestrator/deploy.sh
2026-02-22 23:18:57 -05:00

174 lines
7.0 KiB
Bash

#!/usr/bin/env bash
# Music Orchestrator — production deploy script for Ubuntu
# Run as a regular user with sudo access. Do NOT run as root.
#
# First run: bash deploy.sh
# Update: bash deploy.sh (re-run at any time — it's idempotent)
set -euo pipefail
# ── Config ─────────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/music-orchestrator"
SERVICE_NAME="music-orchestrator"
SERVICE_USER="$(whoami)"
NGINX_SITE="music-orchestrator"
# Where your Plex library lives on this machine.
# Can be changed later by editing $INSTALL_DIR/backend/.env
DEFAULT_MUSIC_DIR="$HOME/Music"
# Colours
GREEN="\033[0;32m"; YELLOW="\033[0;33m"; RED="\033[0;31m"; NC="\033[0m"
info() { echo -e "${GREEN}[+]${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
section() { echo -e "\n${GREEN}── $* ──────────────────────────────────────────────────${NC}"; }
# ── Checks ─────────────────────────────────────────────────────────────────────
section "Checking prerequisites"
if [[ $EUID -eq 0 ]]; then
echo -e "${RED}[✗]${NC} Do not run this script as root. Run as your regular user."
exit 1
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ ! -f "$SCRIPT_DIR/backend/main.py" ]]; then
echo -e "${RED}[✗]${NC} Run this script from the music-orchestrator project root."
exit 1
fi
# ── System dependencies ────────────────────────────────────────────────────────
section "Installing system packages"
sudo apt-get update -qq
sudo apt-get install -y \
python3 python3-pip python3-venv \
ffmpeg \
nginx \
nodejs npm \
--no-install-recommends
info "System packages ready"
# ── Install directory ──────────────────────────────────────────────────────────
section "Setting up install directory ($INSTALL_DIR)"
sudo mkdir -p "$INSTALL_DIR"
sudo chown "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR"
# Sync project files (rsync excludes dev artifacts)
rsync -a --delete \
--exclude='.git' \
--exclude='node_modules' \
--exclude='frontend/dist' \
--exclude='backend/venv' \
--exclude='backend/__pycache__' \
--exclude='backend/tmp' \
--exclude='backend/Music' \
--exclude='.env' \
"$SCRIPT_DIR/" "$INSTALL_DIR/"
info "Project files synced to $INSTALL_DIR"
# ── Backend: Python virtualenv ─────────────────────────────────────────────────
section "Setting up Python virtual environment"
python3 -m venv "$INSTALL_DIR/backend/venv"
"$INSTALL_DIR/backend/venv/bin/pip" install --quiet --upgrade pip
"$INSTALL_DIR/backend/venv/bin/pip" install --quiet -r "$INSTALL_DIR/backend/requirements.txt"
info "Python dependencies installed"
# ── Backend: .env ──────────────────────────────────────────────────────────────
section "Configuring backend .env"
ENV_FILE="$INSTALL_DIR/backend/.env"
if [[ ! -f "$ENV_FILE" ]]; then
# First install — prompt for music dir
echo ""
warn "Where is your Plex music library? (press Enter for default: $DEFAULT_MUSIC_DIR)"
read -r -p " Music directory: " MUSIC_DIR_INPUT
MUSIC_DIR="${MUSIC_DIR_INPUT:-$DEFAULT_MUSIC_DIR}"
mkdir -p "$MUSIC_DIR"
cat > "$ENV_FILE" <<EOF
# Path to your Plex music library folder
MUSIC_DIR=$MUSIC_DIR
# Temp directory for in-progress downloads (auto-cleaned)
TEMP_DIR=/tmp/music-orchestrator
EOF
info ".env created — MUSIC_DIR=$MUSIC_DIR"
else
warn ".env already exists at $ENV_FILE — skipping (edit manually to change settings)"
fi
# Ensure tmp dir exists
TEMP_DIR=$(grep '^TEMP_DIR' "$ENV_FILE" 2>/dev/null | cut -d= -f2 || echo "/tmp/music-orchestrator")
mkdir -p "$TEMP_DIR"
# ── Frontend: build ────────────────────────────────────────────────────────────
section "Building React frontend"
cd "$INSTALL_DIR/frontend"
npm install --silent
npm run build
info "Frontend built to $INSTALL_DIR/frontend/dist"
# ── nginx ──────────────────────────────────────────────────────────────────────
section "Configuring nginx"
sudo cp "$INSTALL_DIR/nginx.conf" "/etc/nginx/sites-available/$NGINX_SITE"
# Enable the site, remove default if present
sudo ln -sf "/etc/nginx/sites-available/$NGINX_SITE" "/etc/nginx/sites-enabled/$NGINX_SITE"
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t # validate config before reloading
sudo systemctl enable nginx --quiet
sudo systemctl reload nginx
info "nginx configured and reloaded"
# ── systemd service ────────────────────────────────────────────────────────────
section "Installing systemd service"
# The service uses %i (instance name) for User= — we pass the username as the instance
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}@.service"
sudo cp "$INSTALL_DIR/music-orchestrator.service" "$SERVICE_FILE"
sudo systemctl daemon-reload
sudo systemctl enable "${SERVICE_NAME}@${SERVICE_USER}" --quiet
sudo systemctl restart "${SERVICE_NAME}@${SERVICE_USER}"
# Wait a moment and check it started cleanly
sleep 2
if systemctl is-active --quiet "${SERVICE_NAME}@${SERVICE_USER}"; then
info "Service started successfully"
else
echo -e "${RED}[✗]${NC} Service failed to start. Check logs with:"
echo " journalctl -u ${SERVICE_NAME}@${SERVICE_USER} -n 50"
exit 1
fi
# ── Done ───────────────────────────────────────────────────────────────────────
section "Deploy complete"
LOCAL_IP=$(hostname -I | awk '{print $1}')
echo ""
echo -e " ${GREEN}Music Orchestrator is running at:${NC}"
echo -e " http://$LOCAL_IP"
echo ""
echo " Useful commands:"
echo " View logs: journalctl -u ${SERVICE_NAME}@${SERVICE_USER} -f"
echo " Restart API: sudo systemctl restart ${SERVICE_NAME}@${SERVICE_USER}"
echo " Edit config: nano $ENV_FILE"
echo ""
echo " To update after code changes: just re-run bash deploy.sh"
echo ""