From 91dfbb1bba3318c1604e75ecc95e23b2991001db Mon Sep 17 00:00:00 2001 From: Daniel Hiltgen Date: Wed, 30 Oct 2024 09:24:31 -0700 Subject: [PATCH] windows: Support alt install paths, fit and finish (#6967) * windows: Support alt install paths Advanced users are leveraging innosetup's /DIR switch to target an alternate location, but we get confused by things not existing in the LocalAppData dir. This also hardens the server path lookup code for a future attempt to unify with a ./bin prefix * Fit and finish improvements for windows app Document alternate install location instructions for binaries and model. Pop up progress UI for upgrades (automatic, with cancel button). Expose non-default port in menu to disambiguate mutiple instances. Set minimum Windows version to 10 22H2 --- app/lifecycle/lifecycle.go | 2 ++ app/lifecycle/paths.go | 11 ++++++++--- app/lifecycle/server.go | 6 ++++++ app/lifecycle/updater_windows.go | 12 ++++-------- app/ollama.iss | 4 ++-- app/tray/wintray/menus.go | 13 +++++++------ docs/windows.md | 30 ++++++++++++++++++++++++++++++ 7 files changed, 59 insertions(+), 19 deletions(-) diff --git a/app/lifecycle/lifecycle.go b/app/lifecycle/lifecycle.go index ab624e81..c24fe646 100644 --- a/app/lifecycle/lifecycle.go +++ b/app/lifecycle/lifecycle.go @@ -11,10 +11,12 @@ import ( "github.com/ollama/ollama/app/store" "github.com/ollama/ollama/app/tray" + "github.com/ollama/ollama/envconfig" ) func Run() { InitLogging() + slog.Info("app config", "env", envconfig.Values()) ctx, cancel := context.WithCancel(context.Background()) var done chan int diff --git a/app/lifecycle/paths.go b/app/lifecycle/paths.go index 4d9f4c5a..42ae8267 100644 --- a/app/lifecycle/paths.go +++ b/app/lifecycle/paths.go @@ -36,8 +36,13 @@ func init() { ServerLogFile = filepath.Join(AppDataDir, "server.log") UpgradeLogFile = filepath.Join(AppDataDir, "upgrade.log") - // Executables are stored in APPDATA - AppDir = filepath.Join(localAppData, "Programs", "Ollama") + exe, err := os.Executable() + if err != nil { + slog.Warn("error discovering executable directory", "error", err) + AppDir = filepath.Join(localAppData, "Programs", "Ollama") + } else { + AppDir = filepath.Dir(exe) + } // Make sure we have PATH set correctly for any spawned children paths := strings.Split(os.Getenv("PATH"), ";") @@ -64,7 +69,7 @@ func init() { } // Make sure our logging dir exists - _, err := os.Stat(AppDataDir) + _, err = os.Stat(AppDataDir) if errors.Is(err, os.ErrNotExist) { if err := os.MkdirAll(AppDataDir, 0o755); err != nil { slog.Error(fmt.Sprintf("create ollama dir %s: %v", AppDataDir, err)) diff --git a/app/lifecycle/server.go b/app/lifecycle/server.go index 37957399..f7aa2026 100644 --- a/app/lifecycle/server.go +++ b/app/lifecycle/server.go @@ -18,11 +18,17 @@ func getCLIFullPath(command string) string { var cmdPath string appExe, err := os.Executable() if err == nil { + // Check both the same location as the tray app, as well as ./bin cmdPath = filepath.Join(filepath.Dir(appExe), command) _, err := os.Stat(cmdPath) if err == nil { return cmdPath } + cmdPath = filepath.Join(filepath.Dir(appExe), "bin", command) + _, err = os.Stat(cmdPath) + if err == nil { + return cmdPath + } } cmdPath, err = exec.LookPath(command) if err == nil { diff --git a/app/lifecycle/updater_windows.go b/app/lifecycle/updater_windows.go index 1d3830d4..293dd603 100644 --- a/app/lifecycle/updater_windows.go +++ b/app/lifecycle/updater_windows.go @@ -26,19 +26,15 @@ func DoUpgrade(cancel context.CancelFunc, done chan int) error { slog.Info("starting upgrade with " + installerExe) slog.Info("upgrade log file " + UpgradeLogFile) - // When running in debug mode, we'll be "verbose" and let the installer pop up and prompt + // make the upgrade show progress, but non interactive installArgs := []string{ "/CLOSEAPPLICATIONS", // Quit the tray app if it's still running "/LOG=" + filepath.Base(UpgradeLogFile), // Only relative seems reliable, so set pwd "/FORCECLOSEAPPLICATIONS", // Force close the tray app - might be needed - } - // make the upgrade as quiet as possible (no GUI, no prompts) - installArgs = append(installArgs, - "/SP", // Skip the "This will install... Do you wish to continue" prompt - "/SUPPRESSMSGBOXES", + "/SP", // Skip the "This will install... Do you wish to continue" prompt + "/NOCANCEL", // Disable the ability to cancel upgrade mid-flight to avoid partially installed upgrades "/SILENT", - "/VERYSILENT", - ) + } // Safeguard in case we have requests in flight that need to drain... slog.Info("Waiting for server to shutdown") diff --git a/app/ollama.iss b/app/ollama.iss index 4038815a..7362eeeb 100644 --- a/app/ollama.iss +++ b/app/ollama.iss @@ -53,8 +53,8 @@ RestartIfNeededByRun=no ; https://jrsoftware.org/ishelp/index.php?topic=setup_wizardimagefile WizardSmallImageFile=.\assets\setup.bmp -; TODO verifty actual min windows version... -; OG Win 10 +; Ollama requires Windows 10 22H2 or newer for proper unicode rendering +; TODO: consider setting this to 10.0.19045 MinVersion=10.0.10240 ; First release that supports WinRT UI Composition for win32 apps diff --git a/app/tray/wintray/menus.go b/app/tray/wintray/menus.go index 59624444..9421b489 100644 --- a/app/tray/wintray/menus.go +++ b/app/tray/wintray/menus.go @@ -11,12 +11,13 @@ import ( ) const ( - updateAvailableMenuID = 1 - updateMenuID = updateAvailableMenuID + 1 - separatorMenuID = updateMenuID + 1 - diagLogsMenuID = separatorMenuID + 1 - diagSeparatorMenuID = diagLogsMenuID + 1 - quitMenuID = diagSeparatorMenuID + 1 + _ = iota + updateAvailableMenuID + updateMenuID + separatorMenuID + diagLogsMenuID + diagSeparatorMenuID + quitMenuID ) func (t *winTray) initMenus() error { diff --git a/docs/windows.md b/docs/windows.md index 5f196756..52b517e6 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -25,6 +25,32 @@ Logs will often be helpful in diagnosing the problem (see Ollama uses unicode characters for progress indication, which may render as unknown squares in some older terminal fonts in Windows 10. If you see this, try changing your terminal font settings. +## Filesystem Requirements + +The Ollama install does not require Administrator, and installs in your home directory by default. You'll need at least 4GB of space for the binary install. Once you've installed Ollama, you'll need additional space for storing the Large Language models, which can be tens to hundreds of GB in size. If your home directory doesn't have enough space, you can change where the binaries are installed, and where the models are stored. + +### Changing Install Location + +To install the Ollama application in a location different than your home directory, start the installer with the following flag + +```powershell +OllamaSetup.exe /DIR="d:\some\location" +``` + +### Changing Model Location + +To change where Ollama stores the downloaded models instead of using your home directory, set the environment variable `OLLAMA_MODELS` in your user account. + +1. Start the Settings (Windows 11) or Control Panel (Windows 10) application and search for _environment variables_. + +2. Click on _Edit environment variables for your account_. + +3. Edit or create a new variable for your user account for `OLLAMA_MODELS` where you want the models stored + +4. Click OK/Apply to save. + +If Ollama is already running, Quit the tray application and relaunch it from the Start menu, or a new terminal started after you saved the environment variables. + ## API Access Here's a quick example showing API access from `powershell` @@ -52,6 +78,10 @@ the explorer window by hitting `+R` and type in: The Ollama Windows installer registers an Uninstaller application. Under `Add or remove programs` in Windows Settings, you can uninstall Ollama. +> [!NOTE] +> If you have [changed the OLLAMA_MODELS location](#changing-model-location), the installer will not remove your downloaded models + + ## Standalone CLI The easiest way to install Ollama on Windows is to use the `OllamaSetup.exe`