From 1b16301a17ad14dba78793e9e7ad6b097459c334 Mon Sep 17 00:00:00 2001 From: "I. A. Naval" <790279+ianonavy@users.noreply.github.com> Date: Sat, 28 Jun 2025 16:27:08 -0400 Subject: [PATCH] Persist open-webui state to app data dir --- backend/main.py | 18 +++++++++++++++ src-tauri/src/lib.rs | 54 +++++++++++++++++++++++++++++++++++++++++--- src/lib/backend.ts | 4 ++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/backend/main.py b/backend/main.py index a47affc..93316e2 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,4 +1,5 @@ import argparse +import os import uvicorn from open_webui import app @@ -14,6 +15,23 @@ def main(): args = parser.parse_args() + # Set up Open WebUI environment variables if they're provided + # These will be set by the Tauri app for proper data persistence + data_dir = os.environ.get("DATA_DIR") + if data_dir: + print(f"Using data directory: {data_dir}") + # Ensure the data directory exists + os.makedirs(data_dir, exist_ok=True) + + # Set additional Open WebUI environment variables for persistence + os.environ.setdefault("WEBUI_DATA_DIR", data_dir) + os.environ.setdefault("WEBUI_UPLOAD_DIR", os.path.join(data_dir, "uploads")) + os.environ.setdefault("WEBUI_CACHE_DIR", os.path.join(data_dir, "cache")) + + # Create subdirectories + os.makedirs(os.environ["WEBUI_UPLOAD_DIR"], exist_ok=True) + os.makedirs(os.environ["WEBUI_CACHE_DIR"], exist_ok=True) + # Run the FastAPI app using uvicorn uvicorn.run(app, host=args.host, port=args.port, log_level="info") diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e466fec..99733d5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -9,6 +9,22 @@ struct AppState { backend_process: Arc>>, } +// Generate a secure secret key for Open WebUI +fn generate_secret_key() -> String { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + use std::time::{SystemTime, UNIX_EPOCH}; + + let mut hasher = DefaultHasher::new(); + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos() + .hash(&mut hasher); + + format!("{:x}", hasher.finish()) +} + // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ #[tauri::command] fn greet(name: &str) -> String { @@ -38,12 +54,33 @@ async fn start_backend(app: tauri::AppHandle) -> Result { // Find an available port let port = find_available_port().map_err(|e| e.to_string())?; - // Start the backend sidecar + // Get the app data directory for persistence + let app_data_dir = app + .path() + .app_data_dir() + .map_err(|e| format!("Failed to get app data directory: {}", e))?; + + // Create the data directory if it doesn't exist + std::fs::create_dir_all(&app_data_dir) + .map_err(|e| format!("Failed to create app data directory: {}", e))?; + + // Set up Open WebUI data directory + let webui_data_dir = app_data_dir.join("open-webui"); + std::fs::create_dir_all(&webui_data_dir) + .map_err(|e| format!("Failed to create Open WebUI data directory: {}", e))?; + + // Start the backend sidecar with proper environment variables let sidecar_command = app .shell() .sidecar("glowpath-backend") .map_err(|e| format!("Failed to create sidecar command: {}", e))? - .args(&["serve", "--port", &port.to_string()]); + .args(&["serve", "--port", &port.to_string()]) + .env("WEBUI_SECRET_KEY", &generate_secret_key()) // Generate a proper secret + .env("DATA_DIR", &webui_data_dir) + .env( + "WEBUI_DATABASE_URL", + format!("sqlite:///{}/webui.db", webui_data_dir.to_string_lossy()), + ); let (mut rx, child) = sidecar_command .spawn() @@ -126,6 +163,16 @@ async fn stop_backend(app: tauri::AppHandle) -> Result<(), String> { Ok(()) } +#[tauri::command] +fn get_data_directory(app: tauri::AppHandle) -> Result { + let app_data_dir = app + .path() + .app_data_dir() + .map_err(|e| format!("Failed to get app data directory: {}", e))?; + + Ok(app_data_dir.to_string_lossy().to_string()) +} + fn find_available_port() -> Result> { use std::net::TcpListener; @@ -146,7 +193,8 @@ pub fn run() { ollama_status, start_backend, get_backend_port, - stop_backend + stop_backend, + get_data_directory ]) .setup(|app| { // Optionally start backend on app startup diff --git a/src/lib/backend.ts b/src/lib/backend.ts index 2e740c4..1f5a039 100644 --- a/src/lib/backend.ts +++ b/src/lib/backend.ts @@ -75,6 +75,10 @@ class BackendService { return this.baseUrl !== null; } + async getDataDirectory(): Promise { + return await invoke("get_data_directory"); + } + async fetch(path: string, options?: RequestInit): Promise { if (!this.baseUrl) { throw new Error("Backend service not initialized");