jellyfin/setup_jellyfin.sh
2025-06-05 16:12:21 +00:00

297 lines
8.5 KiB
Bash

#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# GitHub repository information
REPO_URL="https://raw.githubusercontent.com/yourusername/jellyfin-docker/main"
echo -e "${GREEN}Jellyfin Docker Setup Script${NC}"
echo "--------------------------------"
# Function to detect GPU
detect_gpu() {
# Check for NVIDIA
if command -v nvidia-smi &> /dev/null; then
echo "nvidia"
return
fi
# Check for AMD GPU
if lspci | grep -i "vga.*amd" &> /dev/null; then
if lspci | grep -i "vga.*radeon" &> /dev/null; then
echo "amd-gpu"
else
echo "amd-apu"
fi
return
fi
# Check for Intel
if lspci | grep -i "vga.*intel" &> /dev/null; then
if [ -d "/sys/class/drm/card0/device/driver/module/drivers/pci:intel_arc" ]; then
echo "intel-arc"
else
echo "intel-igpu"
fi
return
fi
echo "none"
}
# Function to download file
download_file() {
local file=$1
echo -e "${YELLOW}Downloading ${file}...${NC}"
curl -sSL "${REPO_URL}/${file}" -o "${INSTALL_DIR}/${file}"
}
# Set installation directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_INSTALL_DIR="$SCRIPT_DIR"
# Ask for installation directory with better validation
setup_install_directory() {
echo -e "${YELLOW}Where would you like to install Jellyfin?${NC}"
echo -e "Default: ${GREEN}${DEFAULT_INSTALL_DIR}${NC}"
read -p "Install directory [$DEFAULT_INSTALL_DIR]: " INSTALL_DIR
INSTALL_DIR=${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}
# Check if directory exists and has existing configuration
if [ -f "${INSTALL_DIR}/docker-compose.yml" ] || \
[ -f "${INSTALL_DIR}/docker-compose.override.yml" ] || \
[ -f "${INSTALL_DIR}/.env" ]; then
echo -e "${RED}Warning: Jellyfin files already exist in ${INSTALL_DIR}${NC}"
read -p "Do you want to proceed and potentially overwrite? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting installation"
exit 1
fi
fi
# Create install directory if it doesn't exist
mkdir -p "$INSTALL_DIR"
# Check if directory is writable
if [ ! -w "$INSTALL_DIR" ]; then
echo -e "${RED}Error: Directory ${INSTALL_DIR} is not writable${NC}"
exit 1
fi
}
setup_install_directory
# Check for existing docker-compose.yml
if [ -f "${INSTALL_DIR}/docker-compose.yml" ]; then
echo -e "${RED}Warning: docker-compose.yml already exists in ${INSTALL_DIR}${NC}"
read -p "Do you want to overwrite it? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting installation"
exit 1
fi
fi
# Set up transcode cache
echo -e "${YELLOW}Where would you like to store the transcode cache?${NC}"
read -p "Transcode cache directory [/mnt/transcode]: " TRANSCODE_DIR
TRANSCODE_DIR=${TRANSCODE_DIR:-/mnt/transcode}
# Create transcode directory
sudo mkdir -p "$TRANSCODE_DIR"
sudo chown -R $USER:$USER "$TRANSCODE_DIR"
# Detect GPU
echo -e "${YELLOW}Detecting GPU...${NC}"
GPU_TYPE=$(detect_gpu)
case $GPU_TYPE in
"nvidia")
echo -e "${GREEN}NVIDIA GPU detected${NC}"
TRANSCODE_FILE="nvidia-transcoding.yml"
;;
"amd-gpu")
echo -e "${GREEN}AMD dedicated GPU detected${NC}"
TRANSCODE_FILE="amd-gpu.transcoding.yml"
;;
"amd-apu")
echo -e "${GREEN}AMD APU detected${NC}"
TRANSCODE_FILE="amd-apu.transcoding.yml"
;;
"intel-arc")
echo -e "${GREEN}Intel ARC detected${NC}"
TRANSCODE_FILE="intel-arc.transcoding.yml"
;;
"intel-igpu")
echo -e "${GREEN}Intel integrated GPU detected${NC}"
TRANSCODE_FILE="intel-igpu.transcoding.yml"
;;
*)
echo -e "${RED}No supported GPU detected${NC}"
echo "CPU transcoding will be used"
TRANSCODE_FILE="intel-igpu.transcoding.yml" # Default fallback
;;
esac
# Download required files
download_file "docker-compose.yml"
download_file "sample.env"
download_file "$TRANSCODE_FILE"
download_file "tonemapping.md"
# Create .env file from sample
cp "${INSTALL_DIR}/sample.env" "${INSTALL_DIR}/.env"
# Update .env file with transcode path
sed -i "s|TRANSCODE_CACHE=.*|TRANSCODE_CACHE=${TRANSCODE_DIR}|g" "${INSTALL_DIR}/.env"
# Get render group ID
RENDER_GID=$(getent group render | cut -d: -f3)
if [ ! -z "$RENDER_GID" ]; then
sed -i "s|RENDER_GID=.*|RENDER_GID=${RENDER_GID}|g" "${INSTALL_DIR}/.env"
fi
# Check for Docker and Docker Compose
check_prerequisites() {
echo -e "${YELLOW}Checking prerequisites...${NC}"
if ! command -v docker &> /dev/null; then
echo -e "${RED}Docker is not installed${NC}"
exit 1
fi
if ! docker compose version &> /dev/null; then
echo -e "${RED}Docker Compose is not installed${NC}"
exit 1
fi
}
# Run prerequisite checks
check_prerequisites
# Network configuration function
configure_network() {
echo -e "${YELLOW}Configuring network...${NC}"
# Ask about host network mode
read -p "Use host network mode? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
USE_HOST_NETWORK=true
else
# Check for port conflicts
check_port_conflict 8096
check_port_conflict 8920
check_port_conflict 1900 "DLNA"
fi
# List available networks
echo -e "${YELLOW}Available Docker networks:${NC}"
docker network ls
read -p "Use specific Docker network? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
select_docker_network
fi
}
# Function to list available volumes
list_volumes() {
echo "Available volumes:"
docker volume ls | grep -v "^local.*[0-9a-f]\{64\}$"
}
# Function to select media volume
select_media_volume() {
local volumes=$(docker volume ls --format "{{.Name}}" | grep -v "^[0-9a-f]\{64\}$")
if [ -z "$volumes" ]; then
echo -e "${RED}No named volumes found${NC}"
return 1
fi
echo "Available volumes:"
select volume in $volumes "Create new" "Skip"; do
case $volume in
"Create new")
configure_new_volume
break
;;
"Skip")
break
;;
*)
if [ -n "$volume" ]; then
echo "Selected volume: $volume"
add_volume_to_override "$volume"
break
fi
;;
esac
done
}
# Function to add volume to override file
add_volume_to_override() {
local volume=$1
if [ ! -f "${INSTALL_DIR}/docker-compose.override.yml" ]; then
cp "${INSTALL_DIR}/docker-compose.override.yml.sample" "${INSTALL_DIR}/docker-compose.override.yml"
fi
# Add volume if not already present
if ! grep -q " $volume:" "${INSTALL_DIR}/docker-compose.override.yml"; then
sed -i "/volumes:/a\ $volume:\n external: true" "${INSTALL_DIR}/docker-compose.override.yml"
fi
}
# Configure volumes
configure_volumes() {
echo -e "${YELLOW}Checking available volumes...${NC}"
list_volumes
read -p "Would you like to use existing volumes? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
select_media_volume
fi
}
# Run volume configuration
configure_volumes
# Collect required environment variables
collect_env_variables() {
echo -e "${YELLOW}Configuring environment variables...${NC}"
# Only ask if not already set in .env
if [ ! -f "${INSTALL_DIR}/.env" ] || ! grep -q "DOMAIN=" "${INSTALL_DIR}/.env"; then
read -p "Domain name for Jellyfin: " DOMAIN
fi
if [ ! -f "${INSTALL_DIR}/.env" ] || ! grep -q "JELLYFIN_ADMIN_USER=" "${INSTALL_DIR}/.env"; then
read -p "Jellyfin admin username: " ADMIN_USER
fi
# Add password collection with masking
if [ ! -f "${INSTALL_DIR}/.env" ] || ! grep -q "JELLYFIN_ADMIN_PASSWORD=" "${INSTALL_DIR}/.env"; then
read -s -p "Jellyfin admin password: " ADMIN_PASSWORD
echo
fi
}
echo -e "${GREEN}Installation complete!${NC}"
echo "--------------------------------"
echo -e "Files installed in: ${YELLOW}${INSTALL_DIR}${NC}"
echo -e "Transcode cache: ${YELLOW}${TRANSCODE_DIR}${NC}"
echo -e "GPU detected: ${YELLOW}${GPU_TYPE}${NC}"
echo
echo "Next steps:"
echo "1. Edit ${INSTALL_DIR}/.env to configure your settings"
echo "2. Start Jellyfin with:"
echo -e "${YELLOW} cd ${INSTALL_DIR}${NC}"
echo -e "${YELLOW} docker compose -f docker-compose.yml -f ${TRANSCODE_FILE} up -d${NC}"