coolmanx commited on
Commit
3196739
·
verified ·
1 Parent(s): 9f28b4f

Update backend/open_webui/env.py

Browse files
Files changed (1) hide show
  1. backend/open_webui/env.py +384 -384
backend/open_webui/env.py CHANGED
@@ -1,384 +1,384 @@
1
- import importlib.metadata
2
- import json
3
- import logging
4
- import os
5
- import pkgutil
6
- import sys
7
- import shutil
8
- from pathlib import Path
9
-
10
- import markdown
11
- from bs4 import BeautifulSoup
12
- from open_webui.constants import ERROR_MESSAGES
13
-
14
- ####################################
15
- # Load .env file
16
- ####################################
17
-
18
- OPEN_WEBUI_DIR = Path(__file__).parent # the path containing this file
19
- print(OPEN_WEBUI_DIR)
20
-
21
- BACKEND_DIR = OPEN_WEBUI_DIR.parent # the path containing this file
22
- BASE_DIR = BACKEND_DIR.parent # the path containing the backend/
23
-
24
- print(BACKEND_DIR)
25
- print(BASE_DIR)
26
-
27
- try:
28
- from dotenv import find_dotenv, load_dotenv
29
-
30
- load_dotenv(find_dotenv(str(BASE_DIR / ".env")))
31
- except ImportError:
32
- print("dotenv not installed, skipping...")
33
-
34
- DOCKER = os.environ.get("DOCKER", "False").lower() == "true"
35
-
36
- # device type embedding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
37
- USE_CUDA = os.environ.get("USE_CUDA_DOCKER", "false")
38
-
39
- if USE_CUDA.lower() == "true":
40
- try:
41
- import torch
42
-
43
- assert torch.cuda.is_available(), "CUDA not available"
44
- DEVICE_TYPE = "cuda"
45
- except Exception as e:
46
- cuda_error = (
47
- "Error when testing CUDA but USE_CUDA_DOCKER is true. "
48
- f"Resetting USE_CUDA_DOCKER to false: {e}"
49
- )
50
- os.environ["USE_CUDA_DOCKER"] = "false"
51
- USE_CUDA = "false"
52
- DEVICE_TYPE = "cpu"
53
- else:
54
- DEVICE_TYPE = "cpu"
55
-
56
-
57
- ####################################
58
- # LOGGING
59
- ####################################
60
-
61
- log_levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]
62
-
63
- GLOBAL_LOG_LEVEL = os.environ.get("GLOBAL_LOG_LEVEL", "").upper()
64
- if GLOBAL_LOG_LEVEL in log_levels:
65
- logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL, force=True)
66
- else:
67
- GLOBAL_LOG_LEVEL = "INFO"
68
-
69
- log = logging.getLogger(__name__)
70
- log.info(f"GLOBAL_LOG_LEVEL: {GLOBAL_LOG_LEVEL}")
71
-
72
- if "cuda_error" in locals():
73
- log.exception(cuda_error)
74
-
75
- log_sources = [
76
- "AUDIO",
77
- "COMFYUI",
78
- "CONFIG",
79
- "DB",
80
- "IMAGES",
81
- "MAIN",
82
- "MODELS",
83
- "OLLAMA",
84
- "OPENAI",
85
- "RAG",
86
- "WEBHOOK",
87
- "SOCKET",
88
- ]
89
-
90
- SRC_LOG_LEVELS = {}
91
-
92
- for source in log_sources:
93
- log_env_var = source + "_LOG_LEVEL"
94
- SRC_LOG_LEVELS[source] = os.environ.get(log_env_var, "").upper()
95
- if SRC_LOG_LEVELS[source] not in log_levels:
96
- SRC_LOG_LEVELS[source] = GLOBAL_LOG_LEVEL
97
- log.info(f"{log_env_var}: {SRC_LOG_LEVELS[source]}")
98
-
99
- log.setLevel(SRC_LOG_LEVELS["CONFIG"])
100
-
101
-
102
- WEBUI_NAME = os.environ.get("WEBUI_NAME", "Open WebUI")
103
- if WEBUI_NAME != "Open WebUI":
104
- WEBUI_NAME += " (Open WebUI)"
105
-
106
- WEBUI_URL = os.environ.get("WEBUI_URL", "http://localhost:3000")
107
-
108
- WEBUI_FAVICON_URL = "https://openwebui.com/favicon.png"
109
-
110
-
111
- ####################################
112
- # ENV (dev,test,prod)
113
- ####################################
114
-
115
- ENV = os.environ.get("ENV", "dev")
116
-
117
- FROM_INIT_PY = os.environ.get("FROM_INIT_PY", "False").lower() == "true"
118
-
119
- if FROM_INIT_PY:
120
- PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
121
- else:
122
- try:
123
- PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
124
- except Exception:
125
- PACKAGE_DATA = {"version": "0.0.0"}
126
-
127
-
128
- VERSION = PACKAGE_DATA["version"]
129
-
130
-
131
- # Function to parse each section
132
- def parse_section(section):
133
- items = []
134
- for li in section.find_all("li"):
135
- # Extract raw HTML string
136
- raw_html = str(li)
137
-
138
- # Extract text without HTML tags
139
- text = li.get_text(separator=" ", strip=True)
140
-
141
- # Split into title and content
142
- parts = text.split(": ", 1)
143
- title = parts[0].strip() if len(parts) > 1 else ""
144
- content = parts[1].strip() if len(parts) > 1 else text
145
-
146
- items.append({"title": title, "content": content, "raw": raw_html})
147
- return items
148
-
149
-
150
- try:
151
- changelog_path = BASE_DIR / "CHANGELOG.md"
152
- with open(str(changelog_path.absolute()), "r", encoding="utf8") as file:
153
- changelog_content = file.read()
154
-
155
- except Exception:
156
- changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode()
157
-
158
-
159
- # Convert markdown content to HTML
160
- html_content = markdown.markdown(changelog_content)
161
-
162
- # Parse the HTML content
163
- soup = BeautifulSoup(html_content, "html.parser")
164
-
165
- # Initialize JSON structure
166
- changelog_json = {}
167
-
168
- # Iterate over each version
169
- for version in soup.find_all("h2"):
170
- version_number = version.get_text().strip().split(" - ")[0][1:-1] # Remove brackets
171
- date = version.get_text().strip().split(" - ")[1]
172
-
173
- version_data = {"date": date}
174
-
175
- # Find the next sibling that is a h3 tag (section title)
176
- current = version.find_next_sibling()
177
-
178
- while current and current.name != "h2":
179
- if current.name == "h3":
180
- section_title = current.get_text().lower() # e.g., "added", "fixed"
181
- section_items = parse_section(current.find_next_sibling("ul"))
182
- version_data[section_title] = section_items
183
-
184
- # Move to the next element
185
- current = current.find_next_sibling()
186
-
187
- changelog_json[version_number] = version_data
188
-
189
-
190
- CHANGELOG = changelog_json
191
-
192
- ####################################
193
- # SAFE_MODE
194
- ####################################
195
-
196
- SAFE_MODE = os.environ.get("SAFE_MODE", "false").lower() == "true"
197
-
198
- ####################################
199
- # WEBUI_BUILD_HASH
200
- ####################################
201
-
202
- WEBUI_BUILD_HASH = os.environ.get("WEBUI_BUILD_HASH", "dev-build")
203
-
204
- ####################################
205
- # DATA/FRONTEND BUILD DIR
206
- ####################################
207
-
208
- DATA_DIR = Path(os.getenv("DATA_DIR", BACKEND_DIR / "data")).resolve()
209
-
210
- if FROM_INIT_PY:
211
- NEW_DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data")).resolve()
212
- NEW_DATA_DIR.mkdir(parents=True, exist_ok=True)
213
-
214
- # Check if the data directory exists in the package directory
215
- if DATA_DIR.exists() and DATA_DIR != NEW_DATA_DIR:
216
- log.info(f"Moving {DATA_DIR} to {NEW_DATA_DIR}")
217
- for item in DATA_DIR.iterdir():
218
- dest = NEW_DATA_DIR / item.name
219
- if item.is_dir():
220
- shutil.copytree(item, dest, dirs_exist_ok=True)
221
- else:
222
- shutil.copy2(item, dest)
223
-
224
- # Zip the data directory
225
- shutil.make_archive(DATA_DIR.parent / "open_webui_data", "zip", DATA_DIR)
226
-
227
- # Remove the old data directory
228
- shutil.rmtree(DATA_DIR)
229
-
230
- DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data"))
231
-
232
-
233
- STATIC_DIR = Path(os.getenv("STATIC_DIR", OPEN_WEBUI_DIR / "static"))
234
-
235
- FONTS_DIR = Path(os.getenv("FONTS_DIR", OPEN_WEBUI_DIR / "static" / "fonts"))
236
-
237
- FRONTEND_BUILD_DIR = Path(os.getenv("FRONTEND_BUILD_DIR", BASE_DIR / "build")).resolve()
238
-
239
- if FROM_INIT_PY:
240
- FRONTEND_BUILD_DIR = Path(
241
- os.getenv("FRONTEND_BUILD_DIR", OPEN_WEBUI_DIR / "frontend")
242
- ).resolve()
243
-
244
-
245
- ####################################
246
- # Database
247
- ####################################
248
-
249
- # Check if the file exists
250
- if os.path.exists(f"{DATA_DIR}/ollama.db"):
251
- # Rename the file
252
- os.rename(f"{DATA_DIR}/ollama.db", f"{DATA_DIR}/webui.db")
253
- log.info("Database migrated from Ollama-WebUI successfully.")
254
- else:
255
- pass
256
-
257
- DATABASE_URL = os.environ.get("DATABASE_URL", f"sqlite:///{DATA_DIR}/webui.db")
258
-
259
- # Replace the postgres:// with postgresql://
260
- if "postgres://" in DATABASE_URL:
261
- DATABASE_URL = DATABASE_URL.replace("postgres://", "postgresql://")
262
-
263
- DATABASE_POOL_SIZE = os.environ.get("DATABASE_POOL_SIZE", 0)
264
-
265
- if DATABASE_POOL_SIZE == "":
266
- DATABASE_POOL_SIZE = 0
267
- else:
268
- try:
269
- DATABASE_POOL_SIZE = int(DATABASE_POOL_SIZE)
270
- except Exception:
271
- DATABASE_POOL_SIZE = 0
272
-
273
- DATABASE_POOL_MAX_OVERFLOW = os.environ.get("DATABASE_POOL_MAX_OVERFLOW", 0)
274
-
275
- if DATABASE_POOL_MAX_OVERFLOW == "":
276
- DATABASE_POOL_MAX_OVERFLOW = 0
277
- else:
278
- try:
279
- DATABASE_POOL_MAX_OVERFLOW = int(DATABASE_POOL_MAX_OVERFLOW)
280
- except Exception:
281
- DATABASE_POOL_MAX_OVERFLOW = 0
282
-
283
- DATABASE_POOL_TIMEOUT = os.environ.get("DATABASE_POOL_TIMEOUT", 30)
284
-
285
- if DATABASE_POOL_TIMEOUT == "":
286
- DATABASE_POOL_TIMEOUT = 30
287
- else:
288
- try:
289
- DATABASE_POOL_TIMEOUT = int(DATABASE_POOL_TIMEOUT)
290
- except Exception:
291
- DATABASE_POOL_TIMEOUT = 30
292
-
293
- DATABASE_POOL_RECYCLE = os.environ.get("DATABASE_POOL_RECYCLE", 3600)
294
-
295
- if DATABASE_POOL_RECYCLE == "":
296
- DATABASE_POOL_RECYCLE = 3600
297
- else:
298
- try:
299
- DATABASE_POOL_RECYCLE = int(DATABASE_POOL_RECYCLE)
300
- except Exception:
301
- DATABASE_POOL_RECYCLE = 3600
302
-
303
- RESET_CONFIG_ON_START = (
304
- os.environ.get("RESET_CONFIG_ON_START", "False").lower() == "true"
305
- )
306
-
307
- ####################################
308
- # REDIS
309
- ####################################
310
-
311
- REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
312
-
313
- ####################################
314
- # WEBUI_AUTH (Required for security)
315
- ####################################
316
-
317
- WEBUI_AUTH = os.environ.get("WEBUI_AUTH", "True").lower() == "true"
318
- WEBUI_AUTH_TRUSTED_EMAIL_HEADER = os.environ.get(
319
- "WEBUI_AUTH_TRUSTED_EMAIL_HEADER", None
320
- )
321
- WEBUI_AUTH_TRUSTED_NAME_HEADER = os.environ.get("WEBUI_AUTH_TRUSTED_NAME_HEADER", None)
322
-
323
-
324
- ####################################
325
- # WEBUI_SECRET_KEY
326
- ####################################
327
-
328
- WEBUI_SECRET_KEY = os.environ.get(
329
- "WEBUI_SECRET_KEY",
330
- os.environ.get(
331
- "WEBUI_JWT_SECRET_KEY", "t0p-s3cr3t"
332
- ), # DEPRECATED: remove at next major version
333
- )
334
-
335
- WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get(
336
- "WEBUI_SESSION_COOKIE_SAME_SITE",
337
- os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax"),
338
- )
339
-
340
- WEBUI_SESSION_COOKIE_SECURE = os.environ.get(
341
- "WEBUI_SESSION_COOKIE_SECURE",
342
- os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true",
343
- )
344
-
345
- if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
346
- raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
347
-
348
- ENABLE_WEBSOCKET_SUPPORT = (
349
- os.environ.get("ENABLE_WEBSOCKET_SUPPORT", "True").lower() == "true"
350
- )
351
-
352
- WEBSOCKET_MANAGER = os.environ.get("WEBSOCKET_MANAGER", "")
353
-
354
- WEBSOCKET_REDIS_URL = os.environ.get("WEBSOCKET_REDIS_URL", REDIS_URL)
355
-
356
- AIOHTTP_CLIENT_TIMEOUT = os.environ.get("AIOHTTP_CLIENT_TIMEOUT", "")
357
-
358
- if AIOHTTP_CLIENT_TIMEOUT == "":
359
- AIOHTTP_CLIENT_TIMEOUT = None
360
- else:
361
- try:
362
- AIOHTTP_CLIENT_TIMEOUT = int(AIOHTTP_CLIENT_TIMEOUT)
363
- except Exception:
364
- AIOHTTP_CLIENT_TIMEOUT = 300
365
-
366
- AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = os.environ.get(
367
- "AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST", "3"
368
- )
369
-
370
- if AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST == "":
371
- AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = None
372
- else:
373
- try:
374
- AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = int(
375
- AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST
376
- )
377
- except Exception:
378
- AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = 3
379
-
380
- ####################################
381
- # OFFLINE_MODE
382
- ####################################
383
-
384
- OFFLINE_MODE = os.environ.get("OFFLINE_MODE", "false").lower() == "true"
 
1
+ import importlib.metadata
2
+ import json
3
+ import logging
4
+ import os
5
+ import pkgutil
6
+ import sys
7
+ import shutil
8
+ from pathlib import Path
9
+
10
+ import markdown
11
+ from bs4 import BeautifulSoup
12
+ from open_webui.constants import ERROR_MESSAGES
13
+
14
+ ####################################
15
+ # Load .env file
16
+ ####################################
17
+
18
+ OPEN_WEBUI_DIR = Path(__file__).parent # the path containing this file
19
+ print(OPEN_WEBUI_DIR)
20
+
21
+ BACKEND_DIR = OPEN_WEBUI_DIR.parent # the path containing this file
22
+ BASE_DIR = BACKEND_DIR.parent # the path containing the backend/
23
+
24
+ print(BACKEND_DIR)
25
+ print(BASE_DIR)
26
+
27
+ try:
28
+ from dotenv import find_dotenv, load_dotenv
29
+
30
+ load_dotenv(find_dotenv(str(BASE_DIR / ".env")))
31
+ except ImportError:
32
+ print("dotenv not installed, skipping...")
33
+
34
+ DOCKER = os.environ.get("DOCKER", "False").lower() == "true"
35
+
36
+ # device type embedding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
37
+ USE_CUDA = os.environ.get("USE_CUDA_DOCKER", "false")
38
+
39
+ if USE_CUDA.lower() == "true":
40
+ try:
41
+ import torch
42
+
43
+ assert torch.cuda.is_available(), "CUDA not available"
44
+ DEVICE_TYPE = "cuda"
45
+ except Exception as e:
46
+ cuda_error = (
47
+ "Error when testing CUDA but USE_CUDA_DOCKER is true. "
48
+ f"Resetting USE_CUDA_DOCKER to false: {e}"
49
+ )
50
+ os.environ["USE_CUDA_DOCKER"] = "false"
51
+ USE_CUDA = "false"
52
+ DEVICE_TYPE = "cpu"
53
+ else:
54
+ DEVICE_TYPE = "cpu"
55
+
56
+
57
+ ####################################
58
+ # LOGGING
59
+ ####################################
60
+
61
+ log_levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]
62
+
63
+ GLOBAL_LOG_LEVEL = os.environ.get("GLOBAL_LOG_LEVEL", "ERROR").upper()
64
+ if GLOBAL_LOG_LEVEL in log_levels:
65
+ logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL, force=True)
66
+ else:
67
+ GLOBAL_LOG_LEVEL = "ERROR"
68
+
69
+ log = logging.getLogger(__name__)
70
+ log.info(f"GLOBAL_LOG_LEVEL: {GLOBAL_LOG_LEVEL}")
71
+
72
+ if "cuda_error" in locals():
73
+ log.exception(cuda_error)
74
+
75
+ log_sources = [
76
+ "AUDIO",
77
+ "COMFYUI",
78
+ "CONFIG",
79
+ "DB",
80
+ "IMAGES",
81
+ "MAIN",
82
+ "MODELS",
83
+ "OLLAMA",
84
+ "OPENAI",
85
+ "RAG",
86
+ "WEBHOOK",
87
+ "SOCKET",
88
+ ]
89
+
90
+ SRC_LOG_LEVELS = {}
91
+
92
+ for source in log_sources:
93
+ log_env_var = source + "_LOG_LEVEL"
94
+ SRC_LOG_LEVELS[source] = os.environ.get(log_env_var, "").upper()
95
+ if SRC_LOG_LEVELS[source] not in log_levels:
96
+ SRC_LOG_LEVELS[source] = GLOBAL_LOG_LEVEL
97
+ log.info(f"{log_env_var}: {SRC_LOG_LEVELS[source]}")
98
+
99
+ log.setLevel(SRC_LOG_LEVELS["CONFIG"])
100
+
101
+
102
+ WEBUI_NAME = os.environ.get("WEBUI_NAME", "Open WebUI")
103
+ if WEBUI_NAME != "Open WebUI":
104
+ WEBUI_NAME += " (Open WebUI)"
105
+
106
+ WEBUI_URL = os.environ.get("WEBUI_URL", "http://localhost:3000")
107
+
108
+ WEBUI_FAVICON_URL = "https://openwebui.com/favicon.png"
109
+
110
+
111
+ ####################################
112
+ # ENV (dev,test,prod)
113
+ ####################################
114
+
115
+ ENV = os.environ.get("ENV", "dev")
116
+
117
+ FROM_INIT_PY = os.environ.get("FROM_INIT_PY", "False").lower() == "true"
118
+
119
+ if FROM_INIT_PY:
120
+ PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
121
+ else:
122
+ try:
123
+ PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
124
+ except Exception:
125
+ PACKAGE_DATA = {"version": "0.0.0"}
126
+
127
+
128
+ VERSION = PACKAGE_DATA["version"]
129
+
130
+
131
+ # Function to parse each section
132
+ def parse_section(section):
133
+ items = []
134
+ for li in section.find_all("li"):
135
+ # Extract raw HTML string
136
+ raw_html = str(li)
137
+
138
+ # Extract text without HTML tags
139
+ text = li.get_text(separator=" ", strip=True)
140
+
141
+ # Split into title and content
142
+ parts = text.split(": ", 1)
143
+ title = parts[0].strip() if len(parts) > 1 else ""
144
+ content = parts[1].strip() if len(parts) > 1 else text
145
+
146
+ items.append({"title": title, "content": content, "raw": raw_html})
147
+ return items
148
+
149
+
150
+ try:
151
+ changelog_path = BASE_DIR / "CHANGELOG.md"
152
+ with open(str(changelog_path.absolute()), "r", encoding="utf8") as file:
153
+ changelog_content = file.read()
154
+
155
+ except Exception:
156
+ changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode()
157
+
158
+
159
+ # Convert markdown content to HTML
160
+ html_content = markdown.markdown(changelog_content)
161
+
162
+ # Parse the HTML content
163
+ soup = BeautifulSoup(html_content, "html.parser")
164
+
165
+ # Initialize JSON structure
166
+ changelog_json = {}
167
+
168
+ # Iterate over each version
169
+ for version in soup.find_all("h2"):
170
+ version_number = version.get_text().strip().split(" - ")[0][1:-1] # Remove brackets
171
+ date = version.get_text().strip().split(" - ")[1]
172
+
173
+ version_data = {"date": date}
174
+
175
+ # Find the next sibling that is a h3 tag (section title)
176
+ current = version.find_next_sibling()
177
+
178
+ while current and current.name != "h2":
179
+ if current.name == "h3":
180
+ section_title = current.get_text().lower() # e.g., "added", "fixed"
181
+ section_items = parse_section(current.find_next_sibling("ul"))
182
+ version_data[section_title] = section_items
183
+
184
+ # Move to the next element
185
+ current = current.find_next_sibling()
186
+
187
+ changelog_json[version_number] = version_data
188
+
189
+
190
+ CHANGELOG = changelog_json
191
+
192
+ ####################################
193
+ # SAFE_MODE
194
+ ####################################
195
+
196
+ SAFE_MODE = os.environ.get("SAFE_MODE", "false").lower() == "true"
197
+
198
+ ####################################
199
+ # WEBUI_BUILD_HASH
200
+ ####################################
201
+
202
+ WEBUI_BUILD_HASH = os.environ.get("WEBUI_BUILD_HASH", "dev-build")
203
+
204
+ ####################################
205
+ # DATA/FRONTEND BUILD DIR
206
+ ####################################
207
+
208
+ DATA_DIR = Path(os.getenv("DATA_DIR", BACKEND_DIR / "data")).resolve()
209
+
210
+ if FROM_INIT_PY:
211
+ NEW_DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data")).resolve()
212
+ NEW_DATA_DIR.mkdir(parents=True, exist_ok=True)
213
+
214
+ # Check if the data directory exists in the package directory
215
+ if DATA_DIR.exists() and DATA_DIR != NEW_DATA_DIR:
216
+ log.info(f"Moving {DATA_DIR} to {NEW_DATA_DIR}")
217
+ for item in DATA_DIR.iterdir():
218
+ dest = NEW_DATA_DIR / item.name
219
+ if item.is_dir():
220
+ shutil.copytree(item, dest, dirs_exist_ok=True)
221
+ else:
222
+ shutil.copy2(item, dest)
223
+
224
+ # Zip the data directory
225
+ shutil.make_archive(DATA_DIR.parent / "open_webui_data", "zip", DATA_DIR)
226
+
227
+ # Remove the old data directory
228
+ shutil.rmtree(DATA_DIR)
229
+
230
+ DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data"))
231
+
232
+
233
+ STATIC_DIR = Path(os.getenv("STATIC_DIR", OPEN_WEBUI_DIR / "static"))
234
+
235
+ FONTS_DIR = Path(os.getenv("FONTS_DIR", OPEN_WEBUI_DIR / "static" / "fonts"))
236
+
237
+ FRONTEND_BUILD_DIR = Path(os.getenv("FRONTEND_BUILD_DIR", BASE_DIR / "build")).resolve()
238
+
239
+ if FROM_INIT_PY:
240
+ FRONTEND_BUILD_DIR = Path(
241
+ os.getenv("FRONTEND_BUILD_DIR", OPEN_WEBUI_DIR / "frontend")
242
+ ).resolve()
243
+
244
+
245
+ ####################################
246
+ # Database
247
+ ####################################
248
+
249
+ # Check if the file exists
250
+ if os.path.exists(f"{DATA_DIR}/ollama.db"):
251
+ # Rename the file
252
+ os.rename(f"{DATA_DIR}/ollama.db", f"{DATA_DIR}/webui.db")
253
+ log.info("Database migrated from Ollama-WebUI successfully.")
254
+ else:
255
+ pass
256
+
257
+ DATABASE_URL = os.environ.get("DATABASE_URL", f"sqlite:///{DATA_DIR}/webui.db")
258
+
259
+ # Replace the postgres:// with postgresql://
260
+ if "postgres://" in DATABASE_URL:
261
+ DATABASE_URL = DATABASE_URL.replace("postgres://", "postgresql://")
262
+
263
+ DATABASE_POOL_SIZE = os.environ.get("DATABASE_POOL_SIZE", 0)
264
+
265
+ if DATABASE_POOL_SIZE == "":
266
+ DATABASE_POOL_SIZE = 0
267
+ else:
268
+ try:
269
+ DATABASE_POOL_SIZE = int(DATABASE_POOL_SIZE)
270
+ except Exception:
271
+ DATABASE_POOL_SIZE = 0
272
+
273
+ DATABASE_POOL_MAX_OVERFLOW = os.environ.get("DATABASE_POOL_MAX_OVERFLOW", 0)
274
+
275
+ if DATABASE_POOL_MAX_OVERFLOW == "":
276
+ DATABASE_POOL_MAX_OVERFLOW = 0
277
+ else:
278
+ try:
279
+ DATABASE_POOL_MAX_OVERFLOW = int(DATABASE_POOL_MAX_OVERFLOW)
280
+ except Exception:
281
+ DATABASE_POOL_MAX_OVERFLOW = 0
282
+
283
+ DATABASE_POOL_TIMEOUT = os.environ.get("DATABASE_POOL_TIMEOUT", 30)
284
+
285
+ if DATABASE_POOL_TIMEOUT == "":
286
+ DATABASE_POOL_TIMEOUT = 30
287
+ else:
288
+ try:
289
+ DATABASE_POOL_TIMEOUT = int(DATABASE_POOL_TIMEOUT)
290
+ except Exception:
291
+ DATABASE_POOL_TIMEOUT = 30
292
+
293
+ DATABASE_POOL_RECYCLE = os.environ.get("DATABASE_POOL_RECYCLE", 3600)
294
+
295
+ if DATABASE_POOL_RECYCLE == "":
296
+ DATABASE_POOL_RECYCLE = 3600
297
+ else:
298
+ try:
299
+ DATABASE_POOL_RECYCLE = int(DATABASE_POOL_RECYCLE)
300
+ except Exception:
301
+ DATABASE_POOL_RECYCLE = 3600
302
+
303
+ RESET_CONFIG_ON_START = (
304
+ os.environ.get("RESET_CONFIG_ON_START", "False").lower() == "true"
305
+ )
306
+
307
+ ####################################
308
+ # REDIS
309
+ ####################################
310
+
311
+ REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
312
+
313
+ ####################################
314
+ # WEBUI_AUTH (Required for security)
315
+ ####################################
316
+
317
+ WEBUI_AUTH = os.environ.get("WEBUI_AUTH", "True").lower() == "true"
318
+ WEBUI_AUTH_TRUSTED_EMAIL_HEADER = os.environ.get(
319
+ "WEBUI_AUTH_TRUSTED_EMAIL_HEADER", None
320
+ )
321
+ WEBUI_AUTH_TRUSTED_NAME_HEADER = os.environ.get("WEBUI_AUTH_TRUSTED_NAME_HEADER", None)
322
+
323
+
324
+ ####################################
325
+ # WEBUI_SECRET_KEY
326
+ ####################################
327
+
328
+ WEBUI_SECRET_KEY = os.environ.get(
329
+ "WEBUI_SECRET_KEY",
330
+ os.environ.get(
331
+ "WEBUI_JWT_SECRET_KEY", "t0p-s3cr3t"
332
+ ), # DEPRECATED: remove at next major version
333
+ )
334
+
335
+ WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get(
336
+ "WEBUI_SESSION_COOKIE_SAME_SITE",
337
+ os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax"),
338
+ )
339
+
340
+ WEBUI_SESSION_COOKIE_SECURE = os.environ.get(
341
+ "WEBUI_SESSION_COOKIE_SECURE",
342
+ os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true",
343
+ )
344
+
345
+ if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
346
+ raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
347
+
348
+ ENABLE_WEBSOCKET_SUPPORT = (
349
+ os.environ.get("ENABLE_WEBSOCKET_SUPPORT", "True").lower() == "true"
350
+ )
351
+
352
+ WEBSOCKET_MANAGER = os.environ.get("WEBSOCKET_MANAGER", "")
353
+
354
+ WEBSOCKET_REDIS_URL = os.environ.get("WEBSOCKET_REDIS_URL", REDIS_URL)
355
+
356
+ AIOHTTP_CLIENT_TIMEOUT = os.environ.get("AIOHTTP_CLIENT_TIMEOUT", "")
357
+
358
+ if AIOHTTP_CLIENT_TIMEOUT == "":
359
+ AIOHTTP_CLIENT_TIMEOUT = None
360
+ else:
361
+ try:
362
+ AIOHTTP_CLIENT_TIMEOUT = int(AIOHTTP_CLIENT_TIMEOUT)
363
+ except Exception:
364
+ AIOHTTP_CLIENT_TIMEOUT = 300
365
+
366
+ AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = os.environ.get(
367
+ "AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST", "3"
368
+ )
369
+
370
+ if AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST == "":
371
+ AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = None
372
+ else:
373
+ try:
374
+ AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = int(
375
+ AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST
376
+ )
377
+ except Exception:
378
+ AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST = 3
379
+
380
+ ####################################
381
+ # OFFLINE_MODE
382
+ ####################################
383
+
384
+ OFFLINE_MODE = os.environ.get("OFFLINE_MODE", "false").lower() == "true"