#!/bin/bash # Jellyfin Migration to Docker Swarm Script # Safely migrates from standalone container to Docker Swarm with storage fixes # Created: $(date) set -e echo "=== Jellyfin Migration to Docker Swarm ===" echo "" # Check current status echo "Checking current Jellyfin status..." if ssh root@omv800 "docker ps | grep -q jellyfin"; then echo "✅ Standalone Jellyfin container is running" STANDALONE_CONTAINER=$(ssh root@omv800 "docker ps -q -f name=jellyfin") echo "Container ID: $STANDALONE_CONTAINER" else echo "❌ Standalone Jellyfin container not found" exit 1 fi # Check Docker Swarm status echo "" echo "Checking Docker Swarm status..." if ssh root@omv800 "docker service ls | grep -q jellyfin"; then echo "⚠️ Jellyfin Docker Swarm service already exists" echo "Removing existing service..." ssh root@omv800 "docker service rm jellyfin_jellyfin" sleep 10 else echo "✅ No existing Jellyfin Docker Swarm service" fi # Storage analysis and preparation echo "" echo "=== STORAGE ANALYSIS ===" echo "Current Jellyfin storage usage:" ssh root@omv800 "docker exec jellyfin du -sh /config /cache /media/* 2>/dev/null || echo 'Container not accessible'" echo "" echo "Available storage on target drives:" ssh root@omv800 "df -h /srv/dev-disk-by-uuid-0f772f0b-917d-4337-a3c5-5cc5d3badac9" ssh root@omv800 "df -h /srv/dev-disk-by-uuid-97cb939b-5af7-4dc1-8190-072eafb37d41" # Create safe storage directories echo "" echo "Creating safe storage directories..." LOCAL_CONFIG_DIR="/srv/dev-disk-by-uuid-0f772f0b-917d-4337-a3c5-5cc5d3badac9/jellyfin-config" LOCAL_CACHE_DIR="/srv/dev-disk-by-uuid-0f772f0b-917d-4337-a3c5-5cc5d3badac9/jellyfin-cache" ssh root@omv800 "mkdir -p $LOCAL_CONFIG_DIR $LOCAL_CACHE_DIR" ssh root@omv800 "chown -R 1000:1000 $LOCAL_CONFIG_DIR $LOCAL_CACHE_DIR" # Backup current configuration echo "" echo "Creating backup of current configuration..." BACKUP_DIR="/export/jellyfin_backups" BACKUP_FILE="$BACKUP_DIR/jellyfin_backup_$(date +%Y%m%d_%H%M%S).tar.gz" ssh root@omv800 "mkdir -p $BACKUP_DIR" echo "Backing up current Jellyfin config..." ssh root@omv800 "docker exec jellyfin tar -czf /tmp/jellyfin_config_backup.tar.gz -C /config ." ssh root@omv800 "docker cp jellyfin:/tmp/jellyfin_config_backup.tar.gz /tmp/" ssh root@omv800 "mv /tmp/jellyfin_config_backup.tar.gz $BACKUP_FILE" echo "✅ Backup created: $BACKUP_FILE" # Stop standalone container echo "" echo "Stopping standalone Jellyfin container..." ssh root@omv800 "docker stop jellyfin" sleep 10 # Copy configuration to local storage echo "" echo "Copying configuration to local storage..." ssh root@omv800 "docker run --rm -v jellyfin-config:/config -v $LOCAL_CONFIG_DIR:/dest alpine tar -xzf /config/jellyfin_config_backup.tar.gz -C /dest" # Verify copy echo "Verifying configuration copy..." ssh root@omv800 "ls -la $LOCAL_CONFIG_DIR/ | head -10" # Deploy Docker Swarm service echo "" echo "Deploying Jellyfin to Docker Swarm..." cd /home/jonathan/Coding/HomeAudit scp stacks/apps/jellyfin.yml root@omv800:/tmp/jellyfin.yml ssh root@omv800 "docker stack deploy -c /tmp/jellyfin.yml jellyfin" # Wait for service to start echo "Waiting for Jellyfin service to start..." sleep 60 # Check service status echo "" echo "Checking Docker Swarm service status..." if ssh root@omv800 "docker service ls | grep -q jellyfin"; then echo "✅ Jellyfin Docker Swarm service is running" # Wait for container to be ready echo "Waiting for container to be ready..." sleep 30 # Check container status CONTAINER_ID=$(ssh root@omv800 "docker ps -q -f name=jellyfin" | head -1) if [ -n "$CONTAINER_ID" ]; then echo "✅ Jellyfin container found: $CONTAINER_ID" # Check health status HEALTH=$(ssh root@omv800 "docker inspect $CONTAINER_ID --format='{{.State.Health.Status}}' 2>/dev/null || echo 'starting'") echo "Container health: $HEALTH" # Test accessibility echo "Testing Jellyfin accessibility..." if ssh root@omv800 "curl -s -o /dev/null -w '%{http_code}' http://localhost:8096" | grep -q "200\|302"; then echo "✅ Jellyfin is accessible on port 8096" else echo "⚠️ Jellyfin may not be accessible yet" fi # Check storage usage echo "" echo "Checking new storage usage..." ssh root@omv800 "du -sh $LOCAL_CONFIG_DIR $LOCAL_CACHE_DIR" else echo "❌ Jellyfin container not found" exit 1 fi else echo "❌ Jellyfin Docker Swarm service failed to start" exit 1 fi # Clean up old standalone container echo "" echo "Cleaning up old standalone container..." ssh root@omv800 "docker rm jellyfin 2>/dev/null || echo 'Container already removed'" # Remove old Docker volumes echo "Removing old Docker volumes..." ssh root@omv800 "docker volume rm jellyfin-config jellyfin-cache 2>/dev/null || echo 'Volumes already removed'" echo "" echo "=== MIGRATION COMPLETE ===" echo "✅ Jellyfin successfully migrated to Docker Swarm" echo "✅ Configuration backed up to: $BACKUP_FILE" echo "✅ Storage moved to safe local drives" echo "✅ Media remains on MergerFS (read-only)" echo "✅ Caddy integration configured" echo "" echo "Storage locations:" echo " - Config: $LOCAL_CONFIG_DIR (safe local storage)" echo " - Cache: $LOCAL_CACHE_DIR (safe local storage)" echo " - Media: /srv/mergerfs/DataPool/ (MergerFS, read-only)" echo "" echo "To monitor Jellyfin:" echo " ssh root@omv800 'docker service ls | grep jellyfin'" echo " ssh root@omv800 'docker service logs jellyfin_jellyfin --tail 20'" echo "" echo "To access Jellyfin:" echo " https://jellyfin.pressmess.duckdns.org" echo "" echo "If you need to restore from backup:" echo " tar -xzf $BACKUP_FILE -C /path/to/restore/"