diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 57f4712027..f350362f13 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -57,6 +57,11 @@ from open_webui.internal.config import ( def get_config(): return _state.snapshot +def get_config_as_envs(): + all_configs = "" + for config in PERSISTENT_CONFIG_REGISTRY: + all_configs = f'{all_configs}{config.get_as_env()}\n' + return all_configs def save_to_db(data): _state.persist(data) diff --git a/backend/open_webui/internal/config.py b/backend/open_webui/internal/config.py index 46f5b1b67d..fc8e7ec206 100644 --- a/backend/open_webui/internal/config.py +++ b/backend/open_webui/internal/config.py @@ -175,6 +175,13 @@ class ConfigVar: self.config_value = self.value await STATE.persist_async() + def get_as_env(self) -> str: + if isinstance(self.value, list): + value = ",".join(map(str, self.value)) + else: + value = str(self).replace('\n', '\\n').replace('"', '\\"') + return f'{self.env_name}="{value}"' + # ── AppConfig ────────────────────────────────────────────────────────── diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py index c40131f41f..050207beda 100644 --- a/backend/open_webui/routers/configs.py +++ b/backend/open_webui/routers/configs.py @@ -6,8 +6,9 @@ from typing import Optional import aiohttp from fastapi import APIRouter, Depends, HTTPException, Request +from fastapi.responses import PlainTextResponse from mcp.shared.auth import OAuthMetadata -from open_webui.config import BannerModel, async_save_config, get_config, save_config +from open_webui.config import BannerModel, async_save_config, get_config, get_config_as_envs, save_config from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT from open_webui.models.oauth_sessions import OAuthSessions from open_webui.utils.auth import get_admin_user, get_verified_user @@ -62,6 +63,10 @@ async def import_config(request: Request, form_data: ImportConfigForm, user=Depe async def export_config(user=Depends(get_admin_user)): return get_config() +@router.get('/export/env') +async def export_config_as_env(user=Depends(get_admin_user)): + return PlainTextResponse(get_config_as_envs(), media_type='text/plain') + ############################ # Connections Config diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 7859a4e787..770ea042f2 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -58,6 +58,33 @@ export const exportConfig = async (token: string) => { return res; }; +export const exportConfigAsEnv = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/export/env`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.text(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getConnectionsConfig = async (token: string) => { let error = null; diff --git a/src/lib/components/admin/Settings/Database.svelte b/src/lib/components/admin/Settings/Database.svelte index 8cc314661f..ef7a76e384 100644 --- a/src/lib/components/admin/Settings/Database.svelte +++ b/src/lib/components/admin/Settings/Database.svelte @@ -8,7 +8,7 @@ import { toast } from 'svelte-sonner'; import { getAllUserChats } from '$lib/apis/chats'; import { getAllUsers } from '$lib/apis/users'; - import { exportConfig, importConfig } from '$lib/apis/configs'; + import { exportConfig, exportConfigAsEnv, importConfig } from '$lib/apis/configs'; const i18n = getContext('i18n'); @@ -113,6 +113,25 @@ + +
+
+
{$i18n.t('Export Config as .env')}
+ +
+
{#if $config?.features.enable_admin_export ?? true} diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index bc583f1958..cbbda7729d 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -903,6 +903,7 @@ "Export chat (.json)": "Chat exportieren (.json)", "Export Chats": "Chats exportieren", "Export Config": "Konfiguration exportieren", + "Export Config as .env": "Konfiguration als .env exportieren", "Export Models": "Modelle exportieren", "Export Prompts": "Prompts exportieren", "Export to CSV": "Nach CSV exportieren", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index ed6da124f6..c9825878fe 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -903,6 +903,7 @@ "Export chat (.json)": "", "Export Chats": "", "Export Config": "", + "Export Config as .env": "", "Export Models": "", "Export Prompts": "", "Export to CSV": "",