Skip to content

Instantly share code, notes, and snippets.

@raspiduino
Created July 11, 2025 09:23
Show Gist options
  • Save raspiduino/687346789209c95cd679b9acd1b6173b to your computer and use it in GitHub Desktop.
Save raspiduino/687346789209c95cd679b9acd1b6173b to your computer and use it in GitHub Desktop.
Minimal(?) Open-WebUI setup for using as chat frontend (NO local inference included)

Minimal(?) Open-WebUI setup for using as chat frontend (NO local inference included)

I personally run this on my 1GB ARM box. The python process takes about 200 - 300MB.

I removed cloud storage (I don't use it anyway, and I think you also don't. You can add it back if you want)

New requirements.txt (backend\requirements.txt)

See the attached requirements.txt. This only install needed libs (and NO transformers or Pytorch or anything like that)

New provider.py (backend\open_webui\storage\provider.py)

Remove cloud storage support. You might keep the original one if you would like, but you will have to install some more cloud dependencies.

What to do?

  1. Replace requirements.txt
  2. (Optional) Edit provider.py
  3. npm install then build frontend with vite build (both should be run from the repo's root). You might prebuilt the frontend on another machine and deploy the folder to the target machine.
  4. Copy build folder (containing built frontend) and backend folder (containing Python backend) and CHANGELOG.md (seriously?) to target machine
  5. In backend folder on target machine: (Optional but recommended: create venv with python3 -m venv .venv then activate the venv) pip3 install -r requirements.txt
  6. Set environment variable RAG_EMBEDDING_ENGINE=ollama and AUDIO_STT_ENGINE=openai
  7. Start Open-WebUI with ./start.sh or start_windows.bat
  8. If you get something like audioop (>= py3.13?), install package audioop-lts
  9. Open web interface on :8080 and start setting up like normal
  10. Go to setting -> Connections and set your API endpoint + key.
  11. Enjoy!
import os
import shutil
import json
import logging
import re
from abc import ABC, abstractmethod
from typing import BinaryIO, Tuple, Dict
from open_webui.config import (
S3_ACCESS_KEY_ID,
S3_BUCKET_NAME,
S3_ENDPOINT_URL,
S3_KEY_PREFIX,
S3_REGION_NAME,
S3_SECRET_ACCESS_KEY,
S3_USE_ACCELERATE_ENDPOINT,
S3_ADDRESSING_STYLE,
S3_ENABLE_TAGGING,
GCS_BUCKET_NAME,
GOOGLE_APPLICATION_CREDENTIALS_JSON,
AZURE_STORAGE_ENDPOINT,
AZURE_STORAGE_CONTAINER_NAME,
AZURE_STORAGE_KEY,
STORAGE_PROVIDER,
UPLOAD_DIR,
)
from open_webui.constants import ERROR_MESSAGES
from open_webui.env import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
class StorageProvider(ABC):
@abstractmethod
def get_file(self, file_path: str) -> str:
pass
@abstractmethod
def upload_file(
self, file: BinaryIO, filename: str, tags: Dict[str, str]
) -> Tuple[bytes, str]:
pass
@abstractmethod
def delete_all_files(self) -> None:
pass
@abstractmethod
def delete_file(self, file_path: str) -> None:
pass
class LocalStorageProvider(StorageProvider):
@staticmethod
def upload_file(
file: BinaryIO, filename: str, tags: Dict[str, str]
) -> Tuple[bytes, str]:
contents = file.read()
if not contents:
raise ValueError(ERROR_MESSAGES.EMPTY_CONTENT)
file_path = f"{UPLOAD_DIR}/{filename}"
with open(file_path, "wb") as f:
f.write(contents)
return contents, file_path
@staticmethod
def get_file(file_path: str) -> str:
"""Handles downloading of the file from local storage."""
return file_path
@staticmethod
def delete_file(file_path: str) -> None:
"""Handles deletion of the file from local storage."""
filename = file_path.split("/")[-1]
file_path = f"{UPLOAD_DIR}/{filename}"
if os.path.isfile(file_path):
os.remove(file_path)
else:
log.warning(f"File {file_path} not found in local storage.")
@staticmethod
def delete_all_files() -> None:
"""Handles deletion of all files from local storage."""
if os.path.exists(UPLOAD_DIR):
for filename in os.listdir(UPLOAD_DIR):
file_path = os.path.join(UPLOAD_DIR, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path) # Remove the file or link
elif os.path.isdir(file_path):
shutil.rmtree(file_path) # Remove the directory
except Exception as e:
log.exception(f"Failed to delete {file_path}. Reason: {e}")
else:
log.warning(f"Directory {UPLOAD_DIR} not found in local storage.")
def get_storage_provider(storage_provider: str):
'''if storage_provider == "local":
Storage = LocalStorageProvider()
elif storage_provider == "s3":
Storage = S3StorageProvider()
elif storage_provider == "gcs":
Storage = GCSStorageProvider()
elif storage_provider == "azure":
Storage = AzureStorageProvider()
else:
raise RuntimeError(f"Unsupported storage provider: {storage_provider}")
return Storage'''
Storage = LocalStorageProvider()
return Storage
Storage = get_storage_provider(STORAGE_PROVIDER)
uvicorn[standard]
typer
pydantic
sqlalchemy
aiocache
aiohttp
requests
redis
fastapi
starlette-compress
itsdangerous
loguru
markdown
beautifulsoup4
asgiref
PyJWT[crypto]
pytz
opentelemetry-api
opentelemetry-sdk
peewee
peewee-migrate
passlib[bcrypt]
python-socketio
alembic
chromadb
#audioop-lts
aiofiles
python-multipart
tiktoken
langchain
langchain_community
ftfy
validators
duckduckgo-search
ldap3
fpdf2
authlib
pydub
black
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment