#Requires -RunAsAdministrator <# .SYNOPSIS JingTian rclone Client Setup Script for Windows .DESCRIPTION This script sets up rclone sync on a Windows client machine to sync the BenjaminTeam folder with the remote Ubuntu server. .PARAMETER ServerHost The IP address or hostname of the Ubuntu sync server. Default: 20.240.140.78 .PARAMETER ServerUser The SSH username on the Ubuntu server. Default: rclone-sync .PARAMETER ServerPath The remote path on the Ubuntu server. Default: /data/jingtian/BenjaminTeam .PARAMETER LocalPath The local BenjaminTeam folder path. If not specified, the script will attempt to auto-detect or prompt the user. .PARAMETER SyncInterval Sync interval in minutes for the scheduled task. Default: 5 .PARAMETER NonInteractive Run without prompts. Auto-accepts detected BenjaminTeam folder. Use this when running from scripts or scheduled tasks. .EXAMPLE .\setup.ps1 .EXAMPLE .\setup.ps1 -LocalPath "D:\Work\BenjaminTeam" -SyncInterval 10 #> param( [string]$ServerHost = "20.240.140.78", [string]$ServerUser = "rclone-sync", [string]$ServerPath = "/data/jingtian/BenjaminTeam", [string]$LocalPath = "", [int]$SyncInterval = 5, [switch]$NonInteractive ) # Configuration $ErrorActionPreference = "Stop" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $RcloneKeySource = Join-Path $ScriptDir "rclone-key" $RcloneKeyDest = "$env:USERPROFILE\.ssh\jingtian_rclone" $RcloneConfigDir = "$env:APPDATA\rclone" $RcloneConfigFile = "$RcloneConfigDir\rclone.conf" $SyncScriptPath = Join-Path $ScriptDir "sync.ps1" $LogDir = "$env:LOCALAPPDATA\JingTian\logs" # Styling function Write-Header { param([string]$Text) Write-Host "" Write-Host "===========================================" -ForegroundColor Cyan Write-Host $Text -ForegroundColor Cyan Write-Host "===========================================" -ForegroundColor Cyan } function Write-Step { param([string]$Step, [string]$Text) Write-Host "" Write-Host "[$Step] $Text" -ForegroundColor Yellow } function Write-Success { param([string]$Text) Write-Host " [OK] $Text" -ForegroundColor Green } function Write-Info { param([string]$Text) Write-Host " $Text" -ForegroundColor Gray } function Write-ErrorMsg { param([string]$Text) Write-Host " [ERROR] $Text" -ForegroundColor Red } # ============================================================ # MAIN SCRIPT # ============================================================ Write-Header "JingTian rclone Client Setup" Write-Host "" Write-Host "Server: $ServerHost" -ForegroundColor White Write-Host "User: $ServerUser" -ForegroundColor White Write-Host "Remote: $ServerPath" -ForegroundColor White # ------------------------------------------------------------ # Step 1: Check/Install Git # ------------------------------------------------------------ Write-Step "1/7" "Checking Git installation..." $gitPath = "C:\Program Files\Git\bin\git.exe" if (Test-Path $gitPath) { $gitVersion = & $gitPath --version Write-Success "Git already installed: $gitVersion" } else { Write-Info "Git not found. Installing..." $gitInstaller = "$env:TEMP\git-installer.exe" $gitUrl = "https://github.com/git-for-windows/git/releases/download/v2.43.0.windows.1/Git-2.43.0-64-bit.exe" Write-Info "Downloading Git installer..." [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri $gitUrl -OutFile $gitInstaller Write-Info "Installing Git (this may take a few minutes)..." Start-Process -FilePath $gitInstaller -ArgumentList '/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS=icons,ext\reg\shellhere,assoc,assoc_sh' -Wait if (Test-Path $gitPath) { Write-Success "Git installed successfully" } else { Write-ErrorMsg "Git installation failed" exit 1 } } # ------------------------------------------------------------ # Step 2: Check/Install rclone # ------------------------------------------------------------ Write-Step "2/7" "Checking rclone installation..." $rclonePath = "$env:LOCALAPPDATA\rclone\rclone.exe" $rclonePathAlt = "C:\rclone\rclone.exe" if (Test-Path $rclonePath) { $rcloneVersion = & $rclonePath version | Select-Object -First 1 Write-Success "rclone already installed: $rcloneVersion" } elseif (Test-Path $rclonePathAlt) { $rclonePath = $rclonePathAlt $rcloneVersion = & $rclonePath version | Select-Object -First 1 Write-Success "rclone already installed: $rcloneVersion" } else { Write-Info "rclone not found. Installing..." $rcloneZip = "$env:TEMP\rclone.zip" $rcloneExtract = "$env:TEMP\rclone-extract" $rcloneInstallDir = "$env:LOCALAPPDATA\rclone" $rcloneUrl = "https://downloads.rclone.org/rclone-current-windows-amd64.zip" Write-Info "Downloading rclone..." [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri $rcloneUrl -OutFile $rcloneZip Write-Info "Extracting rclone..." if (Test-Path $rcloneExtract) { Remove-Item -Recurse -Force $rcloneExtract } Expand-Archive -Path $rcloneZip -DestinationPath $rcloneExtract # Find the extracted folder (it has version in the name) $extractedFolder = Get-ChildItem -Path $rcloneExtract -Directory | Select-Object -First 1 # Create install directory and copy rclone if (-not (Test-Path $rcloneInstallDir)) { New-Item -ItemType Directory -Path $rcloneInstallDir -Force | Out-Null } Copy-Item -Path "$($extractedFolder.FullName)\rclone.exe" -Destination $rclonePath -Force # Clean up Remove-Item -Recurse -Force $rcloneZip, $rcloneExtract if (Test-Path $rclonePath) { Write-Success "rclone installed to $rclonePath" } else { Write-ErrorMsg "rclone installation failed" exit 1 } } # ------------------------------------------------------------ # Step 3: Detect/Confirm BenjaminTeam folder # ------------------------------------------------------------ Write-Step "3/7" "Locating BenjaminTeam folder..." if ($LocalPath -and (Test-Path $LocalPath)) { Write-Success "Using specified path: $LocalPath" } else { # Common locations to search $searchPaths = @( "$env:USERPROFILE\Documents\BenjaminTeam", "$env:USERPROFILE\Documents\Benjamin Team", "D:\BenjaminTeam", "D:\Benjamin Team", "C:\BenjaminTeam", "C:\Benjamin Team" ) $foundPath = $null foreach ($path in $searchPaths) { if (Test-Path $path) { $foundPath = $path break } } if ($foundPath) { Write-Info "Found BenjaminTeam folder at: $foundPath" if ($NonInteractive) { # Auto-accept in non-interactive mode $LocalPath = $foundPath } else { $confirm = Read-Host " Use this path? (Y/n)" if ($confirm -eq "" -or $confirm -match "^[Yy]") { $LocalPath = $foundPath } } } if (-not $LocalPath -or -not (Test-Path $LocalPath)) { if ($NonInteractive) { Write-ErrorMsg "Could not auto-detect BenjaminTeam folder. Use -LocalPath parameter." exit 1 } Write-Info "Could not auto-detect BenjaminTeam folder." $LocalPath = Read-Host " Enter the full path to your BenjaminTeam folder" if (-not (Test-Path $LocalPath)) { Write-ErrorMsg "Path does not exist: $LocalPath" exit 1 } } Write-Success "Using path: $LocalPath" } # Ensure _LLM_Sync folder exists $llmSyncPath = Join-Path $LocalPath "_LLM_Sync" if (-not (Test-Path $llmSyncPath)) { New-Item -ItemType Directory -Path $llmSyncPath -Force | Out-Null Write-Info "Created _LLM_Sync folder" } # ------------------------------------------------------------ # Step 4: Setup SSH key # ------------------------------------------------------------ Write-Step "4/7" "Setting up SSH key..." # Create .ssh directory if it doesn't exist $sshDir = "$env:USERPROFILE\.ssh" if (-not (Test-Path $sshDir)) { New-Item -ItemType Directory -Path $sshDir -Force | Out-Null } # Copy the SSH key if (-not (Test-Path $RcloneKeySource)) { Write-ErrorMsg "SSH key not found at: $RcloneKeySource" Write-Info "Make sure the rclone-key file is in the same directory as this script." exit 1 } Copy-Item -Path $RcloneKeySource -Destination $RcloneKeyDest -Force Write-Success "SSH key copied to $RcloneKeyDest" # Test SSH connection (fully non-interactive) Write-Info "Testing SSH connection to $ServerHost..." $sshArgs = @( "-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes", "-o", "ConnectTimeout=10", "-o", "UserKnownHostsFile=$env:USERPROFILE\.ssh\known_hosts", "-i", $RcloneKeyDest, "$ServerUser@$ServerHost", "echo 'SSH_OK'" ) try { $sshTest = & ssh @sshArgs 2>&1 if ($sshTest -match "SSH_OK") { Write-Success "SSH connection successful" } else { Write-ErrorMsg "SSH connection failed: $sshTest" Write-Info "Please check the server is running and the key is correct." exit 1 } } catch { Write-ErrorMsg "SSH test error: $_" exit 1 } # ------------------------------------------------------------ # Step 5: Configure rclone # ------------------------------------------------------------ Write-Step "5/7" "Configuring rclone..." # Create rclone config directory if (-not (Test-Path $RcloneConfigDir)) { New-Item -ItemType Directory -Path $RcloneConfigDir -Force | Out-Null } # Generate rclone config $rcloneConfig = @" [jingtian-server] type = sftp host = $ServerHost user = $ServerUser key_file = $RcloneKeyDest shell_type = unix "@ # Write config file Set-Content -Path $RcloneConfigFile -Value $rcloneConfig -Encoding ASCII Write-Success "rclone config written to $RcloneConfigFile" # Test rclone connection Write-Info "Testing rclone connection..." $rcloneTest = & $rclonePath lsd "jingtian-server:$ServerPath" 2>&1 if ($LASTEXITCODE -eq 0) { Write-Success "rclone connection successful" Write-Info "Remote folders:" $rcloneTest | ForEach-Object { Write-Info " $_" } } else { Write-ErrorMsg "rclone connection failed: $rcloneTest" exit 1 } # ------------------------------------------------------------ # Step 6: Create log directory # ------------------------------------------------------------ Write-Step "6/7" "Setting up logging..." if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir -Force | Out-Null } Write-Success "Log directory: $LogDir" # ------------------------------------------------------------ # Step 7: Create Scheduled Task # ------------------------------------------------------------ Write-Step "7/7" "Creating scheduled sync task..." $taskName = "JingTian-Sync" $taskDescription = "Syncs BenjaminTeam folder with remote server every $SyncInterval minutes" # Remove existing task if it exists $existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue if ($existingTask) { Unregister-ScheduledTask -TaskName $taskName -Confirm:$false Write-Info "Removed existing scheduled task" } # Create the scheduled task $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$SyncScriptPath`" -LocalPath `"$LocalPath`" -RclonePath `"$rclonePath`" -LogDir `"$LogDir`"" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes $SyncInterval) -RepetitionDuration (New-TimeSpan -Days 9999) $principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Highest $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 1) Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description $taskDescription | Out-Null Write-Success "Scheduled task created: $taskName" Write-Info "Sync will run every $SyncInterval minutes" # ------------------------------------------------------------ # Summary # ------------------------------------------------------------ Write-Header "Setup Complete!" Write-Host "" Write-Host "Configuration Summary:" -ForegroundColor White Write-Host " Local Path: $LocalPath" -ForegroundColor Gray Write-Host " Remote: $ServerUser@$ServerHost`:$ServerPath" -ForegroundColor Gray Write-Host " Sync Interval: Every $SyncInterval minutes" -ForegroundColor Gray Write-Host " Log Directory: $LogDir" -ForegroundColor Gray Write-Host "" Write-Host "Sync Behavior:" -ForegroundColor White Write-Host " - Main folders: One-way sync (Windows -> Server)" -ForegroundColor Gray Write-Host " - _LLM_Sync: Bidirectional sync" -ForegroundColor Gray Write-Host "" Write-Host "To manually trigger a sync, run:" -ForegroundColor White Write-Host " .\sync.ps1" -ForegroundColor Cyan Write-Host "" Write-Host "To check sync logs:" -ForegroundColor White Write-Host " Get-Content `"$LogDir\sync.log`" -Tail 50" -ForegroundColor Cyan Write-Host ""