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)
This commit is contained in:
parent
fdea857efe
commit
aa53d5541d
43
package/diy/docker-restore/Makefile
Normal file
43
package/diy/docker-restore/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (C) 2026 xiexiaobao
|
||||
#
|
||||
# This is free software, licensed under the GPL 2.0 license.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=docker-restore
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=xiexiaobao
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/docker-restore
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Docker container restore script for R6C
|
||||
DEPENDS:=+docker
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/docker-restore/description
|
||||
One-click restore script for all 16 Docker containers on NanoPi R6C.
|
||||
Saves docker run commands for Jellyfin, Plex, Emby, Immich, Navidrome,
|
||||
n8n, HomeAssistant, PhotoPrism, LANraragi, UptimeKuma, Aria2, etc.
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/docker-restore/install
|
||||
$(INSTALL_DIR) $(1)/root
|
||||
$(INSTALL_BIN) ./files/restore-docker.sh $(1)/root/restore-docker.sh
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,docker-restore))
|
||||
231
package/diy/docker-restore/files/restore-docker.sh
Normal file
231
package/diy/docker-restore/files/restore-docker.sh
Normal file
@ -0,0 +1,231 @@
|
||||
#!/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"
|
||||
@ -1 +1,2 @@
|
||||
CONFIG_PACKAGE_jellyfin-autoinit=y
|
||||
CONFIG_PACKAGE_docker-restore=y
|
||||
|
||||
Loading…
Reference in New Issue
Block a user