istoreos/package/diy/docker-restore/files/restore-docker.sh
xiexiaobao aa53d5541d feat: add docker-restore package (16-container restore script)
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)
2026-06-26 10:28:31 +08:00

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"