mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-13 23:14:11 +00:00
Merge 4f279fff0f into ffae4116a8
This commit is contained in:
commit
d3372bb297
2 changed files with 52 additions and 13 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import base64
|
||||
import os
|
||||
import random
|
||||
import socket
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Annotated
|
||||
|
|
@ -14,6 +15,29 @@ KEY_FILE = Path.cwd() / '.webui_secret_key'
|
|||
DEFAULT_SECRET_KEY_LENGTH = 24
|
||||
|
||||
|
||||
def get_dual_stack_host(requested_host: str, port: int) -> str:
|
||||
"""
|
||||
Attempts to use requested_host (default '::' for dual-stack binding).
|
||||
If '::' is used but IPv6 binding fails or is unavailable, falls back to '0.0.0.0'.
|
||||
"""
|
||||
if requested_host == '::':
|
||||
if not socket.has_ipv6:
|
||||
typer.echo('IPv6 not supported by system. Falling back to IPv4 (0.0.0.0).')
|
||||
return '0.0.0.0'
|
||||
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
sock.bind(('::', port))
|
||||
sock.close()
|
||||
return '::'
|
||||
except OSError:
|
||||
typer.echo(f'IPv6 binding failed on port {port}. Falling back to IPv4 (0.0.0.0).')
|
||||
return '0.0.0.0'
|
||||
|
||||
return requested_host
|
||||
|
||||
|
||||
def version_callback(value: bool) -> None:
|
||||
if value:
|
||||
from open_webui.env import VERSION
|
||||
|
|
@ -34,7 +58,7 @@ def main(
|
|||
|
||||
@app.command()
|
||||
def serve(
|
||||
host: str = '0.0.0.0',
|
||||
host: str = '::',
|
||||
port: int = 8080,
|
||||
):
|
||||
os.environ['FROM_INIT_PY'] = 'true'
|
||||
|
|
@ -77,13 +101,15 @@ def serve(
|
|||
from open_webui.env import UVICORN_WORKERS, UVICORN_WS_PER_MESSAGE_DEFLATE
|
||||
|
||||
# On Windows, uvicorn's default loop factory hardcodes ProactorEventLoop,
|
||||
# which is incompatible with psycopg v3 async. Setting loop='none' lets
|
||||
# which is incompatible with psycopg v3 async. Setting loop='none' lets
|
||||
# asyncio.run() respect the WindowsSelectorEventLoopPolicy set in db.py.
|
||||
loop = 'none' if sys.platform == 'win32' else 'auto'
|
||||
|
||||
bind_host = get_dual_stack_host(host, port)
|
||||
|
||||
uvicorn.run(
|
||||
'open_webui.main:app',
|
||||
host=host,
|
||||
host=bind_host,
|
||||
port=port,
|
||||
forwarded_allow_ips='*',
|
||||
workers=UVICORN_WORKERS,
|
||||
|
|
@ -94,15 +120,17 @@ def serve(
|
|||
|
||||
@app.command()
|
||||
def dev(
|
||||
host: str = '0.0.0.0',
|
||||
host: str = '::',
|
||||
port: int = 8080,
|
||||
reload: bool = True,
|
||||
):
|
||||
from open_webui.env import UVICORN_WS_PER_MESSAGE_DEFLATE
|
||||
|
||||
bind_host = get_dual_stack_host(host, port)
|
||||
|
||||
uvicorn.run(
|
||||
'open_webui.main:app',
|
||||
host=host,
|
||||
host=bind_host,
|
||||
port=port,
|
||||
reload=reload,
|
||||
forwarded_allow_ips='*',
|
||||
|
|
|
|||
|
|
@ -4,34 +4,46 @@ set -euo pipefail
|
|||
# ---------------------------------------------------------------------------
|
||||
# Container entry point for Open WebUI.
|
||||
# Handles secret key generation, optional Ollama/CUDA/Playwright setup,
|
||||
# HuggingFace Space deployment, and launches the uvicorn server.
|
||||
# HuggingFace Space deployment, dual-stack host binding, and launches the uvicorn server.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Default optional env vars that we test below with bash's `,,` lowercase
|
||||
# expansion. The two can't be combined inline (`${VAR:-default,,}` makes
|
||||
# the default literal `,,`), so we normalise once up front and the simple
|
||||
# `${VAR,,}` form stays safe under `set -u` everywhere else.
|
||||
: "${USE_SLIM_DOCKER:=}" "${WEB_LOADER_ENGINE:=}" "${USE_OLLAMA_DOCKER:=}" "${USE_CUDA_DOCKER:=}"
|
||||
: "${WEB_LOADER_ENGINE:=}" "${USE_OLLAMA_DOCKER:=}" "${USE_CUDA_DOCKER:=}"
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
|
||||
cd "$SCRIPT_DIR" || exit 1
|
||||
|
||||
# ── Playwright browser installation (if configured) ──────────────────────────
|
||||
|
||||
if [[ "${USE_SLIM_DOCKER,,}" != "true" && "${WEB_LOADER_ENGINE,,}" == "playwright" ]]; then
|
||||
if [[ "${WEB_LOADER_ENGINE,,}" == "playwright" ]]; then
|
||||
if [[ -z "${PLAYWRIGHT_WS_URL:-}" ]]; then
|
||||
echo "Installing Playwright Chromium browser..."
|
||||
playwright install chromium
|
||||
playwright install-deps chromium
|
||||
fi
|
||||
python -c "import nltk; nltk.download('punkt_tab')"
|
||||
fi
|
||||
|
||||
# ── Secret key setup ─────────────────────────────────────────────────────────
|
||||
# ── Secret key & network setup ───────────────────────────────────────────────
|
||||
|
||||
KEY_FILE="${WEBUI_SECRET_KEY_FILE:-.webui_secret_key}"
|
||||
WEBUI_SECRET_KEY_LENGTH="${WEBUI_SECRET_KEY_LENGTH:-24}"
|
||||
PORT="${PORT:-8080}"
|
||||
HOST="${HOST:-0.0.0.0}"
|
||||
# Default to dual-stack IPv6/IPv4 binding '::' unless explicitly overridden
|
||||
HOST="${HOST:-::}"
|
||||
|
||||
PYTHON_CMD=$(command -v python3 || command -v python)
|
||||
|
||||
# Probe IPv6 socket availability if HOST is set to '::'
|
||||
if [[ "$HOST" == "::" ]]; then
|
||||
if ! "$PYTHON_CMD" -c "import socket; s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM); s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1); s.bind(('::', ${PORT})); s.close()" 2>/dev/null; then
|
||||
echo "WARNING: IPv6 binding failed or unavailable on port ${PORT}. Falling back to IPv4 (0.0.0.0)."
|
||||
HOST="0.0.0.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${WEBUI_SECRET_KEY:-}" && -z "${WEBUI_JWT_SECRET_KEY:-}" ]]; then
|
||||
echo "No WEBUI_SECRET_KEY environment variable set, loading from file."
|
||||
|
|
@ -71,11 +83,11 @@ if [[ -n "${SPACE_ID:-}" ]]; then
|
|||
if [[ -n "${ADMIN_USER_EMAIL:-}" && -n "${ADMIN_USER_PASSWORD:-}" ]]; then
|
||||
echo "Creating admin user for Space..."
|
||||
WEBUI_SECRET_KEY="${WEBUI_SECRET_KEY:-}" \
|
||||
uvicorn open_webui.main:app --host "$HOST" --port "$PORT" --forwarded-allow-ips "${FORWARDED_ALLOW_IPS:-*}" --ws-per-message-deflate "${UVICORN_WS_PER_MESSAGE_DEFLATE:-true}" &
|
||||
"$PYTHON_CMD" -m uvicorn open_webui.main:app --host "$HOST" --port "$PORT" --forwarded-allow-ips "${FORWARDED_ALLOW_IPS:-*}" --ws-per-message-deflate "${UVICORN_WS_PER_MESSAGE_DEFLATE:-true}" &
|
||||
webui_pid=$!
|
||||
|
||||
echo "Waiting for server to become healthy..."
|
||||
until curl -sf "http://localhost:${PORT}/health" > /dev/null 2>&1; do
|
||||
until curl -sf "http://localhost:${PORT}/health" > /dev/null 2>&1 || curl -sf "http://[::1]:${PORT}/health" > /dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
|
@ -95,7 +107,6 @@ fi
|
|||
|
||||
# ── Launch uvicorn ───────────────────────────────────────────────────────────
|
||||
|
||||
PYTHON_CMD=$(command -v python3 || command -v python)
|
||||
UVICORN_WORKERS="${UVICORN_WORKERS:-1}"
|
||||
|
||||
if [[ "$#" -gt 0 ]]; then
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue