521 lines
19 KiB
Bash
Executable file
521 lines
19 KiB
Bash
Executable file
#!/bin/bash
|
||
# ============================================================================
|
||
# Phase 2 Batch 2 Migration Script
|
||
# Target: replicant (.80)
|
||
# Services: tinymediamanager, autoscan, channeltube, dispatcharr
|
||
# Run this on the control server (CT 127)
|
||
# ============================================================================
|
||
|
||
set -e
|
||
|
||
COMPOSE_BASE=~/clustered-fucks/compose-files/replicant
|
||
PLAYBOOK_DIR=~/clustered-fucks/playbooks
|
||
|
||
echo "╔════════════════════════════════════════════════════════════════════════════╗"
|
||
echo "║ Phase 2 Batch 2: tinymediamanager, autoscan, channeltube, dispatcharr ║"
|
||
echo "║ Target: replicant (192.168.1.80) ║"
|
||
echo "╚════════════════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
|
||
# ============================================================================
|
||
# TINYMEDIAMANAGER
|
||
# ============================================================================
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "Creating: tinymediamanager"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
mkdir -p "$COMPOSE_BASE/tinymediamanager"
|
||
|
||
cat > "$COMPOSE_BASE/tinymediamanager/docker-compose.yml" << 'EOF'
|
||
services:
|
||
tinymediamanager:
|
||
image: romancin/tinymediamanager:latest-v4
|
||
container_name: tinymediamanager
|
||
environment:
|
||
- USER_ID=1000
|
||
- GROUP_ID=1000
|
||
- TZ=America/Indiana/Indianapolis
|
||
- DISPLAY_WIDTH=1920
|
||
- DISPLAY_HEIGHT=1080
|
||
- KEEP_APP_RUNNING=1
|
||
- CLEAN_TMP_DIR=1
|
||
volumes:
|
||
- ./config:/config
|
||
- /volume1/Media:/media
|
||
ports:
|
||
- "45800:5800" # Web UI
|
||
- "45900:5900" # VNC
|
||
restart: unless-stopped
|
||
networks:
|
||
- proxy
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 1G
|
||
cpus: '2.0'
|
||
labels:
|
||
- "autoheal=true"
|
||
- "com.centurylinklabs.watchtower.enable=true"
|
||
|
||
networks:
|
||
proxy:
|
||
external: true
|
||
EOF
|
||
|
||
echo "✅ Created $COMPOSE_BASE/tinymediamanager/docker-compose.yml"
|
||
|
||
# Ansible playbook for tinymediamanager
|
||
cat > "$PLAYBOOK_DIR/deploy-tinymediamanager.yml" << 'EOF'
|
||
---
|
||
- name: Deploy TinyMediaManager to replicant
|
||
hosts: replicant
|
||
vars:
|
||
service_name: tinymediamanager
|
||
service_dir: /home/maddox/docker/appdata/{{ service_name }}
|
||
compose_src: "{{ playbook_dir }}/../compose-files/replicant/{{ service_name }}"
|
||
|
||
tasks:
|
||
- name: Create service directory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Create config subdirectory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}/config"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Copy docker-compose.yml
|
||
ansible.builtin.copy:
|
||
src: "{{ compose_src }}/docker-compose.yml"
|
||
dest: "{{ service_dir }}/docker-compose.yml"
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0644'
|
||
|
||
- name: Deploy container
|
||
community.docker.docker_compose_v2:
|
||
project_src: "{{ service_dir }}"
|
||
state: present
|
||
pull: always
|
||
become: yes
|
||
become_user: maddox
|
||
EOF
|
||
|
||
echo "✅ Created $PLAYBOOK_DIR/deploy-tinymediamanager.yml"
|
||
|
||
# ============================================================================
|
||
# AUTOSCAN
|
||
# ============================================================================
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "Creating: autoscan"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
mkdir -p "$COMPOSE_BASE/autoscan"
|
||
|
||
cat > "$COMPOSE_BASE/autoscan/docker-compose.yml" << 'EOF'
|
||
services:
|
||
autoscan:
|
||
image: cloudb0x/autoscan:latest
|
||
container_name: autoscan
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/Indiana/Indianapolis
|
||
volumes:
|
||
- ./config:/config
|
||
- /volume1/Media:/media:ro
|
||
- /volume1/Downloads:/downloads:ro
|
||
ports:
|
||
- "3030:3030"
|
||
restart: unless-stopped
|
||
networks:
|
||
- proxy
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 512M
|
||
cpus: '1.0'
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://localhost:3030/health"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
start_period: 40s
|
||
retries: 3
|
||
labels:
|
||
- "autoheal=true"
|
||
- "com.centurylinklabs.watchtower.enable=true"
|
||
|
||
networks:
|
||
proxy:
|
||
external: true
|
||
EOF
|
||
|
||
echo "✅ Created $COMPOSE_BASE/autoscan/docker-compose.yml"
|
||
|
||
# Ansible playbook for autoscan
|
||
cat > "$PLAYBOOK_DIR/deploy-autoscan.yml" << 'EOF'
|
||
---
|
||
- name: Deploy Autoscan to replicant
|
||
hosts: replicant
|
||
vars:
|
||
service_name: autoscan
|
||
service_dir: /home/maddox/docker/appdata/{{ service_name }}
|
||
compose_src: "{{ playbook_dir }}/../compose-files/replicant/{{ service_name }}"
|
||
|
||
tasks:
|
||
- name: Create service directory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Create config subdirectory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}/config"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Copy docker-compose.yml
|
||
ansible.builtin.copy:
|
||
src: "{{ compose_src }}/docker-compose.yml"
|
||
dest: "{{ service_dir }}/docker-compose.yml"
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0644'
|
||
|
||
- name: Deploy container
|
||
community.docker.docker_compose_v2:
|
||
project_src: "{{ service_dir }}"
|
||
state: present
|
||
pull: always
|
||
become: yes
|
||
become_user: maddox
|
||
EOF
|
||
|
||
echo "✅ Created $PLAYBOOK_DIR/deploy-autoscan.yml"
|
||
|
||
# ============================================================================
|
||
# CHANNELTUBE
|
||
# ============================================================================
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "Creating: channeltube"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
mkdir -p "$COMPOSE_BASE/channeltube"
|
||
|
||
cat > "$COMPOSE_BASE/channeltube/docker-compose.yml" << 'EOF'
|
||
services:
|
||
channeltube:
|
||
image: thewicklowwolf/channeltube:latest
|
||
container_name: channeltube
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/Indiana/Indianapolis
|
||
volumes:
|
||
- ./config:/channeltube/config
|
||
- /volume1/Media/Youtube/movies:/channeltube/downloads
|
||
- /volume1/Media/Youtube/audio:/channeltube/audio_downloads
|
||
ports:
|
||
- "5444:5000"
|
||
restart: unless-stopped
|
||
networks:
|
||
- proxy
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 1G
|
||
cpus: '2.0'
|
||
labels:
|
||
- "autoheal=true"
|
||
- "com.centurylinklabs.watchtower.enable=true"
|
||
|
||
networks:
|
||
proxy:
|
||
external: true
|
||
EOF
|
||
|
||
echo "✅ Created $COMPOSE_BASE/channeltube/docker-compose.yml"
|
||
|
||
# Ansible playbook for channeltube
|
||
cat > "$PLAYBOOK_DIR/deploy-channeltube.yml" << 'EOF'
|
||
---
|
||
- name: Deploy ChannelTube to replicant
|
||
hosts: replicant
|
||
vars:
|
||
service_name: channeltube
|
||
service_dir: /home/maddox/docker/appdata/{{ service_name }}
|
||
compose_src: "{{ playbook_dir }}/../compose-files/replicant/{{ service_name }}"
|
||
|
||
tasks:
|
||
- name: Create service directory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Create config subdirectory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}/config"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Copy docker-compose.yml
|
||
ansible.builtin.copy:
|
||
src: "{{ compose_src }}/docker-compose.yml"
|
||
dest: "{{ service_dir }}/docker-compose.yml"
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0644'
|
||
|
||
- name: Deploy container
|
||
community.docker.docker_compose_v2:
|
||
project_src: "{{ service_dir }}"
|
||
state: present
|
||
pull: always
|
||
become: yes
|
||
become_user: maddox
|
||
EOF
|
||
|
||
echo "✅ Created $PLAYBOOK_DIR/deploy-channeltube.yml"
|
||
|
||
# ============================================================================
|
||
# DISPATCHARR (with proxy to gluetun VPN)
|
||
# ============================================================================
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "Creating: dispatcharr (using gluetun proxy for VPN)"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
mkdir -p "$COMPOSE_BASE/dispatcharr"
|
||
|
||
cat > "$COMPOSE_BASE/dispatcharr/docker-compose.yml" << 'EOF'
|
||
services:
|
||
dispatcharr:
|
||
image: ghcr.io/dispatcharr/dispatcharr:latest
|
||
container_name: dispatcharr
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/Indiana/Indianapolis
|
||
- PORT=9191
|
||
# Route traffic through gluetun's HTTP proxy on download-stack
|
||
- HTTP_PROXY=http://192.168.1.122:38888
|
||
- HTTPS_PROXY=http://192.168.1.122:38888
|
||
- http_proxy=http://192.168.1.122:38888
|
||
- https_proxy=http://192.168.1.122:38888
|
||
# GPU settings (for future pve-alien, or CPU fallback)
|
||
- NVIDIA_VISIBLE_DEVICES=all
|
||
- NVIDIA_DRIVER_CAPABILITIES=compute,video,utility
|
||
volumes:
|
||
- ./data:/data
|
||
ports:
|
||
- "9191:9191"
|
||
restart: unless-stopped
|
||
networks:
|
||
- proxy
|
||
# Intel QuickSync access (pve-z620 has limited decode capability)
|
||
devices:
|
||
- /dev/dri:/dev/dri
|
||
group_add:
|
||
- video
|
||
- render
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 2G
|
||
cpus: '2.0'
|
||
labels:
|
||
- "autoheal=true"
|
||
- "com.centurylinklabs.watchtower.enable=true"
|
||
|
||
networks:
|
||
proxy:
|
||
external: true
|
||
EOF
|
||
|
||
echo "✅ Created $COMPOSE_BASE/dispatcharr/docker-compose.yml"
|
||
|
||
# Ansible playbook for dispatcharr
|
||
cat > "$PLAYBOOK_DIR/deploy-dispatcharr.yml" << 'EOF'
|
||
---
|
||
- name: Deploy Dispatcharr to replicant
|
||
hosts: replicant
|
||
vars:
|
||
service_name: dispatcharr
|
||
service_dir: /home/maddox/docker/appdata/{{ service_name }}
|
||
compose_src: "{{ playbook_dir }}/../compose-files/replicant/{{ service_name }}"
|
||
|
||
tasks:
|
||
- name: Create service directory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Create data subdirectory
|
||
ansible.builtin.file:
|
||
path: "{{ service_dir }}/data"
|
||
state: directory
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0755'
|
||
|
||
- name: Copy docker-compose.yml
|
||
ansible.builtin.copy:
|
||
src: "{{ compose_src }}/docker-compose.yml"
|
||
dest: "{{ service_dir }}/docker-compose.yml"
|
||
owner: maddox
|
||
group: maddox
|
||
mode: '0644'
|
||
|
||
- name: Deploy container
|
||
community.docker.docker_compose_v2:
|
||
project_src: "{{ service_dir }}"
|
||
state: present
|
||
pull: always
|
||
become: yes
|
||
become_user: maddox
|
||
EOF
|
||
|
||
echo "✅ Created $PLAYBOOK_DIR/deploy-dispatcharr.yml"
|
||
|
||
# ============================================================================
|
||
# COMBINED PLAYBOOK
|
||
# ============================================================================
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "Creating: Combined deployment playbook"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
cat > "$PLAYBOOK_DIR/deploy-phase2-batch2.yml" << 'EOF'
|
||
---
|
||
# Combined playbook for Phase 2 Batch 2 migrations
|
||
# Run with: ansible-playbook playbooks/deploy-phase2-batch2.yml
|
||
|
||
- name: Deploy TinyMediaManager
|
||
import_playbook: deploy-tinymediamanager.yml
|
||
|
||
- name: Deploy Autoscan
|
||
import_playbook: deploy-autoscan.yml
|
||
|
||
- name: Deploy ChannelTube
|
||
import_playbook: deploy-channeltube.yml
|
||
|
||
- name: Deploy Dispatcharr
|
||
import_playbook: deploy-dispatcharr.yml
|
||
EOF
|
||
|
||
echo "✅ Created $PLAYBOOK_DIR/deploy-phase2-batch2.yml"
|
||
|
||
# ============================================================================
|
||
# SUMMARY AND NEXT STEPS
|
||
# ============================================================================
|
||
echo ""
|
||
echo "╔════════════════════════════════════════════════════════════════════════╗"
|
||
echo "║ FILES CREATED ║"
|
||
echo "╚════════════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
echo "Compose files:"
|
||
echo " - $COMPOSE_BASE/tinymediamanager/docker-compose.yml"
|
||
echo " - $COMPOSE_BASE/autoscan/docker-compose.yml"
|
||
echo " - $COMPOSE_BASE/channeltube/docker-compose.yml"
|
||
echo " - $COMPOSE_BASE/dispatcharr/docker-compose.yml"
|
||
echo ""
|
||
echo "Playbooks:"
|
||
echo " - $PLAYBOOK_DIR/deploy-tinymediamanager.yml"
|
||
echo " - $PLAYBOOK_DIR/deploy-autoscan.yml"
|
||
echo " - $PLAYBOOK_DIR/deploy-channeltube.yml"
|
||
echo " - $PLAYBOOK_DIR/deploy-dispatcharr.yml"
|
||
echo " - $PLAYBOOK_DIR/deploy-phase2-batch2.yml (combined)"
|
||
echo ""
|
||
echo "╔════════════════════════════════════════════════════════════════════════╗"
|
||
echo "║ NEXT STEPS ║"
|
||
echo "╚════════════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
echo "1. STOP OLD CONTAINERS on alien:"
|
||
echo " ssh alien 'docker stop tinymediamanager autoscan channeltube dispatcharr'"
|
||
echo ""
|
||
echo "2. CREATE TARGET DIRECTORIES on replicant:"
|
||
echo " ssh replicant 'mkdir -p /home/maddox/docker/appdata/{tinymediamanager,autoscan,channeltube}/config'"
|
||
echo " ssh replicant 'mkdir -p /home/maddox/docker/appdata/dispatcharr/data'"
|
||
echo ""
|
||
echo "3. RSYNC DATA (run FROM replicant):"
|
||
echo ""
|
||
echo " ssh replicant"
|
||
echo ""
|
||
echo " # TinyMediaManager config:"
|
||
echo " rsync -avP maddox@alien:/home/maddox/docker/appdata/tinymediamanager/config/ /home/maddox/docker/appdata/tinymediamanager/config/"
|
||
echo ""
|
||
echo " # Autoscan config (note: different source path on alien):"
|
||
echo " rsync -avP maddox@alien:/volume1/docker/autoscan/ /home/maddox/docker/appdata/autoscan/config/"
|
||
echo ""
|
||
echo " # ChannelTube config:"
|
||
echo " rsync -avP maddox@alien:/home/maddox/docker/appdata/channeltube/config/ /home/maddox/docker/appdata/channeltube/config/"
|
||
echo ""
|
||
echo " # Dispatcharr data (note: source is in vpn subdirectory):"
|
||
echo " rsync -avP maddox@alien:/home/maddox/docker/appdata/vpn/dispatcharr/ /home/maddox/docker/appdata/dispatcharr/data/"
|
||
echo ""
|
||
echo "4. DEPLOY ALL (combined playbook):"
|
||
echo " ansible-playbook playbooks/deploy-phase2-batch2.yml"
|
||
echo ""
|
||
echo " OR deploy individually:"
|
||
echo " ansible-playbook playbooks/deploy-tinymediamanager.yml"
|
||
echo " ansible-playbook playbooks/deploy-autoscan.yml"
|
||
echo " ansible-playbook playbooks/deploy-channeltube.yml"
|
||
echo " ansible-playbook playbooks/deploy-dispatcharr.yml"
|
||
echo ""
|
||
echo "5. VERIFY SERVICES:"
|
||
echo " curl -s http://192.168.1.80:45800/ | head -5 # TinyMediaManager"
|
||
echo " curl -s http://192.168.1.80:3030/health # Autoscan"
|
||
echo " curl -s http://192.168.1.80:5444/ | head -5 # ChannelTube"
|
||
echo " curl -s http://192.168.1.80:9191/ | head -5 # Dispatcharr"
|
||
echo ""
|
||
echo "6. UPDATE TRAEFIK (if applicable):"
|
||
echo " - tinymediamanager: backend → 192.168.1.80:45800"
|
||
echo " - autoscan: backend → 192.168.1.80:3030"
|
||
echo " - channeltube: backend → 192.168.1.80:5444"
|
||
echo " - dispatcharr: backend → 192.168.1.80:9191"
|
||
echo ""
|
||
echo "7. CLEANUP ALIEN:"
|
||
echo " ssh alien 'docker rm tinymediamanager autoscan channeltube dispatcharr'"
|
||
echo ""
|
||
echo "8. GIT COMMIT:"
|
||
echo " git add -A && git commit -m 'Phase 2 Batch 2: tinymediamanager, autoscan, channeltube, dispatcharr → replicant' && git push"
|
||
echo ""
|
||
echo "╔════════════════════════════════════════════════════════════════════════╗"
|
||
echo "║ ℹ️ DISPATCHARR NOTES ║"
|
||
echo "╚════════════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
echo "Dispatcharr is configured to use gluetun's HTTP proxy for VPN protection:"
|
||
echo " - HTTP_PROXY=http://192.168.1.122:38888"
|
||
echo " - HTTPS_PROXY=http://192.168.1.122:38888"
|
||
echo ""
|
||
echo "This routes HTTP/HTTPS traffic through the VPN while allowing dispatcharr"
|
||
echo "to run on replicant with its own network stack and direct port access."
|
||
echo ""
|
||
echo "GPU Status:"
|
||
echo " - /dev/dri is passed through (Intel QuickSync on pve-z620)"
|
||
echo " - FirePro V3900 = decode-only (no hardware encoding)"
|
||
echo " - NVIDIA env vars set for future pve-alien migration"
|
||
echo " - Will use CPU transcoding until GTX 1070 is available"
|
||
echo ""
|