// coolify-login.mjs — log into the Coolify web UI and save a Playwright storageState. // Needed because this Coolify instance (v4.1.2) does NOT expose the /applications/* // REST API (all 404), so application config must be driven through the UI. // // Usage (from the manager repo root, env loaded via .env.local.ps1): // node deploy_skill/scripts/coolify-ui/coolify-login.mjs [shot.png] // Env: // CF_EMAIL / CF_PASS credentials (map from $env:COOLIFY_EMAIL / $env:COOLIFY_PASSWORD) // CF_BASE base URL, default https://coolify.urieljareth.org // CF_PW_BASE path to a package.json whose node_modules has playwright // (default: this manager repo) import { createRequire } from 'module'; const require = createRequire(process.env.CF_PW_BASE || 'H:/MegaSync/Proyectos/Proxmox & Coolify Manager/package.json'); const { chromium } = require('playwright'); const BASE = (process.env.CF_BASE || 'https://coolify.urieljareth.org').replace(/\/$/, ''); const EMAIL = process.env.CF_EMAIL, PASS = process.env.CF_PASS; const OUT = process.argv[2] || 'coolify_state.json'; const SHOT = process.argv[3] || 'coolify_login.png'; if (!EMAIL || !PASS) { console.error('Missing CF_EMAIL/CF_PASS'); process.exit(2); } const browser = await chromium.launch({ headless: true }); const ctx = await browser.newContext({ viewport: { width: 1600, height: 1000 }, ignoreHTTPSErrors: true }); const page = await ctx.newPage(); try { await page.goto(`${BASE}/login`, { waitUntil: 'domcontentloaded', timeout: 45000 }); await page.waitForTimeout(1500); for (const s of ['input[type="email"]','input[name="email"]','#email']) { const el = await page.$(s); if (el) { await el.fill(EMAIL); break; } } for (const s of ['input[type="password"]','input[name="password"]','#password']) { const el = await page.$(s); if (el) { await el.fill(PASS); break; } } const btn = await page.$('button[type="submit"]') || await page.$('button:has-text("Login")'); if (btn) await btn.click(); else await page.keyboard.press('Enter'); await page.waitForTimeout(4000); await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(()=>{}); const ok = !/\/login/.test(page.url()); console.log('LOGIN_OK:', ok, 'url:', page.url()); await page.screenshot({ path: SHOT }).catch(()=>{}); if (ok) { await ctx.storageState({ path: OUT }); console.log('storageState ->', OUT); process.exitCode = 0; } else { console.log('login failed'); process.exitCode = 1; } } catch (e) { console.error('ERR', e.message); process.exitCode = 1; } finally { await browser.close(); }