<# .SYNOPSIS Build and start the full InboxIntel stack using deploy/.env for secrets. .EXAMPLE ./deploy/up.ps1 # build + start detached ./deploy/up.ps1 -Proxy # also start the top-level nginx reverse proxy ./deploy/up.ps1 -Foreground # stream logs instead of detaching #> param( [switch]$Proxy, [switch]$Foreground ) $ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot # repo root (deploy/ is one level down) $envFile = Join-Path $PSScriptRoot '.env' if (-not (Test-Path $envFile)) { throw "Missing $envFile. Create it from .env.example with your real secrets." } # Fail fast if a required key is absent or blank. $required = 'POSTGRES_PASSWORD','GOOGLE_CLIENT_ID','GOOGLE_CLIENT_SECRET' $envMap = @{} Get-Content $envFile | ForEach-Object { if ($_ -match '^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$') { $envMap[$Matches[1]] = $Matches[2].Trim() } } $missing = $required | Where-Object { [string]::IsNullOrWhiteSpace($envMap[$_]) } if ($missing) { throw "deploy/.env is missing values for: $($missing -join ', ')" } $composeArgs = @('compose', '--env-file', $envFile) if ($Proxy) { $composeArgs += @('--profile', 'proxy') } $composeArgs += @('up', '--build') if (-not $Foreground) { $composeArgs += '-d' } Push-Location $root try { Write-Host "Starting InboxIntel via docker compose (env: deploy/.env)..." -ForegroundColor Cyan & docker @composeArgs if (-not $Foreground) { & docker compose --env-file $envFile ps Write-Host "`nFrontend: http://localhost:8081 API/Swagger: http://localhost:8080/swagger" -ForegroundColor Green Write-Host "Logs: ./deploy/logs.ps1 Stop: ./deploy/down.ps1" -ForegroundColor DarkGray } } finally { Pop-Location }