at master 5.4 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 inherit (lib) types; 9 10 cfg = config.services.open-webui; 11in 12{ 13 options = { 14 services.open-webui = { 15 enable = lib.mkEnableOption "Open-WebUI server"; 16 package = lib.mkPackageOption pkgs "open-webui" { }; 17 18 stateDir = lib.mkOption { 19 type = types.path; 20 default = "/var/lib/open-webui"; 21 example = "/home/foo"; 22 description = "State directory of Open-WebUI."; 23 }; 24 25 host = lib.mkOption { 26 type = types.str; 27 default = "127.0.0.1"; 28 example = "0.0.0.0"; 29 description = '' 30 The host address which the Open-WebUI server HTTP interface listens to. 31 ''; 32 }; 33 34 port = lib.mkOption { 35 type = types.port; 36 default = 8080; 37 example = 11111; 38 description = '' 39 Which port the Open-WebUI server listens to. 40 ''; 41 }; 42 43 environment = lib.mkOption { 44 type = types.attrsOf types.str; 45 default = { 46 SCARF_NO_ANALYTICS = "True"; 47 DO_NOT_TRACK = "True"; 48 ANONYMIZED_TELEMETRY = "False"; 49 }; 50 example = '' 51 { 52 OLLAMA_API_BASE_URL = "http://127.0.0.1:11434"; 53 # Disable authentication 54 WEBUI_AUTH = "False"; 55 } 56 ''; 57 description = '' 58 Extra environment variables for Open-WebUI. 59 For more details see <https://docs.openwebui.com/getting-started/advanced-topics/env-configuration/> 60 ''; 61 }; 62 63 environmentFile = lib.mkOption { 64 description = '' 65 Environment file to be passed to the systemd service. 66 Useful for passing secrets to the service to prevent them from being 67 world-readable in the Nix store. 68 ''; 69 type = lib.types.nullOr lib.types.path; 70 default = null; 71 example = "/var/lib/secrets/openWebuiSecrets"; 72 }; 73 74 openFirewall = lib.mkOption { 75 type = types.bool; 76 default = false; 77 description = '' 78 Whether to open the firewall for Open-WebUI. 79 This adds `services.open-webui.port` to `networking.firewall.allowedTCPPorts`. 80 ''; 81 }; 82 }; 83 }; 84 85 config = lib.mkIf cfg.enable { 86 systemd.services.open-webui = { 87 description = "User-friendly WebUI for LLMs"; 88 wantedBy = [ "multi-user.target" ]; 89 after = [ "network.target" ]; 90 91 environment = { 92 STATIC_DIR = "${cfg.stateDir}/static"; 93 DATA_DIR = "${cfg.stateDir}/data"; 94 HF_HOME = "${cfg.stateDir}/hf_home"; 95 SENTENCE_TRANSFORMERS_HOME = "${cfg.stateDir}/transformers_home"; 96 WEBUI_URL = "http://localhost:${toString cfg.port}"; 97 } 98 // cfg.environment; 99 100 # backwards compatability migration 101 preStart = '' 102 if [ -d "${cfg.stateDir}/data" ] && [ -n "$(ls -A "${cfg.stateDir}/data" 2>/dev/null)" ]; then 103 exit 0 104 fi 105 106 mkdir -p "${cfg.stateDir}/data" 107 108 [ -f "${cfg.stateDir}/webui.db" ] && mv "${cfg.stateDir}/webui.db" "${cfg.stateDir}/data/" 109 110 for dir in cache uploads vector_db; do 111 [ -d "${cfg.stateDir}/$dir" ] && mv "${cfg.stateDir}/$dir" "${cfg.stateDir}/data/" 112 done 113 114 exit 0 115 ''; 116 117 serviceConfig = { 118 ExecStart = "${lib.getExe cfg.package} serve --host \"${cfg.host}\" --port ${toString cfg.port}"; 119 EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile; 120 WorkingDirectory = cfg.stateDir; 121 StateDirectory = "open-webui"; 122 RuntimeDirectory = "open-webui"; 123 RuntimeDirectoryMode = "0755"; 124 PrivateTmp = true; 125 DynamicUser = true; 126 DevicePolicy = "closed"; 127 LockPersonality = true; 128 MemoryDenyWriteExecute = false; # onnxruntime/capi/onnxruntime_pybind11_state.so: cannot enable executable stack as shared object requires: Permission Denied 129 PrivateUsers = true; 130 ProtectHome = true; 131 ProtectHostname = true; 132 ProtectKernelLogs = true; 133 ProtectKernelModules = true; 134 ProtectKernelTunables = true; 135 ProtectControlGroups = true; 136 ProcSubset = "all"; # Error in cpuinfo: failed to parse processor information from /proc/cpuinfo 137 RestrictNamespaces = true; 138 RestrictRealtime = true; 139 SystemCallArchitectures = "native"; 140 UMask = "0077"; 141 CapabilityBoundingSet = ""; 142 RestrictAddressFamilies = [ 143 "AF_INET" 144 "AF_INET6" 145 "AF_UNIX" 146 ]; 147 ProtectClock = true; 148 ProtectProc = "invisible"; 149 SystemCallFilter = [ 150 "@system-service" 151 "~@privileged" 152 ]; 153 SupplementaryGroups = [ "render" ]; # for rocm to access /dev/dri/renderD* devices 154 DeviceAllow = [ 155 # CUDA 156 # https://docs.nvidia.com/dgx/pdf/dgx-os-5-user-guide.pdf 157 "char-nvidiactl" 158 "char-nvidia-caps" 159 "char-nvidia-frontend" 160 "char-nvidia-uvm" 161 # ROCm 162 "char-drm" 163 "char-fb" 164 "char-kfd" 165 # WSL (Windows Subsystem for Linux) 166 "/dev/dxg" 167 ]; 168 }; 169 }; 170 171 networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; }; 172 }; 173 174 meta.maintainers = with lib.maintainers; [ shivaraj-bh ]; 175}