Persist open-webui state to app data dir

This commit is contained in:
I. A. Naval 2025-06-28 16:27:08 -04:00
parent 482eec9d1f
commit 1b16301a17
Signed by: potato
GPG Key ID: D22B0F9008C43F2B
3 changed files with 73 additions and 3 deletions

View File

@ -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")

View File

@ -9,6 +9,22 @@ struct AppState {
backend_process: Arc<Mutex<Option<tauri_plugin_shell::process::CommandChild>>>,
}
// 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<u16, String> {
// 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<String, String> {
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<u16, Box<dyn std::error::Error>> {
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

View File

@ -75,6 +75,10 @@ class BackendService {
return this.baseUrl !== null;
}
async getDataDirectory(): Promise<string> {
return await invoke<string>("get_data_directory");
}
async fetch(path: string, options?: RequestInit): Promise<Response> {
if (!this.baseUrl) {
throw new Error("Backend service not initialized");