Pre-installs /root/restore-docker.sh in firmware for one-click recovery of all Docker containers after reflash. - Covers Jellyfin, Plex, Emby, Immich, Navidrome, n8n, etc. - Auto-creates immich_default network if missing - Includes Jellyfin WebRootPath fix and JS patch - Placeholder passwords (edit before use)
232 lines
7.1 KiB
Bash
232 lines
7.1 KiB
Bash
#!/bin/sh
|
|
# R6C Docker Container Restore Script
|
|
# Pre-installed in firmware by docker-restore package
|
|
# Run after flashing iStoreOS: sh /root/restore-docker.sh
|
|
#
|
|
# EDIT THIS FILE: replace CHANGEME values with your actual passwords.
|
|
# If you preserved /mnt/usb1-0/, container data survives reflash.
|
|
# Immich DB password and Aria2 RPC secret can be found from your old install.
|
|
|
|
set -e
|
|
echo "=== R6C Docker Restore ==="
|
|
echo ""
|
|
|
|
# ---- Wait for dockerd ----
|
|
for i in 1 2 3 4 5 6 7 8 9 10 15 20; do
|
|
docker info >/dev/null 2>&1 && break
|
|
echo "Waiting for dockerd... (${i}s)"
|
|
sleep 3
|
|
done
|
|
docker info >/dev/null 2>&1 || { echo "dockerd not ready"; exit 1; }
|
|
echo "dockerd ready"
|
|
echo ""
|
|
|
|
# ---- Check Docker data root ----
|
|
CURRENT_ROOT=$(docker info --format "{{.DockerRootDir}}" 2>/dev/null)
|
|
if [ "$CURRENT_ROOT" = "/opt/docker" ] && [ -d "/mnt/usb1-0/docker" ]; then
|
|
echo "Docker data root is on eMMC but TF card has data."
|
|
echo "Run this to fix:"
|
|
echo ' uci set dockerd.globals.data_root=/mnt/usb1-0/docker'
|
|
echo ' uci add_list dockerd.globals.registry_mirrors=https://docker.1ms.run'
|
|
echo ' uci commit dockerd && /etc/init.d/dockerd restart'
|
|
echo ""
|
|
fi
|
|
|
|
restore_container() {
|
|
local name="$1"
|
|
shift
|
|
if docker inspect "$name" >/dev/null 2>&1; then
|
|
echo "SKIP: $name already exists"
|
|
return
|
|
fi
|
|
echo "Creating: $name"
|
|
docker run -d --name "$name" "$@"
|
|
echo "DONE: $name"
|
|
echo ""
|
|
}
|
|
|
|
# ========== Preparation ==========
|
|
# Create Immich network if missing
|
|
if ! docker network inspect immich_default >/dev/null 2>&1; then
|
|
echo "Creating network: immich_default"
|
|
docker network create immich_default
|
|
echo ""
|
|
fi
|
|
|
|
# ========== CONTAINERS ==========
|
|
|
|
# ---- n8n ----
|
|
restore_container n8n \
|
|
--restart=unless-stopped \
|
|
-e WEBHOOK_URL=https://n8n.maplemaple.top \
|
|
-e N8N_AI_ENABLED=true \
|
|
-e N8N_SECURE_COOKIE=false \
|
|
-v /opt/n8n/data:/home/node/.n8n \
|
|
-p 5678:5678 \
|
|
n8nio/n8n:latest
|
|
|
|
# ---- ChangeDetection ----
|
|
restore_container changedetection \
|
|
--restart=unless-stopped \
|
|
-e BASE_URL=https://watch.maplemaple.top \
|
|
-v /opt/changedetection/data:/datastore \
|
|
-p 127.0.0.1:5000:5000 \
|
|
ghcr.io/dgtlmoon/changedetection.io:latest
|
|
|
|
# ---- Jellyfin (with WebRootPath fix) ----
|
|
restore_container jellyfin \
|
|
--restart=unless-stopped \
|
|
--network=host \
|
|
-e TZ=Asia/Shanghai \
|
|
-v /mnt/usb1-0/Configs/Jellyfin:/config \
|
|
-v /mnt/usb1-0/Caches/Jellyfin:/config/transcodes \
|
|
-v /mnt/usb1-0:/mnt/usb1-0 \
|
|
--entrypoint sh \
|
|
jellyfin/jellyfin:2026062206-arm64 \
|
|
-c "ln -sf /jellyfin/jellyfin-web /jellyfin/wwwroot && exec /jellyfin/jellyfin"
|
|
|
|
# ---- Emby ----
|
|
restore_container emby \
|
|
--restart=unless-stopped \
|
|
--network=host \
|
|
-v /mnt/usb1-0/Configs/Emby:/config \
|
|
-v /mnt:/mnt \
|
|
emby/embyserver:latest
|
|
|
|
# ---- HomeAssistant ----
|
|
restore_container homeassistant \
|
|
--restart=unless-stopped \
|
|
--network=host \
|
|
-v /mnt/usb1-0/homeassistant:/config \
|
|
homeassistant/home-assistant:latest
|
|
|
|
# ---- Immich (4 containers) ----
|
|
# Note: Update DB_PASSWORD if your Immich DB password differs
|
|
IMMICH_DB_PASS="${IMMICH_DB_PASS:-CHANGEME_IMMICH_DB_PASSWORD}"
|
|
|
|
restore_container immich_postgres \
|
|
--restart=unless-stopped \
|
|
--network=immich_default \
|
|
-e POSTGRES_USER=postgres \
|
|
-e POSTGRES_DB=immich \
|
|
-e POSTGRES_PASSWORD="$IMMICH_DB_PASS" \
|
|
-e POSTGRES_INITDB_ARGS="--data-checksums" \
|
|
-v /opt/immich/postgres:/var/lib/postgresql/data:rw \
|
|
ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
|
|
|
|
restore_container immich_redis \
|
|
--restart=unless-stopped \
|
|
--network=immich_default \
|
|
docker.io/valkey/valkey:9
|
|
|
|
restore_container immich_server \
|
|
--restart=unless-stopped \
|
|
--network=immich_default \
|
|
-e TZ=Asia/Shanghai \
|
|
-e DB_USERNAME=postgres \
|
|
-e DB_DATABASE_NAME=immich \
|
|
-e DB_PASSWORD="$IMMICH_DB_PASS" \
|
|
-e UPLOAD_LOCATION=/mnt/usb1-0/Public/Immich \
|
|
-v /mnt/usb1-0/Public/Immich:/data:rw \
|
|
-p 2283:2283 \
|
|
ghcr.io/immich-app/immich-server:v2
|
|
|
|
restore_container immich_machine_learning \
|
|
--restart=unless-stopped \
|
|
--network=immich_default \
|
|
-e TZ=Asia/Shanghai \
|
|
-e DB_PASSWORD="$IMMICH_DB_PASS" \
|
|
-v immich_model-cache:/cache:rw \
|
|
ghcr.io/immich-app/immich-machine-learning:v2
|
|
|
|
# ---- UptimeKuma ----
|
|
restore_container uptime-kuma \
|
|
--restart=unless-stopped \
|
|
-v /mnt/usb1-0/uptime-kuma:/app/data \
|
|
-p 3001:3001 \
|
|
louislam/uptime-kuma:latest
|
|
|
|
# ---- Navidrome ----
|
|
restore_container navidrome \
|
|
--restart=unless-stopped \
|
|
-e ND_PORT=4533 \
|
|
-v /mnt/usb1-0/navidrome:/data \
|
|
-v /mnt/usb1-0/music:/music:ro \
|
|
-p 4533:4533 \
|
|
deluan/navidrome:latest
|
|
|
|
# ---- LANraragi ----
|
|
restore_container lanraragi \
|
|
--restart=unless-stopped \
|
|
-e TZ=Asia/Shanghai \
|
|
-v /mnt/usb1-0/Configs/LANraragi:/root/lanraragi/database \
|
|
-v /mnt/usb1-0/Public/Comics:/root/lanraragi/content \
|
|
-v /mnt:/mnt:rslave \
|
|
-p 3000:3000 \
|
|
dezhao/lanraragi_cn
|
|
|
|
# ---- PhotoPrism ----
|
|
restore_container photoprism \
|
|
--restart=unless-stopped \
|
|
-e PHOTOPRISM_UPLOAD_NSFW=true \
|
|
-e PHOTOPRISM_ADMIN_PASSWORD=CHANGEME_PHOTOPRISM_PASS \
|
|
-e TZ=Asia/Shanghai \
|
|
-v /mnt/usb1-0/Configs/PhotoPrism:/photoprism/storage \
|
|
-v /mnt/usb1-0/Public/Photo:/photoprism/originals \
|
|
-p 2342:2342 \
|
|
photoprism/photoprism
|
|
|
|
# ---- Plex ----
|
|
restore_container plex \
|
|
--restart=unless-stopped \
|
|
-e TZ=Asia/Shanghai \
|
|
-e PLEX_CLAIM= \
|
|
-v /mnt/usb1-0/Configs/Plex:/config \
|
|
-v /mnt/usb1-0/Caches/Plex:/transcode \
|
|
-v /mnt:/mnt:rslave \
|
|
-p 3005:3005 \
|
|
-p 32400:32400 \
|
|
-p 32410:32410/udp \
|
|
-p 32412:32412/udp \
|
|
-p 32413:32413/udp \
|
|
-p 32414:32414/udp \
|
|
-p 32469:32469 \
|
|
-p 8324:8324 \
|
|
linuxserver/plex:latest
|
|
|
|
# ---- Aria2 ----
|
|
# Update RPC_SECRET if yours differs
|
|
Aria2_RPC_SECRET="${ARIA2_SECRET:-CHANGEME_ARIA2_SECRET}"
|
|
restore_container aria2 \
|
|
--restart=unless-stopped \
|
|
-e PUID=0 -e PGID=0 \
|
|
-e RPC_SECRET="$Aria2_RPC_SECRET" \
|
|
-e TZ=Asia/Shanghai \
|
|
-v /opt/aria2/downloads:/downloads \
|
|
-v /opt/aria2/config:/config \
|
|
-p 6889:6888 \
|
|
-p 6889:6888/udp \
|
|
-p 6880:8080 \
|
|
p3terx/aria2-pro:latest
|
|
|
|
# ========== Jellyfin JS patch ==========
|
|
echo ""
|
|
echo "Patching Jellyfin web UI bug..."
|
|
for i in 1 2 3 4 5 6 7 8 9 10; do
|
|
docker exec jellyfin curl -s http://127.0.0.1:8096/system/info/public >/dev/null 2>&1 && break
|
|
sleep 3
|
|
done
|
|
docker exec jellyfin sh -c 'sed -i "s/key:\"getApi\",value:function(e){var t,n=this.getApiClient(e);return/key:\"getApi\",value:function(e){if(!e)return;var t,n=this.getApiClient(e);return/g" /wwwroot/main.jellyfin.bundle.js' 2>/dev/null || true
|
|
docker restart jellyfin 2>/dev/null || true
|
|
|
|
echo ""
|
|
echo "=== Restore complete ==="
|
|
echo ""
|
|
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Set PLEX_CLAIM (visit plex.tv/claim)"
|
|
echo " 2. Change PhotoPrism admin password in web UI"
|
|
echo " 3. Check Immich admin setup at http://192.168.100.1:2283"
|
|
echo " 4. Restart changedetection to pick up API key changes"
|