diff --git a/Configurations/host.conf.template b/Configurations/host.conf.template index 82e3c04..2842f46 100644 --- a/Configurations/host.conf.template +++ b/Configurations/host.conf.template @@ -503,3 +503,27 @@ HOSTN_SYS_WATCHDOG_CHECK_NETWORK=true HOSTN_SYS_WATCHDOG_CHECK_SSHD=true HOSTN_SYS_WATCHDOG_CHECK_RUNAWAY=false + +# ============================================================================================== +# ── AUTH STACK ──────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== +# Credentials for the Varaverk Auth Stack page (NPM, lldap, Authelia). + +# ━━━ NginxProxyManager ━━━ +# Admin API runs on 7818 (not 81 — 81 is the partnership WebUI port). + HOSTN_NPM_URL="http://localhost:7818" + HOSTN_NPM_USER="" # NPM admin email + HOSTN_NPM_PASS="" # NPM admin password + +# ━━━ lldap ━━━ + HOSTN_LLDAP_URL="http://localhost:17170" + HOSTN_LLDAP_USER="admin" # lldap admin username + HOSTN_LLDAP_PASS="" # lldap admin password + +# ━━━ Authelia ━━━ + HOSTN_AUTHELIA_CONFIG="/mnt/user/appdata/Authelia/configuration.yml" + HOSTN_AUTHELIA_CONTAINER="Authelia" + +# ============================================================================================== +# ──────────────────────── End Of HOSTn Variables ────────────────────────────────────────────── +# ============================================================================================== diff --git a/Plugin/unraid/api/setup.php b/Plugin/unraid/api/setup.php index c744bb1..ef7d62a 100644 --- a/Plugin/unraid/api/setup.php +++ b/Plugin/unraid/api/setup.php @@ -215,18 +215,25 @@ $hostId = strtoupper($mySlot); $hostIdLow = strtolower($mySlot); $confFile = $hostIdLow . '.conf'; +// Storage mode: use wizard selection, fall back to auto-detect from boot transport +$smParam = trim($_POST['storage_mode'] ?? ''); +if ($smParam === 'flash') { + $storageInternal = 'false'; +} elseif ($smParam === 'internal') { + $storageInternal = 'true'; +} else { + $bootPart = trim(shell_exec('findmnt -n -o SOURCE /boot 2>/dev/null') ?: ''); + $bootDisk = $bootPart ? trim(shell_exec('lsblk -no pkname ' . escapeshellarg($bootPart) . ' 2>/dev/null') ?: '') : ''; + $transport = $bootDisk ? strtolower(trim(shell_exec('lsblk -dno TRAN /dev/' . escapeshellarg($bootDisk) . ' 2>/dev/null') ?: '')) : ''; + $storageInternal = ($transport !== 'usb') ? 'true' : 'false'; +} + if (!file_exists(CONF_DIR . '/' . $confFile)) { $template = @file_get_contents(CONF_DIR . '/host.conf.template') ?: ''; if ($template) { $sshOwner = strtolower(preg_replace('/^unraid-/i', '', $myHostname)); $sshKeyPath = '/root/.ssh/' . $sshOwner . '_rsync_automation'; - // Auto-detect storage mode from boot device transport - $bootPart = trim(shell_exec('findmnt -n -o SOURCE /boot 2>/dev/null') ?: ''); - $bootDisk = $bootPart ? trim(shell_exec('lsblk -no pkname ' . escapeshellarg($bootPart) . ' 2>/dev/null') ?: '') : ''; - $transport = $bootDisk ? strtolower(trim(shell_exec('lsblk -dno TRAN /dev/' . escapeshellarg($bootDisk) . ' 2>/dev/null') ?: '')) : ''; - $storageInternal = ($transport !== 'usb') ? 'true' : 'false'; - $conf = str_replace('HOSTN', $hostId, $template); $conf = str_replace('hostn', $hostIdLow, $conf); $conf = preg_replace('/^(\s*' . $hostId . '_SSH_KEY\s*=\s*)""/m', @@ -251,9 +258,14 @@ if (file_exists($sshScript)) { // Auto-create Unraid API key and write into the fresh conf $apiKeyResult = vv_auto_create_api_key($hostId, $confFile); +$targetDir = ($storageInternal === 'true') ? '/boot/config/plugins/varaverk' : '/mnt/user/appdata/Varaverk'; +$needsMigration = (defined('SCRIPTS_DIR') && SCRIPTS_DIR !== $targetDir); + echo json_encode([ - 'ok' => true, - 'host_id' => $hostId, - 'api_key' => $apiKeyResult, - 'redirect' => '?tab=scheduler&vv_setup=master.conf', + 'ok' => true, + 'host_id' => $hostId, + 'api_key' => $apiKeyResult, + 'needs_migration'=> $needsMigration, + 'migrate_to' => $needsMigration ? ($storageInternal === 'true' ? 'internal' : 'flash') : null, + 'redirect' => '?tab=scheduler&vv_setup=master.conf', ]); diff --git a/Plugin/unraid/pages/setup.php b/Plugin/unraid/pages/setup.php index b342f66..fd691cc 100644 --- a/Plugin/unraid/pages/setup.php +++ b/Plugin/unraid/pages/setup.php @@ -86,6 +86,19 @@ hr.vv-hr { border: none; border-top: 1px solid #1e1e1e; margin: 22px 0; }
Detecting environment…
+
+ +
+
+ Appdata
USB boot · requires array +
+
+ Internal Boot
NVMe/SSD · no array dep +
+
+
+
+
@@ -174,7 +187,19 @@ hr.vv-hr { border: none; border-top: 1px solid #1e1e1e; margin: 22px 0; }
diff --git a/Tools/claude_startup.sh b/Tools/claude_startup.sh index 42cafaa..17c1d51 100755 --- a/Tools/claude_startup.sh +++ b/Tools/claude_startup.sh @@ -5,18 +5,27 @@ # # PURPOSE # ───────────────────────────────────────────────────────────────────────────── -# Restores Claude Code's persistent data after an Unraid reboot and launches Claude. -# Unraid's root filesystem lives in RAM — /root/.claude and /root/.local are wiped on -# every reboot. This script symlinks both directories back to persistent appdata storage -# before launching Claude, so memory, sessions, and settings survive across reboots. +# Restores Claude Code's persistent data after an Unraid reboot. +# /root is RAM — wiped on every boot. This script re-creates symlinks so +# Claude's memory, sessions, settings, and binary survive across reboots. # -# On first run with no existing persistent data, migrates from the current live locations: -# /root/.claude → PERSIST_DIR/.claude (memory, sessions, settings) -# /root/.local/share/claude → PERSIST_DIR/local/share/claude (installed binaries) -# Subsequent runs skip the migration and only create the symlinks. +# Storage mode is read from the host conf file: # -# Standalone script — no common.sh dependency. Safe to run directly from terminal -# or from array_started.sh. +# HOST*_STORAGE_MODE_INTERNAL=true → Internal (boot) mode +# .claude data → /boot/config/claude +# binary → /boot/config/claude-bin +# No array dependency — runs even before array mounts. +# +# HOST*_STORAGE_MODE_INTERNAL=false → Appdata mode +# .claude data → /mnt/user/appdata/claude-code/.claude +# binary → /mnt/user/appdata/claude-code/local/share/claude +# Requires array to be mounted. +# +# On first run in either mode, migrates any existing live data to persistent +# storage. Subsequent runs only re-create the symlinks. +# +# Standalone script — no common.sh dependency. Safe to run directly from +# terminal or from array_started.sh. # # ============================================================================================== # RUNTIME MODES @@ -30,14 +39,9 @@ # # ============================================================================================== -PERSIST_DIR="/mnt/user/appdata/claude-code" -CLAUDE_DATA="$PERSIST_DIR/.claude" -CLAUDE_BIN="$PERSIST_DIR/local/share/claude" - LAUNCH=false [[ "$1" == "--launch" ]] && LAUNCH=true -# Standalone — no common.sh dependency _log() { echo " ✅ $*"; } _warn() { echo " ⚠️ $*"; } _err() { echo " ❌ $*" >&2; } @@ -46,15 +50,48 @@ echo "" echo "━━━ Claude Code Startup ━━━" echo "" -# ── Array must be mounted ───────────────────────────────────────────────────────────────────── -if ! mountpoint -q /mnt/user 2>/dev/null; then - _err "Array not mounted — /mnt/user not available" - exit 1 +# ── Detect storage mode ─────────────────────────────────────────────────────────────────────── +CONF_DIR="/boot/config/plugins/varaverk/Configurations" +STORAGE_INTERNAL=false +for _conf in "$CONF_DIR"/host*.conf; do + [[ -f "$_conf" ]] || continue + if grep -q "_STORAGE_MODE_INTERNAL=true" "$_conf" 2>/dev/null; then + STORAGE_INTERNAL=true + break + fi +done + +if [[ "$STORAGE_INTERNAL" == true ]]; then + CLAUDE_DATA="/boot/config/plugins/varaverk/claude-data" + CLAUDE_BIN="/boot/config/plugins/varaverk/claude-bin" + _log "Storage mode: internal boot" +else + PERSIST_DIR="/mnt/user/appdata/claude-code" + CLAUDE_DATA="$PERSIST_DIR/.claude" + CLAUDE_BIN="$PERSIST_DIR/local/share/claude" + _log "Storage mode: appdata" +fi + +# ── Array check (appdata mode only) ────────────────────────────────────────────────────────── +if [[ "$STORAGE_INTERNAL" == false ]]; then + if ! mountpoint -q /mnt/user 2>/dev/null; then + _err "Array not mounted — /mnt/user not available (required for appdata mode)" + exit 1 + fi fi # ── Create persistent dirs ──────────────────────────────────────────────────────────────────── mkdir -p "$CLAUDE_DATA" "$CLAUDE_BIN" +# ── Migrate from old /boot/config/claude location (internal mode only) ─────────────────────── +if [[ "$STORAGE_INTERNAL" == true && -d /boot/config/claude && "$CLAUDE_DATA" != "/boot/config/claude" ]]; then + if [[ -z "$(ls -A "$CLAUDE_DATA" 2>/dev/null)" ]]; then + _warn "Migrating old /boot/config/claude → $CLAUDE_DATA" + cp -a /boot/config/claude/. "$CLAUDE_DATA/" + _log "Migrated .claude data from old location" + fi +fi + # ── Migrate .claude on first run ────────────────────────────────────────────────────────────── if [[ ! -L /root/.claude && -d /root/.claude ]]; then _warn "First run — migrating /root/.claude → $CLAUDE_DATA" @@ -75,8 +112,6 @@ if [[ ! -L /root/.local/share/claude && -d /root/.local/share/claude ]]; then fi # ── Create symlinks ─────────────────────────────────────────────────────────────────────────── -# Remove any real directories first — ln -sfn silently creates inside a dir instead of -# replacing it, which produces a circular symlink on subsequent runs after migration. mkdir -p /root/.local/share /root/.local/bin [[ -d /root/.claude && ! -L /root/.claude ]] && rm -rf /root/.claude @@ -88,8 +123,6 @@ ln -sfn "$CLAUDE_BIN" /root/.local/share/claude _log "claude binary → $CLAUDE_BIN" # ── Symlink CLAUDE.md ───────────────────────────────────────────────────────────────────────── -# Lives on /boot so it survives reboots without appdata. Symlinked into /root so Claude -# picks it up automatically from the working directory on every session. CLAUDE_MD="/boot/config/plugins/varaverk/CLAUDE.md" if [[ -f "$CLAUDE_MD" ]]; then ln -sfn "$CLAUDE_MD" /root/CLAUDE.md @@ -111,7 +144,6 @@ _log "claude v$LATEST ready" echo "" -# ── Setup-only mode (used by array_started.sh or other callers) ───────────────────────────────── if [[ "$LAUNCH" == false ]]; then _log "Setup complete — run 'claude' to start" echo ""