From a145fad3980b65cdc4a599c6eead6548c703ba94 Mon Sep 17 00:00:00 2001 From: atagen Date: Wed, 1 May 2024 15:30:22 +1000 Subject: [PATCH] integrate stateful dockerised AI applications --- flakes/comfyui/flake.lock | 95 ++++++++++++++++++++++++++++++ flakes/comfyui/flake.nix | 68 +++++++++++++++++++++ home/bolt.nix | 2 + home/home.nix | 1 - home/programs/ollama.nix | 75 +++++++++++++++++++++++ home/programs/stable-diffusion.nix | 61 ++++++++++++++----- home/util/firefox-webapp.nix | 11 +++- system/quiver.nix | 2 +- 8 files changed, 295 insertions(+), 20 deletions(-) create mode 100644 flakes/comfyui/flake.lock create mode 100644 flakes/comfyui/flake.nix create mode 100644 home/programs/ollama.nix diff --git a/flakes/comfyui/flake.lock b/flakes/comfyui/flake.lock new file mode 100644 index 0000000..c567ee7 --- /dev/null +++ b/flakes/comfyui/flake.lock @@ -0,0 +1,95 @@ +{ + "nodes": { + "comfyui-mgr": { + "flake": false, + "locked": { + "lastModified": 1714523018, + "narHash": "sha256-BsJbbWtgIx7ydyVCy4lxdJR9xAGvCdA3FDGdwcLEuSY=", + "owner": "ltdrdata", + "repo": "ComfyUI-Manager", + "rev": "393bf64b35439ee948dc71483e69c478bb05e35c", + "type": "github" + }, + "original": { + "owner": "ltdrdata", + "repo": "ComfyUI-Manager", + "type": "github" + } + }, + "comfyui-src": { + "flake": false, + "locked": { + "lastModified": 1714526620, + "narHash": "sha256-mQ9YBiSAR+WbGeEHd7DRdcMSz9+XF6ZrQkxrZigv2Cw=", + "owner": "comfyanonymous", + "repo": "ComfyUI", + "rev": "2aed53c4ac78d842a2e984d23343334a29ed8562", + "type": "github" + }, + "original": { + "owner": "comfyanonymous", + "repo": "ComfyUI", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1714253743, + "narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "comfyui-mgr": "comfyui-mgr", + "comfyui-src": "comfyui-src", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flakes/comfyui/flake.nix b/flakes/comfyui/flake.nix new file mode 100644 index 0000000..820deae --- /dev/null +++ b/flakes/comfyui/flake.nix @@ -0,0 +1,68 @@ +{ + description = "ComfyUI"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + comfyui-src = { + url = "github:comfyanonymous/ComfyUI"; + flake = false; + }; + comfyui-mgr = { + url = "github:ltdrdata/ComfyUI-Manager"; + flake = false; + }; + }; + + # cuda + # micromamba + # pytorch + # triton + # comfyui + # requirements.txt + # needs some kind of mutability escape hatch for addons, models etc.. + + outputs = { + self, + nixpkgs, + flake-utils, + comfyui-src, + comfyui-mgr, + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs {inherit system;}; + in + with pkgs; rec { + packages.default = buildFHSEnv { + name = "ComfyUI"; + targetPkgs = pkgs: (with pkgs; + with cudaPackages; [ + cuda_cudart + cudnn + micromamba + ]); + extraBuildCommands = '' + mkdir -p $out/opt/ComfyUI + mkdir -p $out/opt/ComfyUI/custom_nodes/ComfyUI-Manager + cp -R ${comfyui-src}/* $out/opt/ComfyUI + cp -R ${comfyui-mgr}/* $out/opt/ComfyUI/custom_nodes/ComfyUI-Manager + ''; + profile = '' + ln -nfs /opt/ComfyUI/models /host/etc/comfyui/models + ln -nfs /opt/ComfyUI/custom_nodes /host/etc/comfyui/custom_nodes + ''; + # cd /opt/ComfyUI + # eval "$(micromamba shell hook --shell bash)" + # micromamba activate + # micromamba install python pytorch triton + # pip install -r requirements.txt + # ''; + runScript = '' + bash + # ./startup.sh + ''; + }; + } + ); +} diff --git a/home/bolt.nix b/home/bolt.nix index d6e9c5b..cc1b148 100644 --- a/home/bolt.nix +++ b/home/bolt.nix @@ -8,6 +8,8 @@ }: { imports = [ ./home.nix + ./programs/stable-diffusion.nix + ./programs/ollama.nix ]; home = { diff --git a/home/home.nix b/home/home.nix index 8992a7c..c425497 100644 --- a/home/home.nix +++ b/home/home.nix @@ -16,7 +16,6 @@ in { ./programs/firefox.nix ./programs/kitty.nix ./programs/zsh.nix - ./programs/stable-diffusion.nix ./util/ez.nix ./util/firefox-webapp.nix # inputs.plasma-manager.homeManagerModules.plasma-manager diff --git a/home/programs/ollama.nix b/home/programs/ollama.nix new file mode 100644 index 0000000..edb88bb --- /dev/null +++ b/home/programs/ollama.nix @@ -0,0 +1,75 @@ +{ + config, + lib, + pkgs, + ... +}: { + config.programs.firefox.webapps = { + "OpenWebUI" = { + url = "http://127.0.0.1:3021"; + id = 6; + extraSettings = config.programs.firefox.profiles.default.settings; + name = "OpenWebUI Client"; + hidden = true; + }; + }; + + config.systemd.user.services = { + open-webui = { + Unit.Description = "OpenWebUI"; + Service = let + docker = lib.getExe pkgs.docker; + in { + ExecStartPre = "bash -c '${docker} inspect open-webui || ${docker} create -e PORT=3021 --network host --gpus all -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama'"; + ExecStart = "${docker} start open-webui"; + }; + }; + }; + + config.xdg.desktopEntries = { + open-webui = { + name = "Ollama OpenWebUI"; + type = "Application"; + exec = "${let + notify-send = "${lib.getExe' pkgs.libnotify "notify-send"}"; + systemctl = "${lib.getExe' pkgs.systemd "systemctl"}"; + dex = "${lib.getExe pkgs.dex}"; + curl = "${lib.getExe pkgs.curl}"; + in + pkgs.writeShellScript "ollama" + '' + ${notify-send} "Ollama OpenWebUI" "Launching backend.." + ${systemctl} --user start open-webui + attempts=0 + success=false + + while [[ $attempts -lt $((20*9)) ]]; do + if [[ $(${curl} http://127.0.0.1:3021) ]]; then + ${notify-send} "Ollama OpenWebUI" "Launching client.." + success=true + break + else + attempts=$((attempts+1)) + if [[ $(($attempts % 20)) -eq 0 ]]; then + ${notify-send} "Ollama OpenWebUI" "Still launching backend.. ($((attempts/2))s)" + fi + fi + sleep 0.5 + done + + if [[ ! $success ]]; then + ${notify-send} "Ollama OpenWebUI" "Failed to launch backend!" + ${systemctl} --user kill open-webui + exit 1 + fi + + sleep 0.5 # give it a little time + ${dex} -w ~/.nix-profile/share/applications/OpenWebUI.desktop + + ${notify-send} "Ollama OpenWebUI" "Shutting down." + ${systemctl} --user stop open-webui + exit 0 + ''}"; + }; + }; +} diff --git a/home/programs/stable-diffusion.nix b/home/programs/stable-diffusion.nix index b52df0b..bc10c19 100644 --- a/home/programs/stable-diffusion.nix +++ b/home/programs/stable-diffusion.nix @@ -4,7 +4,8 @@ lib, ... }: { - # TODO: create a flake for this + # TODO: figure out if there's a meaningful way to add this to the nix store + # if nothing's reproducible should we even bother # https://github.com/AbdBarho/stable-diffusion-webui-docker/ config.programs.firefox.webapps = { @@ -13,44 +14,72 @@ id = 5; extraSettings = config.programs.firefox.profiles.default.settings; name = "Stable Diffusion Client"; + hidden = true; }; }; - # consider making these manually activated systemd services config.systemd.user.services = { stable-diffusion = { Unit.Description = "Stable Diffusion Backend"; Service = { WorkingDirectory = "${config.home.homeDirectory}/code/etc/stable-diffusion-webui-docker"; ExecStart = "${lib.getExe pkgs.docker} compose --profile comfy up --build"; - # ExecStop = "${lib.getExe pkgs.docker} compose stop"; }; }; - # stable-diffusion-dl = {} }; config.xdg.desktopEntries = { stable-diffusion = { - name = "Stable Diffusion Backend Start"; + name = "Stable Diffusion"; type = "Application"; - exec = "systemctl --user start stable-diffusion.service"; + exec = "${let + notify-send = "${lib.getExe' pkgs.libnotify "notify-send"}"; + systemctl = "${lib.getExe' pkgs.systemd "systemctl"}"; + dex = "${lib.getExe pkgs.dex}"; + curl = "${lib.getExe pkgs.curl}"; + in + pkgs.writeShellScript "stable-diffusion" + '' + ${notify-send} "Stable Diffusion" "Launching backend.." + ${systemctl} --user start stable-diffusion + attempts=0 + success=false + + while [[ $attempts -lt $((20*9)) ]]; do + if [[ $(${curl} http://127.0.0.1:7860) ]]; then + ${notify-send} "Stable Diffusion" "Launching client.." + success=true + break + else + attempts=$((attempts+1)) + if [[ $(($attempts % 20)) -eq 0 ]]; then + ${notify-send} "Stable Diffusion" "Still launching backend.. ($((attempts/2))s)" + fi + fi + sleep 0.5 + done + + if [[ ! $success ]]; then + ${notify-send} "Stable Diffusion" "Failed to launch backend!" + ${systemctl} --user kill stable-diffusion + exit 1 + fi + + sleep 0.5 # give it a little time + ${dex} -w ~/.nix-profile/share/applications/StableDiffusion.desktop + + ${notify-send} "Stable Diffusion" "Shutting down." + ${systemctl} --user stop stable-diffusion + exit 0 + ''}"; }; - stable-diffusion-stop = { - name = "Stable Diffusion Backend Stop"; - type = "Application"; - exec = "systemctl --user stop stable-diffusion.service"; - }; - # settings = { - # Path = "${config.home.homeDirectory}/code/etc/stable-diffusion-webui-docker"; - # }; - # exec = "kitty -d ${config.home.homeDirectory}/code/etc/stable-diffusion-webui-docker sh -c \"docker compose --profile comfy up --build\""; # stable-diffusion-dl = { # name = "Stable Diffusion Setup"; # type = "Application"; # settings = { # Path = "${config.home.homeDirectory}/code/etc/stable-diffusion-webui-docker"; # }; - # exec = "kitty --hold docker compose --profile download up --build"; + # exec = "docker compose --profile download up --build"; # }; }; } diff --git a/home/util/firefox-webapp.nix b/home/util/firefox-webapp.nix index fb14465..f92d04e 100644 --- a/home/util/firefox-webapp.nix +++ b/home/util/firefox-webapp.nix @@ -5,7 +5,7 @@ }: let inherit (builtins) getAttr stringLength substring; inherit (lib) mkOption; - inherit (lib.attrsets) mapAttrs mapAttrs' nameValuePair; + inherit (lib.attrsets) filterAttrs mapAttrs mapAttrs' nameValuePair; inherit (lib.strings) concatStringsSep toUpper; make-app-profiles = cfg: @@ -87,6 +87,12 @@ in { description = "The Firefox profile ID to set."; }; + hidden = mkOption { + type = bool; + description = "Hide this webapp from the list of applications (but still generate a .desktop file)."; + default = false; + }; + extraArgs = mkOption { type = listOf str; default = []; @@ -184,7 +190,7 @@ in { type = "Application"; exec = concatStringsSep " " ([ - "${config.programs.firefox.package}/bin/firefox" + "${lib.getExe config.programs.firefox.package}" "--name" "${name}" "--app-id" @@ -201,6 +207,7 @@ in { settings = { X-MultipleArgs = "false"; # Consider enabling, don't know what this does StartupWMClass = "${name}"; + NoDisplay = lib.boolToString cfg.hidden; }; }) config.programs.firefox.webapps; diff --git a/system/quiver.nix b/system/quiver.nix index f5e9187..166caae 100644 --- a/system/quiver.nix +++ b/system/quiver.nix @@ -10,6 +10,7 @@ }: { imports = [ ./configuration.nix + # ../ollama.nix ]; boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbcore" "sd_mod"]; @@ -74,7 +75,6 @@ extraOptions = "--add-runtime nvidia=/run/current-system/sw/bin/nvidia-container-runtime"; }; }; - systemd.enableUnifiedCgroupHierarchy = false; # libnvidia-container doesn't support cgroups v2 services.minidlna = { enable = true;