Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport release-24.05] open-webui: init at 0.2.4 #332412

Merged
merged 2 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@
./services/misc/octoprint.nix
./services/misc/ollama.nix
./services/misc/ombi.nix
./services/misc/open-webui.nix
./services/misc/osrm.nix
./services/misc/owncast.nix
./services/misc/packagekit.nix
Expand Down
94 changes: 94 additions & 0 deletions nixos/modules/services/misc/open-webui.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) types;

cfg = config.services.open-webui;
in
{
options = {
services.open-webui = {
enable = lib.mkEnableOption "Enable open-webui, an interactive chat web app";
package = lib.mkPackageOption pkgs "open-webui" { };

stateDir = lib.mkOption {
type = types.path;
default = "/var/lib/open-webui";
description = "State directory of open-webui.";
};

host = lib.mkOption {
type = types.str;
default = "localhost";
description = "Host of open-webui";
};

port = lib.mkOption {
type = types.port;
default = 8080;
description = "Port of open-webui";
};

environment = lib.mkOption {
type = types.attrsOf types.str;
default = { };
example = ''
{
OLLAMA_API_BASE_URL = "http://localhost:11434";
# Disable authentication
WEBUI_AUTH = "False";
}
'';
description = "Extra environment variables for open-webui";
};
};
};

config = lib.mkIf cfg.enable {
systemd.services.open-webui = {
description = "User-friendly WebUI for LLMs (Formerly Ollama WebUI)";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];

preStart = ''
mkdir -p ${cfg.stateDir}/static
'';

environment = {
STATIC_DIR = "${cfg.stateDir}/static";
DATA_DIR = "${cfg.stateDir}";
} // cfg.environment;

serviceConfig = {
ExecStart = "${lib.getExe cfg.package} serve --host ${cfg.host} --port ${toString cfg.port}";
WorkingDirectory = cfg.stateDir;
StateDirectory = "open-webui";
RuntimeDirectory = "open-webui";
RuntimeDirectoryMode = "0755";
PrivateTmp = true;
DynamicUser = true;
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = false; # onnxruntime/capi/onnxruntime_pybind11_state.so: cannot enable executable stack as shared object requires: Permission Denied
PrivateUsers = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
ProcSubset = "all"; # Error in cpuinfo: failed to parse processor information from /proc/cpuinfo
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
UMask = "0077";
};
};
};

meta.maintainers = with lib.maintainers; [ shivaraj-bh ];
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ in {
outline = handleTest ./outline.nix {};
image-contents = handleTest ./image-contents.nix {};
openvscode-server = handleTest ./openvscode-server.nix {};
open-webui = runTest ./open-webui.nix;
orangefs = handleTest ./orangefs.nix {};
os-prober = handleTestOn ["x86_64-linux"] ./os-prober.nix {};
osquery = handleTestOn ["x86_64-linux"] ./osquery.nix {};
Expand Down
33 changes: 33 additions & 0 deletions nixos/tests/open-webui.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{ lib, ... }:
let
mainPort = "8080";
in
{
name = "open-webui";
meta = with lib.maintainers; {
maintainers = [ shivaraj-bh ];
};

nodes = {
machine =
{ ... }:
{
services.open-webui = {
enable = true;
environment = {
# Requires network connection
RAG_EMBEDDING_MODEL = "";
};
};
};
};

testScript = ''
machine.start()

machine.wait_for_unit("open-webui.service")
machine.wait_for_open_port(${mainPort})

machine.succeed("curl http://127.0.0.1:${mainPort}")
'';
}
142 changes: 142 additions & 0 deletions pkgs/by-name/op/open-webui/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
lib,
buildNpmPackage,
fetchFromGitHub,
python3,
nixosTests,
}:
let
pname = "open-webui";
version = "0.2.4";

src = fetchFromGitHub {
owner = "open-webui";
repo = "open-webui";
rev = "v${version}";
hash = "sha256-jWO0mo26C+QTIX5j3ucDk/no+vQnAh7Q6JwB3lLM83k=";
};

frontend = buildNpmPackage {
inherit pname version src;

npmDepsHash = "sha256-QIgYHZusuq2QD8p8MGsNVhCbz6fR+qP9UuU/kbBkadc=";

# Disabling `pyodide:fetch` as it downloads packages during `buildPhase`
# Until this is solved, running python packages from the browser will not work.
postPatch = ''
substituteInPlace package.json \
--replace-fail "npm run pyodide:fetch && vite build" "vite build" \
'';

env.CYPRESS_INSTALL_BINARY = "0"; # disallow cypress from downloading binaries in sandbox

installPhase = ''
runHook preInstall

mkdir -p $out/share
cp -a build $out/share/open-webui

runHook postInstall
'';
};
in
python3.pkgs.buildPythonApplication rec {
inherit pname version src;
pyproject = true;

# The custom hook tries to run `npm install` in `buildPhase`.
# We don't have to worry, as nodejs depedencies are managed by `frontend` drv.
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail '[tool.hatch.build.hooks.custom]' "" \
--replace-fail ', build = "open_webui/frontend"' ""
'';

pythonRelaxDeps = true;

pythonRemoveDeps = [
# using `psycopg2` instead
"psycopg2-binary"
# using `opencv4`
"opencv-python-headless"
# package request: https://github.com/NixOS/nixpkgs/issues/317065
"rapidocr-onnxruntime"
# package request: https://github.com/NixOS/nixpkgs/issues/317066
"langfuse"
# package request: https://github.com/NixOS/nixpkgs/issues/317068
"langchain-chroma"
];

dependencies = with python3.pkgs; [
beautifulsoup4
fastapi
uvicorn
python-multipart
flask
flask-cors
python-socketio
python-jose
passlib
requests
aiohttp
peewee
peewee-migrate
psycopg2
pymysql
bcrypt
litellm
boto3
argon2-cffi
apscheduler
google-generativeai
langchain
langchain-community
fake-useragent
chromadb
sentence-transformers
pypdf
docx2txt
python-pptx
unstructured
markdown
pypandoc
pandas
openpyxl
pyxlsb
xlrd
validators
opencv4
fpdf2
rank-bm25
faster-whisper
pyjwt
black
youtube-transcript-api
pytube
];

build-system = with python3.pkgs; [
hatchling
pythonRelaxDepsHook
];

pythonImportsCheck = [ "open_webui" ];

postInstall = ''
wrapProgram $out/bin/open-webui \
--set FRONTEND_BUILD_DIR "${frontend}/share/open-webui"
'';

passthru.tests = {
inherit (nixosTests) open-webui;
};

meta = {
description = "Full-stack of open-webui. open-webui is a user-friendly WebUI for LLMs (Formerly Ollama WebUI)";
homepage = "https://github.com/open-webui/open-webui";
changelog = "https://github.com/open-webui/open-webui/blob/${src.rev}/CHANGELOG.md";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ shivaraj-bh ];
mainProgram = "open-webui";
};
}