-
-
Notifications
You must be signed in to change notification settings - Fork 14.5k
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
Add Ollama-webui package and service for Mixtral #275448
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,106 @@ | ||
{ config, lib, pkgs, ... }: let | ||
{ config, pkgs, lib, ... }: | ||
|
||
cfg = config.services.ollama; | ||
with lib; | ||
|
||
in { | ||
let cfg = config.services.ollama; | ||
|
||
in { | ||
options = { | ||
services.ollama = { | ||
enable = lib.mkEnableOption ( | ||
lib.mdDoc "Server for local large language models" | ||
); | ||
package = lib.mkPackageOption pkgs "ollama" { }; | ||
enable = mkEnableOption (lib.mdDoc '' | ||
Ollama backend service. | ||
Run state-of-the-art AI large language models (LLM) similar to ChatGPT locally with privacy | ||
on your personal computer. | ||
|
||
This module provides the `ollama serve` backend runner service so that you can run | ||
`ollam run <model-name>` locally in a terminal; this will automatically download the | ||
LLM model and open a chat. See <https://github.com/jmorganca/ollama#quickstart>. | ||
The model names can be looked up on <https://ollama.ai/library> and are available in | ||
varying sizes to fit your CPU, GPU, RAM and disk storage. | ||
See <https://github.com/jmorganca/ollama#model-library>. | ||
|
||
Optional: This module is intended to be run locally, but can be served from a (home) server, | ||
ideally behind a secured reverse-proxy. | ||
Look at <https://nixos.wiki/wiki/Nginx> or <https://nixos.wiki/wiki/Caddy> | ||
on how to set up a reverse proxy. | ||
|
||
Optional: This service doesn't persist any chats and is only available in the terminal. | ||
For a convenient, graphical web app on top of it, take look at | ||
<https://github.com/ollama-webui/ollama-webui>, also as `ollama-webui` in Nixpkgs. | ||
''); | ||
|
||
ollama-package = mkPackageOption pkgs "ollama" { }; | ||
|
||
host = mkOption { | ||
type = types.str; | ||
default = "127.0.0.1"; | ||
description = lib.mdDoc '' | ||
The host/domain name under which the Ollama backend service is reachable. | ||
''; | ||
}; | ||
|
||
port = mkOption { | ||
type = types.port; | ||
default = 11434; | ||
description = lib.mdDoc "The port for the Ollama backend service."; | ||
}; | ||
|
||
cors_origins = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
example = "https://myserver:8080,http://10.0.0.10:*"; | ||
description = lib.mdDoc '' | ||
Allow access from web apps that are served under some (different) URL. | ||
If a web app like Ollama-WebUI is available/served on `https://myserver:8080`, | ||
then add this URL here. Otherwise the Ollama backend server will reject the | ||
UIs request and return 403 forbidden due to CORS. | ||
See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>. | ||
''; | ||
}; | ||
|
||
openFirewall = mkOption { | ||
type = types.bool; | ||
default = false; | ||
description = lib.mdDoc "Open ports in the firewall for the Ollama backend service."; | ||
}; | ||
}; | ||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
|
||
systemd = { | ||
services.ollama = { | ||
wantedBy = [ "multi-user.target" ]; | ||
description = "Server for local large language models"; | ||
after = [ "network.target" ]; | ||
environment = { | ||
HOME = "%S/ollama"; | ||
OLLAMA_MODELS = "%S/ollama/models"; | ||
}; | ||
serviceConfig = { | ||
ExecStart = "${lib.getExe cfg.package} serve"; | ||
WorkingDirectory = "/var/lib/ollama"; | ||
StateDirectory = [ "ollama" ]; | ||
DynamicUser = true; | ||
}; | ||
config = mkIf cfg.enable { | ||
systemd.services.ollama = { | ||
description = "Ollama: A backend service for local large language models (LLM)."; | ||
after = [ "network.target" ]; | ||
wantedBy = [ "multi-user.target" ]; | ||
|
||
environment = { | ||
OLLAMA_HOST = "${cfg.host}:${toString cfg.port}"; | ||
OLLAMA_ORIGINS = cfg.cors_origins; | ||
# Where to store LLM model files. | ||
# Directory is managed by systemd DynamicUser feature, see below. | ||
HOME = "%S/ollama"; | ||
OLLAMA_MODELS = "%S/ollama/models"; | ||
}; | ||
|
||
serviceConfig = { | ||
ExecStart = "${lib.getExe cfg.ollama-package} serve"; | ||
# Systemd takes care of username, user id, security & permissions | ||
# See https://0pointer.net/blog/dynamic-users-with-systemd.html | ||
# Almost nothing on the disk is readable for this dynamic user; only a few places writable: | ||
# See https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#RuntimeDirectory= | ||
DynamicUser = "true"; | ||
Type = "simple"; | ||
Restart = "on-failure"; | ||
RestartSec = 3; | ||
WorkingDirectory = "/var/lib/ollama"; | ||
# Persistent storage for model files, i.e. /var/lib/<StateDirectory> | ||
StateDirectory = [ "ollama" ]; | ||
}; | ||
}; | ||
|
||
environment.systemPackages = [ cfg.package ]; | ||
networking.firewall = mkIf cfg.openFirewall { | ||
allowedTCPPorts = [ cfg.port ]; | ||
}; | ||
|
||
}; | ||
|
||
meta.maintainers = with lib.maintainers; [ onny ]; | ||
|
||
meta.maintainers = with lib.maintainers; [ onny malteneuss ]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
{ config, pkgs, lib, ... }: | ||
|
||
with lib; | ||
|
||
let cfg = config.services.ollama-webui; | ||
|
||
in { | ||
options = { | ||
services.ollama-webui = { | ||
enable = mkEnableOption (lib.mdDoc '' | ||
Ollama-WebUI frontend service for the Ollama backend service. | ||
It's a single page web application that integrates with Ollama to | ||
run state-of-the-art AI large language models (LLM) locally with privacy | ||
on your personal computer. | ||
It's look and feel is similar to ChatGPT, supports different LLM models, | ||
it stores chats (in the browser storage), supports image uploads, | ||
Markdown and Latex rendering etc.See <https://github.com/ollama-webui/ollama-webui>. | ||
|
||
The model names can be looked up on <https://ollama.ai/library> and are available in | ||
varying sizes to fit your CPU, GPU, RAM and disk storage. | ||
|
||
Required: This module requires the Ollama backend runner service that actually runs the | ||
LLM models. The Ollama backend can be running locally or on a server; it's available | ||
as a Nix package or a NixOS module. | ||
The URL to the Ollama backend service can be set in this module, but overriden | ||
later in the running Ollama-WebUI as well. | ||
|
||
Optional: This module is configured to run locally, but can be served from a (home) server, | ||
ideally behind a secured reverse-proxy. | ||
Look at <https://nixos.wiki/wiki/Nginx> or <https://nixos.wiki/wiki/Caddy> | ||
on how to set up a reverse proxy. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you think referencing the caddy file of the original repo would be a good idea ? |
||
''); | ||
|
||
ollama-webui-package = mkPackageOption pkgs "ollama-webui" { }; | ||
|
||
host = mkOption { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this host isn't used anywhere, is that intentional ? |
||
type = types.str; | ||
default = "127.0.0.1"; | ||
description = lib.mdDoc '' | ||
The host/domain name under which the Ollama-WebUI service is reachable. | ||
''; | ||
}; | ||
|
||
port = mkOption { | ||
type = types.port; | ||
default = 8080; | ||
description = lib.mdDoc "The port for the Ollama-WebUI service."; | ||
}; | ||
|
||
cors_origins = mkOption { | ||
type = types.nullOr types.str; | ||
default = null; | ||
example = "*,https://myserver:8080,http://10.0.0.10:*"; | ||
description = lib.mdDoc '' | ||
Allow access from web apps that are served under some (different) URL. | ||
If a web app like Ollama-WebUI is available/served on `https://myserver:8080`, | ||
then add this URL here. Otherwise the Ollama frontend server will reject the | ||
UIs request and return 403 forbidden due to CORS. | ||
See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>. | ||
''; | ||
}; | ||
|
||
openFirewall = mkOption { | ||
type = types.bool; | ||
default = false; | ||
description = lib.mdDoc "Open ports in the firewall for the Ollama-WebUI service."; | ||
}; | ||
}; | ||
}; | ||
|
||
config = mkIf cfg.enable { | ||
|
||
systemd.services.ollama-webui = { | ||
description = "Ollama WebUI Service"; | ||
wantedBy = [ "multi-user.target" ]; | ||
after = [ "network.target" ]; | ||
|
||
serviceConfig = let | ||
cors-arg = if cfg.cors_origins == null then "" else "--cors='" + cfg.cors_origin +"'"; | ||
in { | ||
ExecStart = "${cfg.ollama-webui-package}/bin/ollama-webui --port ${toString cfg.port} ${cors-arg}"; | ||
DynamicUser = "true"; | ||
Type = "simple"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just for information the default type is simple for services is simple. I'm not sure how I feel about having it written explicitely, if you prefer it that way, feel free to keep it. |
||
Restart = "on-failure"; | ||
}; | ||
}; | ||
|
||
networking.firewall = mkIf cfg.openFirewall { | ||
allowedTCPPorts = [ cfg.port ]; | ||
}; | ||
|
||
}; | ||
meta.maintainers = with lib.maintainers; [ malteneuss ]; | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,62 @@ | ||||||
{ lib | ||||||
, buildNpmPackage | ||||||
, nodePackages | ||||||
, fetchFromGitHub | ||||||
, runtimeShell | ||||||
}: | ||||||
|
||||||
# We just package the JS frontend part, not the Python reverse-proxy backend. | ||||||
# NixOS can provide any another reverse proxy such as nginx. | ||||||
buildNpmPackage rec { | ||||||
pname = "ollama-webui"; | ||||||
# ollama-webui doesn't tag versions yet. | ||||||
version = "0.0.0-unstable-2023-12-22"; | ||||||
|
||||||
src = fetchFromGitHub { | ||||||
owner = "ollama-webui"; | ||||||
repo = "ollama-webui"; | ||||||
rev = "77c1a77fccb04337ff95440030cd051fd16c2cd8"; | ||||||
hash = "sha256-u7h2tpHgtQwYXornslY3CZjKjigqBK2mHmaiK1EoEgk="; | ||||||
}; | ||||||
# dependencies are downloaded into a separate node_modules Nix package | ||||||
npmDepsHash = "sha256-SI2dPn1SwbGwl8093VBtcDsA2eHSxr3UUC+ta68w2t8="; | ||||||
|
||||||
# We have to bake in the default URL it will use for ollama webserver here, | ||||||
# but it can be overriden in the UI later. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when you say it can be overridden later, does that mean inside the module ? |
||||||
PUBLIC_API_BASE_URL = "http://localhost:11434/api"; | ||||||
|
||||||
# The path '/ollama/api' will be redirected to the specified backend URL | ||||||
OLLAMA_API_BASE_URL = PUBLIC_API_BASE_URL; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the env var only seems to be set after the build has succeeded |
||||||
# "npm run build" creates a static page in the "build" folder. | ||||||
installPhase = '' | ||||||
mkdir -p $out/lib | ||||||
cp -R ./build/. $out/lib | ||||||
|
||||||
mkdir -p $out/bin | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you don't need those last instructions.
second point and this is entirely optional. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just a bit more context on not providing an executable for a node package. if you prefer to provide a binary, I respect your decision, in that case, you should probably use makeWrapper, you can look at jellyseerr for an example (you'll find many more if you don't like this particular one). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Since There are a bunch of other frontends that people might want to use with the |
||||||
cat <<EOF >>$out/bin/${pname} | ||||||
#!${runtimeShell} | ||||||
${nodePackages.http-server}/bin/http-server $out/lib | ||||||
EOF | ||||||
chmod +x $out/bin/${pname} | ||||||
''; | ||||||
|
||||||
meta = with lib; { | ||||||
description = "ChatGPT-Style Web Interface for Ollama"; | ||||||
longDescription = '' | ||||||
Tools like Ollama make open-source large langue models (LLM) accessible and almost | ||||||
trivial to download and run them locally on a consumer computer. | ||||||
However, Ollama only runs in a terminal and doesn't store any chat history. | ||||||
Ollama-WebUI is a web frontend on top of Ollama that looks and behaves similar to ChatGPT's web frontend. | ||||||
You can have separate chats with different LLMs that are saved in your browser, | ||||||
automatic Markdown and Latex rendering, upload files etc. | ||||||
This package contains two parts: | ||||||
- `<nix-store-package-path>/lib` The WebUI as a compiled, static html folder to bundle in your web server | ||||||
- `<nix-store-package-path>/bin/${pname}` A runnable webserver the serves the WebUI for convenience. | ||||||
''; | ||||||
homepage = "https://github.com/ollama-webui/ollama-webui"; | ||||||
license = licenses.mit; | ||||||
mainProgram = pname; | ||||||
maintainers = with maintainers; [ malteneuss ]; | ||||||
platforms = platforms.all; | ||||||
}; | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it better to use
/var/lib/private/ollama
instead of the%s
so that it's more functional to work with the variables?^ Having to hard-code the path as the expansion doesn't seem to work like other services