Improve portable USB pack and credentials-based tunnel launcher.

Expand pack-usb.bat to sync LAUNCH.bat, cloudflare assets, and data dirs while preserving operator state; align usb/LAUNCH.bat with credentials.json tunnel flow instead of a baked token.
This commit is contained in:
AetherForge
2026-05-31 02:32:24 -07:00
parent babe644c94
commit 2f528229f2
2 changed files with 156 additions and 87 deletions

View File

@@ -3,17 +3,15 @@ setlocal EnableExtensions EnableDelayedExpansion
title AetherForge — Pack USB title AetherForge — Pack USB
cd /d "%~dp0" cd /d "%~dp0"
set "ROOT=%CD%" set "ROOT=%CD%"
set "USB=%ROOT%\USB" set "USB=%ROOT%\usb"
echo. echo.
echo ================================================================ echo ================================================================
echo AetherForge — Pack Portable USB echo AetherForge — Pack Portable USB
echo ================================================================ echo ================================================================
echo. echo.
echo This script builds AetherForge.exe and assembles everything echo Assembles a self-contained copy in: %USB%\
echo needed to run the Control Deck from a USB drive. echo Copy that entire folder to a USB drive — nothing else needed.
echo.
echo Output folder: %USB%\
echo. echo.
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
@@ -32,11 +30,13 @@ if errorlevel 1 (
set "SKIP_FRONTEND=1" set "SKIP_FRONTEND=1"
) )
if not exist "%USB%" mkdir "%USB%"
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 1. Build the frontend (if npm available) :: 1. Build the frontend when npm is available
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
if not defined SKIP_FRONTEND ( if not defined SKIP_FRONTEND (
echo [1/4] Building frontend... echo [1/7] Building frontend...
cd "%ROOT%\server\web" cd "%ROOT%\server\web"
call npm install --silent call npm install --silent
call npm run build call npm run build
@@ -47,15 +47,15 @@ if not defined SKIP_FRONTEND (
exit /b 1 exit /b 1
) )
cd "%ROOT%" cd "%ROOT%"
echo [1/4] Frontend built. echo [1/7] Frontend built.
) else ( ) else (
echo [1/4] Skipped (npm not found). echo [1/7] Skipped - npm not found.
) )
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 2. Build AetherForge.exe for the current machine (amd64 windows) :: 2. Build AetherForge.exe for Windows amd64
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
echo [2/4] Compiling AetherForge.exe... echo [2/7] Compiling AetherForge.exe...
cd "%ROOT%\server" cd "%ROOT%\server"
set "CGO_ENABLED=0" set "CGO_ENABLED=0"
set "GOOS=windows" set "GOOS=windows"
@@ -68,64 +68,105 @@ if errorlevel 1 (
exit /b 1 exit /b 1
) )
cd "%ROOT%" cd "%ROOT%"
echo [2/4] AetherForge.exe -> USB\AetherForge.exe echo [2/7] AetherForge.exe ready.
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 3. Copy webroot :: 3. Copy webroot - dashboard UI
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
echo [3/4] Copying webroot... echo [3/7] Copying webroot...
if exist "%USB%\webroot" rd /s /q "%USB%\webroot"
if exist "%ROOT%\server\webroot" ( if exist "%ROOT%\server\webroot" (
if exist "%USB%\webroot" rd /s /q "%USB%\webroot"
xcopy /e /i /q "%ROOT%\server\webroot" "%USB%\webroot" >nul xcopy /e /i /q "%ROOT%\server\webroot" "%USB%\webroot" >nul
echo [3/4] webroot copied.
) else if exist "%ROOT%\server\web\dist" ( ) else if exist "%ROOT%\server\web\dist" (
if exist "%USB%\webroot" rd /s /q "%USB%\webroot"
xcopy /e /i /q "%ROOT%\server\web\dist" "%USB%\webroot" >nul xcopy /e /i /q "%ROOT%\server\web\dist" "%USB%\webroot" >nul
echo [3/4] webroot copied from web\dist.
) else ( ) else (
echo [3/4] WARNING: No webroot found. Run 'npm run build' in server\web\ first. echo ERROR: No webroot found. Run npm run build in server\web first.
pause
exit /b 1
) )
echo [3/7] webroot copied.
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 4. Copy source trees (needed for Forge to compile agents on the USB) :: 4. Copy agent and fusion source - Forge needs these at runtime
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
echo [4/4] Copying agent + fusion source... echo [4/7] Copying agent + fusion source...
if exist "%USB%\agent" rd /s /q "%USB%\agent" if exist "%USB%\agent" rd /s /q "%USB%\agent"
if exist "%USB%\fusion" rd /s /q "%USB%\fusion" if exist "%USB%\fusion" rd /s /q "%USB%\fusion"
:: Copy agent source, excluding test results and build outputs
xcopy /e /i /q /EXCLUDE:"%ROOT%\usb_pack_exclude.txt" "%ROOT%\agent" "%USB%\agent" >nul xcopy /e /i /q /EXCLUDE:"%ROOT%\usb_pack_exclude.txt" "%ROOT%\agent" "%USB%\agent" >nul
xcopy /e /i /q /EXCLUDE:"%ROOT%\usb_pack_exclude.txt" "%ROOT%\fusion" "%USB%\fusion" >nul xcopy /e /i /q /EXCLUDE:"%ROOT%\usb_pack_exclude.txt" "%ROOT%\fusion" "%USB%\fusion" >nul
echo [4/4] Source trees copied. echo [4/7] Source trees copied.
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 5. Ensure data directories exist on USB :: 5. Launcher + docs (always sync from project root)
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
if not exist "%USB%\data\builds" mkdir "%USB%\data\builds" echo [5/7] Syncing LAUNCH.bat, README, cloudflare...
if not exist "%USB%\data\logs" mkdir "%USB%\data\logs" copy /y "%ROOT%\LAUNCH.bat" "%USB%\LAUNCH.bat" >nul
if not exist "%USB%\data\blueprints" mkdir "%USB%\data\blueprints" if not exist "%USB%\README.txt" (
if not exist "%USB%\data\preps" mkdir "%USB%\data\preps" if exist "%ROOT%\usb\README.txt" copy /y "%ROOT%\usb\README.txt" "%USB%\README.txt" >nul
)
:: run.bat is a project-root marker used by some tooling
echo @echo off > "%USB%\run.bat"
echo rem AetherForge portable root marker >> "%USB%\run.bat"
if not exist "%USB%\cloudflare" mkdir "%USB%\cloudflare"
if exist "%ROOT%\usb\cloudflare\SETUP.txt" (
copy /y "%ROOT%\usb\cloudflare\SETUP.txt" "%USB%\cloudflare\SETUP.txt" >nul
)
if exist "%ROOT%\cloudflared-windows-amd64.msi" (
copy /y "%ROOT%\cloudflared-windows-amd64.msi" "%USB%\cloudflare\cloudflared-windows-amd64.msi" >nul
echo [5/7] cloudflared MSI bundled.
) else if exist "%ROOT%\usb\cloudflare\cloudflared-windows-amd64.msi" (
echo [5/7] cloudflared MSI already in usb\cloudflare\
) else (
echo [5/7] WARNING: No cloudflared MSI found. Tunnel auto-install skipped.
)
:: Preserve existing credentials.json if present (never overwrite operator tunnel)
if not exist "%USB%\cloudflare\credentials.json" (
if exist "%ROOT%\usb\cloudflare\credentials.json" (
copy /y "%ROOT%\usb\cloudflare\credentials.json" "%USB%\cloudflare\credentials.json" >nul
)
)
echo [5/7] Launcher synced.
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 6. Summary :: 6. Remove stale nested server mirror (not needed for portable)
:: ----------------------------------------------------------------
echo [6/7] Cleaning stale artifacts...
if exist "%USB%\server" rd /s /q "%USB%\server"
echo [6/7] Done.
:: ----------------------------------------------------------------
:: 7. Ensure data directories exist - preserve existing config and db
:: ----------------------------------------------------------------
echo [7/7] Ensuring data directories...
if not exist "%USB%\data" mkdir "%USB%\data"
if not exist "%USB%\data\builds" mkdir "%USB%\data\builds"
if not exist "%USB%\data\logs" mkdir "%USB%\data\logs"
if not exist "%USB%\data\blueprints" mkdir "%USB%\data\blueprints"
if not exist "%USB%\data\preps" mkdir "%USB%\data\preps"
if not exist "%USB%\data\spread-kits" mkdir "%USB%\data\spread-kits"
if not exist "%USB%\data\uploads" mkdir "%USB%\data\uploads"
if not exist "%USB%\data\cloudflare" mkdir "%USB%\data\cloudflare"
echo [7/7] data\ ready - existing config and db preserved.
:: ----------------------------------------------------------------
:: Summary
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
echo. echo.
echo ================================================================ echo ================================================================
echo USB pack complete! echo USB pack complete!
echo. echo.
echo Contents of %USB%\: echo Folder: %USB%\
echo.
dir /b "%USB%" dir /b "%USB%"
echo. echo.
echo To use: echo To use:
echo 1. Copy the entire USB\ folder to a USB drive (or another PC) echo 1. Copy the entire usb\ folder to your USB drive
echo 2. Double-click LAUNCH.bat echo 2. Double-click LAUNCH.bat on any Windows PC
echo 3. Open http://localhost:8989 in a browser echo 3. Open http://localhost:8989
echo. echo.
echo Toolchain note: echo Your data\ and toolchain\ folders are preserved across repacks.
echo If Go is not installed on the target PC, LAUNCH.bat will echo First launch without Go: LAUNCH.bat downloads toolchain\go\ once.
echo download it automatically on first run and save it to
echo USB\toolchain\ for future use.
echo ================================================================ echo ================================================================
echo. echo.

View File

@@ -123,81 +123,108 @@ if not exist "%ROOT%\data\spread-kits" mkdir "%ROOT%\data\spread-kits"
if not exist "%ROOT%\data\uploads" mkdir "%ROOT%\data\uploads" if not exist "%ROOT%\data\uploads" mkdir "%ROOT%\data\uploads"
if not exist "%ROOT%\data\blueprints" mkdir "%ROOT%\data\blueprints" if not exist "%ROOT%\data\blueprints" mkdir "%ROOT%\data\blueprints"
if not exist "%ROOT%\data\preps" mkdir "%ROOT%\data\preps" if not exist "%ROOT%\data\preps" mkdir "%ROOT%\data\preps"
if not exist "%ROOT%\data\cloudflare" mkdir "%ROOT%\data\cloudflare"
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
:: 5. Cloudflare Tunnel — install MSI, register service with token :: 5. Cloudflare Tunnel — auto-install, configure, start
:: ---------------------------------------------------------------- :: ----------------------------------------------------------------
set "CF_MSI=%ROOT%\cloudflare\cloudflared-windows-amd64.msi" set "CF_DIR=%ROOT%\cloudflare"
set "CF_TOKEN=eyJhIjoiODk1NDc5YWIzNTQwZGFhNmQ2MWFlNzAyYTUxNjQ0NzUiLCJ0IjoiYWFhYzYzMTctMzgyYS00OTM3LTgxY2YtYjM2ZjVkNjZjYTU4IiwicyI6Ik1XRXlaV0FqTlRndE5XTTRPUzAwT0RCa0xXRTNaR010WkdRNU56UTJZMlJoTmpNMiJ9" set "CF_CREDS_BUNDLE=%CF_DIR%\credentials.json"
set "CF_MSI=%CF_DIR%\cloudflared-windows-amd64.msi"
set "CF_HOSTNAME=killa.thetempleofdoom.com" set "CF_HOSTNAME=killa.thetempleofdoom.com"
set "CF_DATA=%ROOT%\data\cloudflare"
set "SERVER_PORT=8989"
set "CF_BIN=" set "CF_BIN="
set "CF_TUNNEL_ID="
set "CF_READY=0" set "CF_READY=0"
:: Step A — locate cloudflared binary (system PATH or default install paths) :: Check credentials exist and are real (not the placeholder)
if not exist "%CF_CREDS_BUNDLE%" goto cf_no_creds
powershell -NoProfile -Command "exit ([string](Get-Content '%CF_CREDS_BUNDLE%') | ConvertFrom-Json | Select-Object -ExpandProperty TunnelID) -eq ''" >nul 2>nul
if errorlevel 1 goto cf_no_creds
:: Parse tunnel ID from credentials JSON
for /f "usebackq delims=" %%i in (`powershell -NoProfile -Command "(Get-Content '%CF_CREDS_BUNDLE%' | ConvertFrom-Json).TunnelID" 2^>nul`) do set "CF_TUNNEL_ID=%%i"
if "!CF_TUNNEL_ID!"=="" goto cf_no_creds
echo [CF] Tunnel ID: !CF_TUNNEL_ID!
:: Stage credentials into data\cloudflare\ (idempotent)
set "CF_CREDS_LOCAL=%CF_DATA%\!CF_TUNNEL_ID!.json"
if not exist "!CF_CREDS_LOCAL!" (
copy "%CF_CREDS_BUNDLE%" "!CF_CREDS_LOCAL!" >nul
echo [CF] Credentials staged to data\cloudflare\
)
:: Always regenerate config.yml with current absolute paths
:: (handles drive-letter changes when USB is moved)
set "CF_CONFIG=%CF_DATA%\config.yml"
powershell -NoProfile -Command "$cfg='%CF_DATA%\config.yml'; $creds='!CF_CREDS_LOCAL!'; $port='%SERVER_PORT%'; $host='%CF_HOSTNAME%'; $id='!CF_TUNNEL_ID!'; Set-Content -Path $cfg -Value @('tunnel: ' + $id, 'credentials-file: ' + $creds, '', 'ingress:', ' - hostname: ' + $host, ' service: http://127.0.0.1:' + $port, ' - service: http_status:404')" >nul 2>nul
echo [CF] Config written for !CF_HOSTNAME! -^> 127.0.0.1:%SERVER_PORT%
:: ---- Locate or install cloudflared ----
where cloudflared >nul 2>nul where cloudflared >nul 2>nul
if not errorlevel 1 ( if not errorlevel 1 (
set "CF_BIN=cloudflared" set "CF_BIN=cloudflared"
goto cf_check_service goto cf_have_bin
) )
if exist "%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe" ( if exist "%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe" (
set "CF_BIN=%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe" set "CF_BIN=%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe"
goto cf_check_service goto cf_have_bin
) )
if exist "%ProgramFiles(x86)%\cloudflare\cloudflared\cloudflared.exe" ( if exist "%ProgramFiles(x86)%\cloudflare\cloudflared\cloudflared.exe" (
set "CF_BIN=%ProgramFiles(x86)%\cloudflare\cloudflared\cloudflared.exe" set "CF_BIN=%ProgramFiles(x86)%\cloudflare\cloudflared\cloudflared.exe"
goto cf_check_service goto cf_have_bin
) )
:: Step B — cloudflared not found, install from bundled MSI :: Not found install from bundled MSI
if not exist "%CF_MSI%" ( if exist "%CF_MSI%" (
echo [CF] WARNING: cloudflared not found and no MSI bundled. Skipping tunnel. echo [CF] cloudflared not found. Installing from bundled MSI...
msiexec /i "%CF_MSI%" /quiet /norestart /l*v "%CF_DATA%\cf-install.log"
echo [CF] MSI install launched - waiting...
ping -n 8 127.0.0.1 >nul
if exist "%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe" (
set "CF_BIN=%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe"
echo [CF] cloudflared installed successfully.
goto cf_have_bin
)
where cloudflared >nul 2>nul
if not errorlevel 1 (
set "CF_BIN=cloudflared"
echo [CF] cloudflared installed successfully.
goto cf_have_bin
)
echo [CF] WARNING: MSI completed but cloudflared not found in PATH.
echo [CF] Try re-running LAUNCH.bat after a reboot.
goto cf_done
) else (
echo [CF] WARNING: cloudflared not installed and no MSI bundled.
goto cf_done goto cf_done
) )
echo [CF] Installing cloudflared from bundled MSI...
msiexec /i "%CF_MSI%" /quiet /norestart
echo [CF] Waiting for MSI to complete...
ping -n 10 127.0.0.1 >nul
:: Re-locate after install :cf_have_bin
where cloudflared >nul 2>nul
if not errorlevel 1 ( set "CF_BIN=cloudflared" & goto cf_check_service )
if exist "%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe" (
set "CF_BIN=%ProgramFiles%\cloudflare\cloudflared\cloudflared.exe"
goto cf_check_service
)
echo [CF] WARNING: MSI installed but cloudflared still not found. Try running as Administrator.
goto cf_done
:cf_check_service
echo [CF] Binary: !CF_BIN! echo [CF] Binary: !CF_BIN!
:: Step C — register tunnel as Windows service if not already installed :: Check if cloudflared tunnel already running (same process = skip)
sc query cloudflared >nul 2>nul tasklist 2>nul | findstr /I "cloudflared" >nul 2>nul
if not errorlevel 1 ( if not errorlevel 1 (
echo [CF] Tunnel service already registered. echo [CF] Tunnel already running on this machine.
goto cf_start_service echo [CF] https://!CF_HOSTNAME!
)
echo [CF] Registering tunnel service with token...
"!CF_BIN!" service install %CF_TOKEN%
if errorlevel 1 (
echo [CF] WARNING: service install failed. Run LAUNCH.bat as Administrator once.
goto cf_done
)
echo [CF] Tunnel service registered.
ping -n 3 127.0.0.1 >nul
:cf_start_service
:: Step D — start the service if not already running
sc query cloudflared | findstr /I "RUNNING" >nul 2>nul
if not errorlevel 1 (
echo [CF] Tunnel already running.
set "CF_READY=1" set "CF_READY=1"
goto cf_done goto cf_done
) )
net start cloudflared >nul 2>nul
ping -n 4 127.0.0.1 >nul :: Start cloudflared tunnel in background
echo [CF] Tunnel live: https://%CF_HOSTNAME% echo [CF] Starting Cloudflare tunnel...
start "" /B "!CF_BIN!" tunnel --config "!CF_CONFIG!" run
ping -n 5 127.0.0.1 >nul
echo [CF] Tunnel live: https://!CF_HOSTNAME!
set "CF_READY=1" set "CF_READY=1"
goto cf_done
:cf_no_creds
echo [CF] No valid credentials.json in cloudflare\
echo [CF] See cloudflare\SETUP.txt to configure your tunnel once.
echo [CF] Running in LAN-only mode this session.
:cf_done :cf_done
@@ -244,7 +271,8 @@ if "!EC!"=="0" (
echo If port %SERVER_PORT% is in use, close other AetherForge windows and retry. echo If port %SERVER_PORT% is in use, close other AetherForge windows and retry.
) )
:: Cloudflare tunnel runs as a Windows service — leave it up between sessions :: On exit, also stop the cloudflared tunnel
taskkill /F /IM cloudflared.exe >nul 2>nul
echo. echo.
pause pause