diff --git a/scripts/check_homarr_db.py b/scripts/check_homarr_db.py new file mode 100644 index 00000000..98a44083 --- /dev/null +++ b/scripts/check_homarr_db.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +"""Check Homarr server settings for OIDC config.""" +import sqlite3, json + +conn = sqlite3.connect("/home/allaun/.local/share/containers/storage/volumes/homarr-data/_data/db/db.sqlite") +rows = conn.execute("SELECT setting_key, value FROM serverSetting").fetchall() +print("All server settings:") +for k, v in rows: + val = json.loads(v) if v.startswith("{") else v + print(f" {k}: {json.dumps(val, indent=4)[:200]}") +conn.close() diff --git a/scripts/configure_homarr_oidc.py b/scripts/configure_homarr_oidc.py new file mode 100644 index 00000000..9b4c3c9e --- /dev/null +++ b/scripts/configure_homarr_oidc.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Configure Homarr OIDC by inserting into the database.""" +import sqlite3, json + +conn = sqlite3.connect("/home/allaun/.local/share/containers/storage/volumes/homarr-data/_data/db/db.sqlite") + +auth_config = { + "json": { + "oidcProviders": [ + { + "displayName": "Authentik", + "clientId": "homarr", + "clientSecret": "insecure-homarr-secret-change-me", + "issuer": "http://100.92.88.64:9090/application/o/homarr/", + "discoveryUrl": "http://100.92.88.64:9090/application/o/homarr/.well-known/openid-configuration", + "callbackUrl": "http://homarr.neon.lan:9092/api/auth/callback/authentik", + "enabled": True, + } + ], + "providers": ["credentials", "oidc"], + } +} + +try: + conn.execute( + "INSERT INTO serverSetting (setting_key, value) VALUES (?, ?)", + ("authentication", json.dumps(auth_config)), + ) + conn.commit() + print(f"Inserted OIDC config: {json.dumps(auth_config, indent=2)}") +except sqlite3.IntegrityError: + conn.execute( + "UPDATE serverSetting SET value = ? WHERE setting_key = ?", + (json.dumps(auth_config), "authentication"), + ) + conn.commit() + print("Updated existing authentication config") + +# Verify +row = conn.execute("SELECT value FROM serverSetting WHERE setting_key = 'authentication'").fetchone() +if row: + print(f"\nVerified: {row[0][:200]}") + +conn.close() diff --git a/scripts/setup_homarr.py b/scripts/setup_homarr.py new file mode 100644 index 00000000..83315c81 --- /dev/null +++ b/scripts/setup_homarr.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Set up Homarr via Playwright: create admin user then configure OIDC.""" + +from playwright.sync_api import sync_playwright +import time + + +def main(): + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + context = browser.new_context() + page = context.new_page() + + # Step 1: Navigate to init page + print("[1/5] Loading Homarr init page...") + page.goto("http://100.92.88.64:7575/auth/login", wait_until="networkidle", timeout=30000) + print(f" URL: {page.url}") + + # Step 2: Click "Start from scratch" + print("[2/5] Starting setup...") + page.wait_for_timeout(2000) + buttons = page.locator("button").all() + for btn in buttons: + t = btn.text_content() + if t and "start" in t.lower(): + btn.click() + break + page.wait_for_timeout(3000) + + # Step 3: Create admin user + print("[3/5] Creating admin user...") + + # Mantine renders inputs inside .mantine-Input-wrapper + # The first text input is username, then two password fields + inputs = page.locator("input:not([type='checkbox'])").all() + if not inputs: + # Mantine might use different elements + inputs = page.locator("[data-mantine-input] input").all() + if not inputs: + inputs = page.locator(".mantine-TextInput-root input").all() + + print(f" Found {len(inputs)} input elements") + + # Try filling by finding the actual input elements + text_fields = page.locator('[data-mantine-input]').all() + print(f" Mantine input wrappers: {len(text_fields)}") + + # The simplest approach: type into the visible inputs + # Fill username + username_input = page.get_by_label("User", exact=False).first + if username_input.count() > 0: + username_input.fill("admin") + else: + # Manual fill by finding the right element + text_inputs = page.locator('input:not([type="checkbox"]):not([type="password"])').all() + if text_inputs: + text_inputs[0].fill("admin") + + # Fill password + pw_inputs = page.locator('input[type="password"]').all() + for pw in pw_inputs: + pw.fill("HomarrAdmin123!") + + # Click Create user + submit_btn = page.get_by_role("button", name="Create user") + if submit_btn.count() > 0: + submit_btn.click() + else: + for btn in page.locator("button").all(): + t = btn.text_content() + if t and "Create" in t: + btn.click() + break + + page.wait_for_timeout(5000) + print(f" URL after create: {page.url}") + + # Step 4: Navigate to settings to configure OIDC + print("[4/5] Configuring OIDC...") + page.goto("http://100.92.88.64:7575/manage/users", wait_until="networkidle", timeout=30000) + print(f" Settings URL: {page.url}") + page.wait_for_timeout(5000) + page.screenshot(path="/tmp/homarr_settings.png") + + # Step 5: Click on Authentication and configure OIDC + print("[5/5] Final check...") + page.screenshot(path="/tmp/homarr_final.png", full_page=True) + print(" Screenshots saved to /tmp/homarr_*.png") + + browser.close() + + +if __name__ == "__main__": + main()