Skip to content

Commit 407dc9a

Browse files
authored
Merge pull request open-webui#16507 from open-webui/dev
0.6.23
2 parents 438e5d9 + 9fb2c9c commit 407dc9a

File tree

204 files changed

+11870
-4921
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

204 files changed

+11870
-4921
lines changed

CHANGELOG.md

Lines changed: 75 additions & 0 deletions
Large diffs are not rendered by default.

Dockerfile

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,13 @@ RUN echo -n 00000000-0000-0000-0000-000000000000 > $HOME/.cache/chroma/telemetry
108108
# Make sure the user has access to the app and root directory
109109
RUN chown -R $UID:$GID /app $HOME
110110

111-
RUN if [ "$USE_OLLAMA" = "true" ]; then \
112-
apt-get update && \
113-
# Install pandoc and netcat
114-
apt-get install -y --no-install-recommends git build-essential pandoc netcat-openbsd curl && \
115-
apt-get install -y --no-install-recommends gcc python3-dev && \
116-
# for RAG OCR
117-
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
118-
# install helper tools
119-
apt-get install -y --no-install-recommends curl jq && \
120-
# install ollama
121-
curl -fsSL https://ollama.com/install.sh | sh && \
122-
# cleanup
123-
rm -rf /var/lib/apt/lists/*; \
124-
else \
125-
apt-get update && \
126-
# Install pandoc, netcat and gcc
127-
apt-get install -y --no-install-recommends git build-essential pandoc gcc netcat-openbsd curl jq && \
128-
apt-get install -y --no-install-recommends gcc python3-dev && \
129-
# for RAG OCR
130-
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
131-
# cleanup
132-
rm -rf /var/lib/apt/lists/*; \
133-
fi
111+
# Install common system dependencies
112+
RUN apt-get update && \
113+
apt-get install -y --no-install-recommends \
114+
git build-essential pandoc gcc netcat-openbsd curl jq \
115+
python3-dev \
116+
ffmpeg libsm6 libxext6 \
117+
&& rm -rf /var/lib/apt/lists/*
134118

135119
# install python dependencies
136120
COPY --chown=$UID:$GID ./backend/requirements.txt ./requirements.txt
@@ -152,7 +136,13 @@ RUN pip3 install --no-cache-dir uv && \
152136
fi; \
153137
chown -R $UID:$GID /app/backend/data/
154138

155-
139+
# Install Ollama if requested
140+
RUN if [ "$USE_OLLAMA" = "true" ]; then \
141+
date +%s > /tmp/ollama_build_hash && \
142+
echo "Cache broken at timestamp: `cat /tmp/ollama_build_hash`" && \
143+
curl -fsSL https://ollama.com/install.sh | sh && \
144+
rm -rf /var/lib/apt/lists/*; \
145+
fi
156146

157147
# copy embedding weight from build
158148
# RUN mkdir -p /root/.cache/chroma/onnx_models/all-MiniLM-L6-v2
@@ -170,6 +160,15 @@ EXPOSE 8080
170160

171161
HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq -ne 'input.status == true' || exit 1
172162

163+
# Minimal, atomic permission hardening for OpenShift (arbitrary UID):
164+
# - Group 0 owns /app and /root
165+
# - Directories are group-writable and have SGID so new files inherit GID 0
166+
RUN set -eux; \
167+
chgrp -R 0 /app /root || true; \
168+
chmod -R g+rwX /app /root || true; \
169+
find /app -type d -exec chmod g+s {} + || true; \
170+
find /root -type d -exec chmod g+s {} + || true
171+
173172
USER $UID:$GID
174173

175174
ARG BUILD_HASH

backend/open_webui/alembic.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ script_location = migrations
1010

1111
# sys.path path, will be prepended to sys.path if present.
1212
# defaults to the current working directory.
13-
prepend_sys_path = .
13+
prepend_sys_path = ..
1414

1515
# timezone to use when rendering the date within the migration file
1616
# as well as the filename.

backend/open_webui/config.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ def __getattr__(self, key):
510510
OAUTH_GROUPS_CLAIM = PersistentConfig(
511511
"OAUTH_GROUPS_CLAIM",
512512
"oauth.oidc.group_claim",
513-
os.environ.get("OAUTH_GROUP_CLAIM", "groups"),
513+
os.environ.get("OAUTH_GROUPS_CLAIM", os.environ.get("OAUTH_GROUP_CLAIM", "groups")),
514514
)
515515

516516
ENABLE_OAUTH_ROLE_MANAGEMENT = PersistentConfig(
@@ -953,6 +953,9 @@ def oidc_oauth_register(client: OAuth):
953953

954954
if OPENAI_API_BASE_URL == "":
955955
OPENAI_API_BASE_URL = "https://api.openai.com/v1"
956+
else:
957+
if OPENAI_API_BASE_URL.endswith("/"):
958+
OPENAI_API_BASE_URL = OPENAI_API_BASE_URL[:-1]
956959

957960
OPENAI_API_KEYS = os.environ.get("OPENAI_API_KEYS", "")
958961
OPENAI_API_KEYS = OPENAI_API_KEYS if OPENAI_API_KEYS != "" else OPENAI_API_KEY
@@ -1355,6 +1358,14 @@ def oidc_oauth_register(client: OAuth):
13551358
os.environ.get("ENABLE_ADMIN_WORKSPACE_CONTENT_ACCESS", "True").lower() == "true"
13561359
)
13571360

1361+
BYPASS_ADMIN_ACCESS_CONTROL = (
1362+
os.environ.get(
1363+
"BYPASS_ADMIN_ACCESS_CONTROL",
1364+
os.environ.get("ENABLE_ADMIN_WORKSPACE_CONTENT_ACCESS", "True"),
1365+
).lower()
1366+
== "true"
1367+
)
1368+
13581369
ENABLE_ADMIN_CHAT_ACCESS = (
13591370
os.environ.get("ENABLE_ADMIN_CHAT_ACCESS", "True").lower() == "true"
13601371
)
@@ -1565,7 +1576,7 @@ class BannerModel(BaseModel):
15651576
)
15661577

15671578
DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = """### Task:
1568-
Suggest 3-5 relevant follow-up questions or prompts that the user might naturally ask next in this conversation as a **user**, based on the chat history, to help continue or deepen the discussion.
1579+
Suggest 3-5 relevant follow-up questions or prompts in the chat's primary language that the user might naturally ask next in this conversation as a **user**, based on the chat history, to help continue or deepen the discussion.
15691580
### Guidelines:
15701581
- Write all follow-up questions from the user’s point of view, directed to the assistant.
15711582
- Make questions concise, clear, and directly related to the discussed topic(s).
@@ -1857,6 +1868,11 @@ class BannerModel(BaseModel):
18571868
),
18581869
)
18591870

1871+
CODE_INTERPRETER_BLOCKED_MODULES = [
1872+
library.strip()
1873+
for library in os.environ.get("CODE_INTERPRETER_BLOCKED_MODULES", "").split(",")
1874+
if library.strip()
1875+
]
18601876

18611877
DEFAULT_CODE_INTERPRETER_PROMPT = """
18621878
#### Tools Available
@@ -2611,6 +2627,14 @@ class BannerModel(BaseModel):
26112627
os.environ.get("WEB_LOADER_ENGINE", ""),
26122628
)
26132629

2630+
2631+
WEB_LOADER_CONCURRENT_REQUESTS = PersistentConfig(
2632+
"WEB_LOADER_CONCURRENT_REQUESTS",
2633+
"rag.web.loader.concurrent_requests",
2634+
int(os.getenv("WEB_LOADER_CONCURRENT_REQUESTS", "10")),
2635+
)
2636+
2637+
26142638
ENABLE_WEB_LOADER_SSL_VERIFICATION = PersistentConfig(
26152639
"ENABLE_WEB_LOADER_SSL_VERIFICATION",
26162640
"rag.web.loader.ssl_verification",

backend/open_webui/env.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717
# Load .env file
1818
####################################
1919

20-
OPEN_WEBUI_DIR = Path(__file__).parent # the path containing this file
21-
print(OPEN_WEBUI_DIR)
20+
# Use .resolve() to get the canonical path, removing any '..' or '.' components
21+
ENV_FILE_PATH = Path(__file__).resolve()
2222

23-
BACKEND_DIR = OPEN_WEBUI_DIR.parent # the path containing this file
24-
BASE_DIR = BACKEND_DIR.parent # the path containing the backend/
23+
# OPEN_WEBUI_DIR should be the directory where env.py resides (open_webui/)
24+
OPEN_WEBUI_DIR = ENV_FILE_PATH.parent
2525

26-
print(BACKEND_DIR)
27-
print(BASE_DIR)
26+
# BACKEND_DIR is the parent of OPEN_WEBUI_DIR (backend/)
27+
BACKEND_DIR = OPEN_WEBUI_DIR.parent
28+
29+
# BASE_DIR is the parent of BACKEND_DIR (open-webui-dev/)
30+
BASE_DIR = BACKEND_DIR.parent
2831

2932
try:
3033
from dotenv import find_dotenv, load_dotenv
@@ -336,6 +339,21 @@ def parse_section(section):
336339
except Exception:
337340
DATABASE_POOL_RECYCLE = 3600
338341

342+
DATABASE_ENABLE_SQLITE_WAL = (
343+
os.environ.get("DATABASE_ENABLE_SQLITE_WAL", "False").lower() == "true"
344+
)
345+
346+
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = os.environ.get(
347+
"DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL", None
348+
)
349+
if DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL is not None:
350+
try:
351+
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = float(
352+
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL
353+
)
354+
except Exception:
355+
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = 0.0
356+
339357
RESET_CONFIG_ON_START = (
340358
os.environ.get("RESET_CONFIG_ON_START", "False").lower() == "true"
341359
)
@@ -677,6 +695,7 @@ def parse_section(section):
677695
####################################
678696

679697
ENABLE_OTEL = os.environ.get("ENABLE_OTEL", "False").lower() == "true"
698+
ENABLE_OTEL_TRACES = os.environ.get("ENABLE_OTEL_TRACES", "False").lower() == "true"
680699
ENABLE_OTEL_METRICS = os.environ.get("ENABLE_OTEL_METRICS", "False").lower() == "true"
681700
ENABLE_OTEL_LOGS = os.environ.get("ENABLE_OTEL_LOGS", "False").lower() == "true"
682701

backend/open_webui/functions.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
)
4848
from open_webui.utils.payload import (
4949
apply_model_params_to_body_openai,
50-
apply_model_system_prompt_to_body,
50+
apply_system_prompt_to_body,
5151
)
5252

5353

@@ -253,9 +253,7 @@ def get_function_params(function_module, form_data, user, extra_params=None):
253253
if params:
254254
system = params.pop("system", None)
255255
form_data = apply_model_params_to_body_openai(params, form_data)
256-
form_data = apply_model_system_prompt_to_body(
257-
system, form_data, metadata, user
258-
)
256+
form_data = apply_system_prompt_to_body(system, form_data, metadata, user)
259257

260258
pipe_id = get_pipe_id(form_data)
261259
function_module = get_function_module_by_id(request, pipe_id)

backend/open_webui/internal/db.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
DATABASE_POOL_RECYCLE,
1515
DATABASE_POOL_SIZE,
1616
DATABASE_POOL_TIMEOUT,
17+
DATABASE_ENABLE_SQLITE_WAL,
1718
)
1819
from peewee_migrate import Router
19-
from sqlalchemy import Dialect, create_engine, MetaData, types
20+
from sqlalchemy import Dialect, create_engine, MetaData, event, types
2021
from sqlalchemy.ext.declarative import declarative_base
2122
from sqlalchemy.orm import scoped_session, sessionmaker
2223
from sqlalchemy.pool import QueuePool, NullPool
@@ -114,6 +115,16 @@ def create_sqlcipher_connection():
114115
engine = create_engine(
115116
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
116117
)
118+
119+
def on_connect(dbapi_connection, connection_record):
120+
cursor = dbapi_connection.cursor()
121+
if DATABASE_ENABLE_SQLITE_WAL:
122+
cursor.execute("PRAGMA journal_mode=WAL")
123+
else:
124+
cursor.execute("PRAGMA journal_mode=DELETE")
125+
cursor.close()
126+
127+
event.listen(engine, "connect", on_connect)
117128
else:
118129
if isinstance(DATABASE_POOL_SIZE, int):
119130
if DATABASE_POOL_SIZE > 0:

0 commit comments

Comments
 (0)