[GH-ISSUE #874] Add flag --web-root for serving UI (w/ code example) #62457

Closed
opened 2026-05-03 09:02:13 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @coolaj86 on GitHub (Oct 22, 2023).
Original GitHub issue: https://github.com/ollama/ollama/issues/874

edit: removed potentially confusing language that was given as an example, not a fixed implementation detail

ollama serve --web-root ./ollama-webui/
  1. Serve /api/* to the API
  2. For all other requests, return results from the web server
  3. If the --web-root flag is given, serve that directory for static files (index.html, etc)
  4. If --web-root is not given, (optionally) serve an embedded filesystem (i.e. a help page)

Here's a tested, working example:

# serves ./documentation/
go run main.go

# serves ./customui/
go run main.go --web-root ./customui/
main.go
webui/index.html
customui/index.html
package main

import (
	"embed"
	"flag"
	"fmt"
	"io/fs"
	"net/http"
	"os"
)

//go:embed webui/*
var defaultWebRoot embed.FS

func main() {
	var webRoot string
	flag.StringVar(&webRoot, "web-root", "", "serve the given GPT API Web Client")
	flag.Parse()

	mux := http.NewServeMux()

	apiHandler := func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "This is the API route.")
	}

	mux.HandleFunc("/api/", apiHandler)

	var webRootHandler http.Handler
	if len(webRoot) > 0 {
		webRootFs := http.Dir(webRoot)
		webRootHandler = http.FileServer(webRootFs)
	} else {
		webRootFs, err := fs.Sub(defaultWebRoot, "webui")
		if err != nil {
			// panic only because this should be impossible
			panic(err)
		}
		webRootHttpFs := http.FS(webRootFs)
		webRootHandler = http.FileServer(webRootHttpFs)
	}
	mux.Handle("/", webRootHandler)

	port := os.Getenv("PORT")
	if len(port) == 0 {
		port = "8080"
	}
	addr := "0.0.0.0:" + port

	fmt.Println("Serving on ", addr)
	http.ListenAndServe(addr, mux)
}
Originally created by @coolaj86 on GitHub (Oct 22, 2023). Original GitHub issue: https://github.com/ollama/ollama/issues/874 **edit**: removed potentially confusing language that was given as an example, not a fixed implementation detail ```sh ollama serve --web-root ./ollama-webui/ ``` 1. Serve `/api/*` to the API 2. For all other requests, return results from the web server 3. If the `--web-root` flag is given, serve that directory for static files (index.html, etc) 4. If `--web-root` is not given, (optionally) serve an embedded filesystem (i.e. a help page) Here's a tested, working example: ```sh # serves ./documentation/ go run main.go # serves ./customui/ go run main.go --web-root ./customui/ ``` ```text main.go webui/index.html customui/index.html ``` ```go package main import ( "embed" "flag" "fmt" "io/fs" "net/http" "os" ) //go:embed webui/* var defaultWebRoot embed.FS func main() { var webRoot string flag.StringVar(&webRoot, "web-root", "", "serve the given GPT API Web Client") flag.Parse() mux := http.NewServeMux() apiHandler := func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "This is the API route.") } mux.HandleFunc("/api/", apiHandler) var webRootHandler http.Handler if len(webRoot) > 0 { webRootFs := http.Dir(webRoot) webRootHandler = http.FileServer(webRootFs) } else { webRootFs, err := fs.Sub(defaultWebRoot, "webui") if err != nil { // panic only because this should be impossible panic(err) } webRootHttpFs := http.FS(webRootFs) webRootHandler = http.FileServer(webRootHttpFs) } mux.Handle("/", webRootHandler) port := os.Getenv("PORT") if len(port) == 0 { port = "8080" } addr := "0.0.0.0:" + port fmt.Println("Serving on ", addr) http.ListenAndServe(addr, mux) } ```
Author
Owner

@coolaj86 commented on GitHub (Oct 22, 2023):

This would be added right around here:
ccff9ca09c/server/routes.go (L644-L661)

The best approach would probably be to change routes.go to return an http-compatible router r, and lift the non-API related boilerplate up into cmd.go rather that sending the TCP listener deeper into layers that don't have any direct dependency on the inner workings of the TCP module.

<!-- gh-comment-id:1773986083 --> @coolaj86 commented on GitHub (Oct 22, 2023): This would be added right around here: https://github.com/jmorganca/ollama/blob/ccff9ca09c1fb6709ba4456f0285b97bd5db9599/server/routes.go#L644-L661 The best approach would probably be to change routes.go to return an http-compatible router `r`, and lift the non-API related boilerplate up into `cmd.go` rather that sending the TCP listener deeper into layers that don't have any direct dependency on the inner workings of the TCP module.
Author
Owner

@coolaj86 commented on GitHub (Oct 24, 2023):

@jmorganca, @mchiang0610 if I create the PR for this will you accept it?

<!-- gh-comment-id:1776321942 --> @coolaj86 commented on GitHub (Oct 24, 2023): @jmorganca, @mchiang0610 if I create the PR for this will you accept it?
Author
Owner

@coolaj86 commented on GitHub (Oct 24, 2023):

@mchiang0610 ^^

<!-- gh-comment-id:1778124822 --> @coolaj86 commented on GitHub (Oct 24, 2023): @mchiang0610 ^^
Author
Owner

@mxyng commented on GitHub (Oct 25, 2023):

We're not currently planning on embedding a UI into the project. There are plenty of community projects that add a UI which can be integrated into ollama quickly and easily. See https://github.com/jmorganca/ollama#community-integrations

<!-- gh-comment-id:1779894231 --> @mxyng commented on GitHub (Oct 25, 2023): We're not currently planning on embedding a UI into the project. There are plenty of community projects that add a UI which can be integrated into ollama quickly and easily. See https://github.com/jmorganca/ollama#community-integrations
Author
Owner

@coolaj86 commented on GitHub (Oct 25, 2023):

@mxyng I think you got this confused with the other issue I had opened.

This is issue is NOT about embedding a UI.

This is about exposing the existing Go file server so that a user-selected directory can be served.

Could you please reopen for discussion on this topic?

<!-- gh-comment-id:1779999637 --> @coolaj86 commented on GitHub (Oct 25, 2023): @mxyng I think you got this confused with the other issue I had opened. This is issue is NOT about embedding a UI. This is about exposing the existing Go file server so that a user-selected directory can be served. Could you please reopen for discussion on this topic?
Author
Owner

@mxyng commented on GitHub (Oct 25, 2023):

Sorry if I misunderstood but I'm not sure what "existing Go file server" you're referring to. There's no such server I'm aware of. Moreover, serving user defined files isn't what ollama is designed for and implementing this feature will be counter to ollama's core goals.

For these reasons, I'm going to keep this issue closed.

<!-- gh-comment-id:1780208381 --> @mxyng commented on GitHub (Oct 25, 2023): Sorry if I misunderstood but I'm not sure what "existing Go file server" you're referring to. There's no such server I'm aware of. Moreover, serving user defined files isn't what ollama is designed for and implementing this feature will be counter to ollama's core goals. For these reasons, I'm going to keep this issue closed.
Author
Owner

@jmorganca commented on GitHub (Oct 25, 2023):

Hi @coolaj86! Thanks so much for this issue. To add to @mxyng's comment, it would be really hard to support all configurations of file servers (e.g. headers, routing etc) to support all the different UIs built on Ollama. Are there changes to the API or ollama serve command that could help solve any compatibility issues with UIs (or make them easier to run/deploy together)?

<!-- gh-comment-id:1780210078 --> @jmorganca commented on GitHub (Oct 25, 2023): Hi @coolaj86! Thanks so much for this issue. To add to @mxyng's comment, it would be really hard to support all configurations of file servers (e.g. headers, routing etc) to support all the different UIs built on Ollama. Are there changes to the API or `ollama serve` command that could help solve any compatibility issues with UIs (or make them easier to run/deploy together)?
Author
Owner

@coolaj86 commented on GitHub (Oct 26, 2023):

@jmorganca literally just using the default built-in Go webserver with the existing Gin router is enough.

All of those other things can be left to web proxies and whatnot in production environments.

I'm just saying to make it accessible so that anyone can just plop an index.html (or a web ui from any of the other projects) in a folder and start playing around without needing to configure CORS or reverse proxy or start a system service or orchestration layer or get bogged down in framework build steps.

Sure, some people will want to develop things that are very complex and require all those things - but I just want to be able to show this off to someone and see the real potential without them feeling like they have to be a docker or Linux expert just to get a page up with a prompt.

I want 0-60 on that "wow, this can run on my computer - I can build something with this" experience.

As you've probably notice here and in other repos' issues, it's a huge barrier to entry for inexperienced devs to get a web server up and configured correctly - but there's not actually any technical requirement for them to need one in the first place.

The only reason CORS or proxies are needed to test this is because there's no way to tell it what directory to load for the "hello world".

<!-- gh-comment-id:1780439193 --> @coolaj86 commented on GitHub (Oct 26, 2023): @jmorganca literally just using the default built-in Go webserver with the existing Gin router is enough. All of those other things can be left to web proxies and whatnot in production environments. I'm just saying to make it accessible so that anyone can just plop an index.html (or a web ui from any of the other projects) in a folder and start playing around without needing to configure CORS or reverse proxy or start a system service or orchestration layer or get bogged down in framework build steps. Sure, some people will want to develop things that are very complex and require all those things - but I just want to be able to show this off to someone and see the real potential without them feeling like they have to be a docker or Linux expert just to get a page up with a prompt. I want 0-60 on that "wow, this can run on my computer - I can build something with this" experience. As you've probably notice here and in other repos' issues, it's a huge barrier to entry for inexperienced devs to get a web server up and configured correctly - but there's not actually any technical requirement for them to need one in the first place. The only reason CORS or proxies are needed to test this is because there's no way to tell it what directory to load for the "hello world".
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/ollama#62457