#!/bin/bash # Phase 2 Migration: Calibre Stack + Audiobookshelf # Target: replicant (.80) # Run from control server (CT 127) set -e REPO_DIR="$HOME/clustered-fucks" COMPOSE_DIR="$REPO_DIR/compose-files/replicant" PLAYBOOK_DIR="$REPO_DIR/playbooks" echo "=== Phase 2: Calibre Stack + Audiobookshelf Migration ===" echo "" # Create directories mkdir -p "$COMPOSE_DIR/calibre" mkdir -p "$COMPOSE_DIR/audiobookshelf" # ============================================================================= # Calibre Stack (calibre-server + calibre-web) # ============================================================================= cat > "$COMPOSE_DIR/calibre/docker-compose.yml" << 'EOF' services: calibre-server: image: linuxserver/calibre:latest container_name: calibre-server restart: unless-stopped security_opt: - seccomp:unconfined ports: - "28080:8080" - "28081:8081" - "28181:8181" volumes: - ./config:/config - /mnt/nas/media/Books:/books environment: - PUID=1000 - PGID=1000 - TZ=America/Indiana/Indianapolis - GUAC_USER=calibre - GUAC_PASS=calibre - CALIBRE_SERVERSIDE_BROWSE=1 networks: - proxy labels: - "autoheal=true" - "com.centurylinklabs.watchtower.enable=true" deploy: resources: limits: memory: 1G cpus: "1.0" calibre-web: image: linuxserver/calibre-web:latest container_name: calibre-web restart: unless-stopped security_opt: - seccomp:unconfined ports: - "28083:8083" volumes: - ./config:/config - /mnt/nas/media/Books:/books:ro environment: - PUID=1000 - PGID=1000 - TZ=America/Indiana/Indianapolis - DOCKER_MODS=linuxserver/mods:calibre-web-calibre - CALIBRE_DBPATH=/books - OAUTHLIB_RELAX_TOKEN_SCOPE=1 networks: - proxy labels: - "autoheal=true" - "com.centurylinklabs.watchtower.enable=true" deploy: resources: limits: memory: 512M cpus: "0.5" depends_on: - calibre-server networks: proxy: external: true EOF echo "[OK] Created $COMPOSE_DIR/calibre/docker-compose.yml" # ============================================================================= # Audiobookshelf # ============================================================================= cat > "$COMPOSE_DIR/audiobookshelf/docker-compose.yml" << 'EOF' services: audiobookshelf: image: ghcr.io/advplyr/audiobookshelf:latest container_name: audiobookshelf restart: unless-stopped ports: - "13378:80" volumes: - ./config:/config - ./metadata:/metadata - /mnt/nas/media/audiobooks:/audiobooks networks: - proxy labels: - "autoheal=true" - "com.centurylinklabs.watchtower.enable=true" deploy: resources: limits: memory: 1G cpus: "1.0" networks: proxy: external: true EOF echo "[OK] Created $COMPOSE_DIR/audiobookshelf/docker-compose.yml" # ============================================================================= # Ansible Playbook: deploy-calibre.yml # ============================================================================= cat > "$PLAYBOOK_DIR/deploy-calibre.yml" << 'EOF' --- - name: Deploy Calibre Stack (calibre-server + calibre-web) hosts: replicant become: true vars: service_dir: /home/maddox/docker/appdata/calibre tasks: - name: Create calibre 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-files/replicant/calibre/docker-compose.yml dest: "{{ service_dir }}/docker-compose.yml" owner: maddox group: maddox mode: "0644" - name: Ensure proxy network exists community.docker.docker_network: name: proxy state: present - name: Deploy calibre stack community.docker.docker_compose_v2: project_src: "{{ service_dir }}" state: present pull: always register: compose_result - name: Show deployment result ansible.builtin.debug: msg: "Calibre stack deployed successfully" when: compose_result.changed EOF echo "[OK] Created $PLAYBOOK_DIR/deploy-calibre.yml" # ============================================================================= # Ansible Playbook: deploy-audiobookshelf.yml # ============================================================================= cat > "$PLAYBOOK_DIR/deploy-audiobookshelf.yml" << 'EOF' --- - name: Deploy Audiobookshelf hosts: replicant become: true vars: service_dir: /home/maddox/docker/appdata/audiobookshelf tasks: - name: Create audiobookshelf 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: Create metadata subdirectory ansible.builtin.file: path: "{{ service_dir }}/metadata" state: directory owner: maddox group: maddox mode: "0755" - name: Copy docker-compose.yml ansible.builtin.copy: src: ../compose-files/replicant/audiobookshelf/docker-compose.yml dest: "{{ service_dir }}/docker-compose.yml" owner: maddox group: maddox mode: "0644" - name: Ensure proxy network exists community.docker.docker_network: name: proxy state: present - name: Deploy audiobookshelf community.docker.docker_compose_v2: project_src: "{{ service_dir }}" state: present pull: always register: compose_result - name: Show deployment result ansible.builtin.debug: msg: "Audiobookshelf deployed successfully" when: compose_result.changed EOF echo "[OK] Created $PLAYBOOK_DIR/deploy-audiobookshelf.yml" # ============================================================================= # Summary # ============================================================================= echo "" echo "=== Files Created ===" echo " Compose files:" echo " - $COMPOSE_DIR/calibre/docker-compose.yml" echo " - $COMPOSE_DIR/audiobookshelf/docker-compose.yml" echo " Playbooks:" echo " - $PLAYBOOK_DIR/deploy-calibre.yml" echo " - $PLAYBOOK_DIR/deploy-audiobookshelf.yml" echo "" echo "=== Migration Steps ===" echo "" echo "1. Stop containers on alien:" echo " ssh alien 'docker stop calibre-server calibre-web audiobookshelf'" echo "" echo "2. Rsync data FROM replicant (SSH into replicant first):" echo " ssh replicant" echo " rsync -avP maddox@192.168.1.252:/home/maddox/docker/appdata/calibre/ /home/maddox/docker/appdata/calibre/" echo " rsync -avP maddox@192.168.1.252:/home/maddox/docker/appdata/audiobookshelf/ /home/maddox/docker/appdata/audiobookshelf/" echo "" echo "3. Deploy services:" echo " cd ~/clustered-fucks" echo " ansible-playbook playbooks/deploy-calibre.yml" echo " ansible-playbook playbooks/deploy-audiobookshelf.yml" echo "" echo "4. Verify services:" echo " curl -s -o /dev/null -w '%{http_code}' http://192.168.1.80:28080/ # calibre desktop" echo " curl -s -o /dev/null -w '%{http_code}' http://192.168.1.80:28083/ # calibre-web" echo " curl -s -o /dev/null -w '%{http_code}' http://192.168.1.80:13378/ # audiobookshelf" echo "" echo "5. Update Traefik backends to point to 192.168.1.80" echo "" echo "6. Cleanup alien (after verification):" echo " ssh alien 'docker rm calibre-server calibre-web audiobookshelf'" echo "" echo "7. Commit changes:" echo " git add -A && git commit -m 'Phase 2: migrate calibre stack + audiobookshelf' && git push" echo "" echo "=== IMPORTANT ===" echo "Change GUAC_PASS in calibre compose before deploying!"