Short answer
To self-host a ChatGPT alternative, run Open WebUI in Docker on a private address, point it at a model you host (Ollama for small teams, vLLM for shared GPU servers), create the admin account first, then switch new sign-ups to approval. Put HTTPS in front, back up the data volume and pin the image version. Privacy depends on the model backend, not the interface.
The steps at a glance
- Decide where prompts will go
- Install Ollama and pull a model
- Let the Open WebUI container reach Ollama
- Start Open WebUI
- Create the admin account, then lock down sign-up
- Connect the model backends you chose
- Set roles, groups and the privacy defaults
- Put HTTPS in front with a reverse proxy
- Back up the data and plan upgrades
Before you start
Who this is for
- IT leads and engineers setting up a private chat interface for a team, a department or a pilot.
- Anyone who wants a ChatGPT-style experience where prompts stay on infrastructure they control.
- Teams who already have Ollama or a vLLM endpoint and need a front end for non-technical colleagues.
Probably not for you if
- Teams who need governed agents, permission-aware company search and an audit trail from day one. The interface covers only part of that; see the limits section below.
- Anyone who wants to white-label the interface for customers. Read the Open WebUI licence section first.
Prerequisites
- A Linux server or workstation with Docker installed. The commands below use Linux.
- A model backend you control. This guide uses Ollama; if you have a vLLM server, how to self-host an LLM sets one up.
- A hostname for the interface if more than one person will use it, and the ability to open a firewall port.
- An email-style admin identity you can keep: the first account created becomes the administrator.
- Time
- About 1 to 2 hours for a working pilot, plus time for single sign-on and a short policy for users.
- Cost
- Free software. You pay for the server, power and the time to maintain it. Hosted model APIs, if you connect any, are billed by their providers.
- Hardware
- The interface itself is light. The model is what needs memory: a small model on a modern laptop or workstation for a pilot, a GPU server for a shared team.
- Skill
- Comfortable with Docker and the command line.
Estimates are ours, not measurements, and move with your hardware, data and network.
The Open WebUI licence: read it if you will rebrand
Open WebUI is free to run, but its licence is not a plain open-source one. From v0.6.6 (19 April 2025) it adds a branding clause: you may not alter, remove or obscure the "Open WebUI" branding unless you have 50 or fewer users in a 30-day period, or have permission or an enterprise licence. The project's own page says that licence is not OSI-approved. Versions up to v0.6.5 stayed under BSD-3-Clause.
For an internal tool that keeps the branding, this changes little. If you plan to rebrand for a larger group or for customers, read the licence text and ask the project. This is orientation, not legal advice.
Step 1Decide where prompts will go
You end up with: A written choice of model backend, because it decides your privacy, not the chat interface.
Open WebUI is an interface. The model behind it generates the text, and wherever that model runs is where your prompts are sent. A self-hosted interface pointed at a hosted API still sends every prompt to that provider. Sometimes that is what you want. Decide on purpose.
For a pilot, Ollama on the same machine is the shortest path: prompts never leave the box. For a shared team, a vLLM server on a GPU machine handles many users better. For tasks the data class allows, you can add a hosted model later through a gateway. Write the choice into your acceptable-use note so users know which data may go where.
Backend Where prompts go Good for Watch out for Ollama on the same host Stay on the host Pilots, small teams, laptops and workstations Limited concurrency; one person's long request can slow others vLLM on a GPU server you run Stay on your network Shared teams with real concurrency You now operate a GPU server A hosted API Go to that provider Hard tasks that your data policy allows Anyone with a key can send data out; control keys centrally Step 2Install Ollama and pull a model
You end up with: A model answers from the command line and over Ollama's local API.
On Linux, the Ollama documentation gives a one-line installer, and the service runs under systemd. Pull a model, run it once to see that it works, then test the API. The Ollama quickstart uses
gemma4:e2bas its example, which is a small model suited to a first test. Pick a larger one later once you know how much memory you have; our guide to running LLMs locally covers sizing.By default Ollama listens on 127.0.0.1 port 11434. That is the right default; you will change it in the next step only if you need to.
Install Ollama (Linux) · bash curl -fsSL https://ollama.com/install.sh | shCheck the service · bash sudo systemctl status ollamaDownload and try a small model (type /bye to leave) · bash ollama pull gemma4:e2b ollama run gemma4:e2bTest the REST API · bash curl http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{"model": "gemma4:e2b", "messages": [{"role": "user", "content": "Say hello in one sentence."}], "stream": false}'Checked against: Ollama Linux install, Ollama quickstart, Ollama FAQ
Step 3Let the Open WebUI container reach Ollama
You end up with: Ollama is reachable from Docker, and still not reachable from the wider network.
Open WebUI will run in a container, and the container cannot see 127.0.0.1 on the host. The Open WebUI troubleshooting page gives three fixes for the common "server connection error": run the container with
--network=host, setOLLAMA_HOST=0.0.0.0so Ollama accepts connections beyond localhost, or usehost.docker.internalas the hostname. The quick-start command already adds--add-host=host.docker.internal:host-gatewayfor that third route.The Ollama FAQ shows how to set the variable for a systemd service: edit the service with
systemctl edit ollama.service, add the environment line, then reload and restart. Be careful with what this does. Ollama has no login. Listening on 0.0.0.0 makes it answer anyone who can reach port 11434, so block that port at the firewall for everything except the Docker network.If you would rather avoid this step entirely, Open WebUI publishes an image with Ollama bundled in (the
:ollamatag). It is simpler, but it ties the model and the interface together in one container, which is harder to scale and upgrade separately.Open the service override and add the lines below · bash sudo systemctl edit ollama.serviceAdd this under [Service] in the editor · text [Service] Environment="OLLAMA_HOST=0.0.0.0:11434"Apply it · bash sudo systemctl daemon-reload sudo systemctl restart ollamaChecked against: Ollama FAQ, Open WebUI connection error troubleshooting, Open WebUI Docker quick start
Step 4Start Open WebUI
You end up with: Open WebUI runs on localhost:3000 with its data in a named volume and a persistent secret key.
Generate a secret key first. The Open WebUI documentation says the key must persist: without it, every time the container is recreated everyone is logged out. Then run the container.
This is the default command from the Open WebUI quick start with three changes. The port binds to 127.0.0.1 so nothing is exposed until your proxy is ready.
OLLAMA_BASE_URLpoints at the host throughhost.docker.internal. And you should replace:mainwith a specific version tag for anything beyond a trial; the docs say:mainis a rolling tag, and the update page warns it "can include breaking changes without warning". Look up the current release tag on the project's releases page and use that.The
open-webuivolume holds your chats, users and settings. The documentation puts it bluntly: never run without it.Create a secret key · bash export WEBUI_SECRET_KEY="$(openssl rand -hex 32)" echo "$WEBUI_SECRET_KEY" # store this in your password managerRun Open WebUI · bash docker run -d -p 127.0.0.1:3000:8080 \ --add-host=host.docker.internal:host-gateway \ -v open-webui:/app/backend/data \ -e WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" \ -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \ --name open-webui --restart always \ ghcr.io/open-webui/open-webui:mainWith an NVIDIA GPU, the quick start uses the :cuda image and --gpus all · bash docker run -d -p 127.0.0.1:3000:8080 --gpus all \ --add-host=host.docker.internal:host-gateway \ -v open-webui:/app/backend/data \ -e WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" \ -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \ --name open-webui --restart always \ ghcr.io/open-webui/open-webui:cudaChecked against: Open WebUI Docker quick start, Open WebUI environment variable reference, Open WebUI updating guide, Docker port publishing
Step 5Create the admin account, then lock down sign-up
You end up with: You are the administrator, and new people cannot get in without approval.
Browse to http://localhost:3000 and sign up. The Open WebUI roles documentation says the very first account on a fresh installation is automatically given the Admin role. That makes the first sign-up an important moment: do it yourself, straight after the container starts, before anyone else knows the address.
Later sign-ups get the Pending role by default, which has no access until an admin approves it. The environment reference lists
DEFAULT_USER_ROLEwith options pending, user and admin, and a default of pending, andENABLE_SIGNUPfor toggling account creation. One quirk catches people out. Settings marked as persistent config apply from the environment only on the first launch; after that the value stored in the database wins. So to change sign-up behaviour later, use the admin settings in the interface, or setENABLE_PERSISTENT_CONFIGtoFalseand accept that changes made in the UI will then not be saved.If you will use single sign-on, plan it now. The reference documents
ENABLE_OAUTH_SIGNUP(default False) and notes thatOPENID_PROVIDER_URLshould be set for the Google and Microsoft sign-in options, otherwise logout may not work. Follow the provider-specific section in the environment reference for the rest of the variables.Checked against: Open WebUI roles, Open WebUI environment variable reference
Step 6Connect the model backends you chose
You end up with: The model picker lists your models, and only the backends you approved.
Ollama models appear on their own once
OLLAMA_BASE_URLis right. For anything else, the Open WebUI documentation says adding a provider is "as simple as entering a URL and API key" in Settings, Admin, Connections. For an OpenAI-compatible server such as vLLM, the base URL ends in/v1.You can also set these by environment variable.
OPENAI_API_BASE_URLdefaults tohttps://api.openai.com/v1, andOPENAI_API_KEYholds the key. Take that default seriously. If someone puts a hosted key in there, prompts go to that provider, so decide who may add connections, and keep provider keys in one place under an owner. A gateway in front of all model traffic is the clean answer once you have more than one backend; see how to set up an LLM gateway.Test with a sentence that contains nothing sensitive, then check on the model server that the request arrived there. That is how you prove where prompts actually go.
Example: connect a vLLM server on the same host by environment variable · bash docker rm -f open-webui docker run -d -p 127.0.0.1:3000:8080 \ --add-host=host.docker.internal:host-gateway \ -v open-webui:/app/backend/data \ -e WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" \ -e OPENAI_API_BASE_URL=http://host.docker.internal:8000/v1 \ -e OPENAI_API_KEY="$VLLM_KEY" \ --name open-webui --restart always \ ghcr.io/open-webui/open-webui:mainCheck the Ollama OpenAI-compatible endpoint if you prefer to connect to Ollama that way · bash curl http://localhost:11434/v1/modelsChecked against: Open WebUI: connect a provider, Open WebUI environment variable reference, Ollama OpenAI compatibility
Step 7Set roles, groups and the privacy defaults
You end up with: People have the access they need and no more, and admins cannot casually read chats.
Open WebUI separates roles (Admin, User, Pending) from groups and permissions. Roles set the baseline trust level. Groups organise users and grant additional permissions or shared access to resources, and permissions are granular feature flags such as whether a user can delete chats or use web search. The model is additive: users start with their default rights and group membership adds capabilities. So keep the default role minimal and grant more through groups.
Admin access to other people's conversations is not automatic. The documentation says that the
ENABLE_ADMIN_CHAT_ACCESS=Falsevariable can stop admins viewing user chats. Decide your position on this before you tell staff the tool is private, and tell them what you chose. If your policy needs administrators to review conversations, say so in the acceptable-use note instead of leaving people to assume.Finally, write a short note for users that says which data classes may be entered, which models are connected and where they run, how long chats are kept, and who to ask for help. A one-page note does more for privacy than most settings.
Checked against: Open WebUI RBAC overview, Open WebUI roles
Step 8Put HTTPS in front with a reverse proxy
You end up with: Users reach the interface at https://chat.example.com, and the container port is not exposed.
Browsers and password managers behave properly only over HTTPS, and sign-in tokens should not cross a network in clear text. Caddy keeps this short: it provisions certificates automatically for a public domain name. The Caddy quick start shows a site address followed by a
reverse_proxyline, thencaddy runfrom the same directory. Caddy's documentation also states that its proxy supports WebSocket connections, which chat interfaces use for streaming.If the server has no public DNS name, automatic certificates will not work. Use an internal certificate authority or your organisation's existing proxy and certificate process instead. Whatever you use, open the firewall for the proxy port only, and leave port 3000 bound to 127.0.0.1 as in step 4.
Caddyfile (replace the hostname) · text chat.example.com { reverse_proxy localhost:3000 }Start Caddy from the directory with the Caddyfile · bash caddy runChecked against: Caddy reverse proxy quick start, Caddy reverse_proxy directive
Step 9Back up the data and plan upgrades
You end up with: A tested backup and a known routine for updating the interface.
Back up before every upgrade. The Open WebUI update page warns that database migrations are one-way: rolling back to an older version will not undo them, so the only safe rollback is to restore from a backup taken before the update. It gives a backup command that archives the volume with a throwaway container.
The update itself is: remove the container, pull the image, run the same command again. Your data persists in the volume. Pin the version tag so that "update" means a version you chose, tested on a copy first if the interface matters to many people.
Test the restore once. A backup that has never been restored is a guess.
Back up the data volume · bash docker run --rm -v open-webui:/data -v "$(pwd)":/backup \ alpine tar czf /backup/openwebui-$(date +%Y%m%d).tar.gz /dataUpdate: remove, pull, recreate (use the same flags as step 4) · bash docker rm -f open-webui docker pull ghcr.io/open-webui/open-webui:mainChecked against: Open WebUI updating guide
Alternatives to Open WebUI
LibreChat is the main alternative. Its repository states an MIT licence and lists multi-user authentication with OAuth2, LDAP and email login, Model Context Protocol tool support and agents. The documented Docker route is git clone https://github.com/LibreChat-AI/LibreChat.git, cd LibreChat, cp .env.example .env, then docker compose up -d, with the app on http://localhost:3080, and docker compose pull followed by docker compose up to update. Choose it if you want one front end across many providers under a permissive licence.
Our comparison of Open WebUI, LibreChat and AnythingLLM covers the differences in more depth. This guide sticks to Open WebUI because it is the closest match to the ChatGPT experience with a local model engine.
What this setup does not give you
The interface is only part of the work. After this guide you have private chat. You do not yet have permission-aware search over company documents, because built-in document chat indexes what you give it and respecting source permissions is your integration work. You do not have an audit record, since chat history is not evidence. You do not have governed agents, which need scoped tool access and approval steps. And you have a service to patch, back up and support.
If those are requirements, plan them early. See how to build a company brain for AI for the retrieval side and how to govern AI agents for the control side.
Troubleshooting
| What you see | Likely cause | Fix |
|---|---|---|
| Open WebUI shows "Server Connection Error" or no Ollama models | The container cannot reach Ollama on the host, usually because Ollama listens only on 127.0.0.1. | Set OLLAMA_HOST=0.0.0.0:11434 on the Ollama service (step 3), keep --add-host=host.docker.internal:host-gateway, and use http://host.docker.internal:11434 as the base URL. The troubleshooting page also offers --network=host; then use OLLAMA_BASE_URL=http://127.0.0.1:11434. |
| Everyone is logged out each time the container is recreated | No persistent WEBUI_SECRET_KEY was set. | Set the same WEBUI_SECRET_KEY on every run, as in step 4, and store it in a password manager. |
You changed ENABLE_SIGNUP or another setting in the command and nothing changed | Persistent config: after the first launch, the stored database value takes precedence over the environment. | Change it in the admin settings, or set ENABLE_PERSISTENT_CONFIG to False if you want environment variables to always win. |
| New colleagues sign up but see nothing | New accounts get the Pending role until an admin approves them (the default). | Approve the account in the admin user list, or set a different default role if your policy allows it. |
| The model list is empty after you added a vLLM connection | The URL is missing the /v1 suffix, the key is wrong, or the container cannot reach the host port. | Use http://host.docker.internal:8000/v1, send the key you set with --api-key, and test the same URL from inside the container network. |
| Chats are lost after an update | The container ran without the data volume mounted. | Always mount -v open-webui:/app/backend/data. Restore from your backup if you have one, and note that migrations cannot be rolled back. |
| The page loads but streaming responses stall behind a proxy | The proxy is buffering responses or not passing WebSocket upgrades. | The Caddy documentation says its proxy supports WebSocket connections. With another proxy, allow upgrade requests and disable response buffering for the chat path. |
Verify it worked
Next steps
- How to self-host an LLM: a shared GPU endpoint for the interface to use
- How to set up an LLM gateway: central keys, budgets and logs for every model behind the chat
- How to detect shadow AI: find out which other tools your colleagues already use
- AI workspace versus ChatGPT Enterprise: when a hosted assistant is the better answer
Related guides
- How to Self-Host an LLM with vLLM (2026 Guide): Serve an open-weight model as a private, OpenAI-compatible endpoint on your own GPU server, with memory sizing, authentication, TLS, metrics and an upgrade routine.
- How to Run LLMs Locally: Ollama, LM Studio, llama.cpp: Install Ollama, LM Studio or llama.cpp, download a model that fits your memory, chat with it and call it from code through a local OpenAI-compatible endpoint.
- How to Set Up an LLM Gateway with LiteLLM (2026): Run the open-source LiteLLM proxy in Docker with a config file, add a model, issue virtual keys with budgets, set fallbacks, wire health checks, and harden it for production.
- How to Build a Company Brain for AI: A Practical Guide: Build a permission-aware knowledge layer for AI: resolve identities, copy access lists from each source, keep provenance, retrieve under access control, and test freshness and leaks.
- How to Detect Shadow AI in Your Organisation: Define what counts as unsanctioned AI, then find it through identity grants, network logs, expense data and a short staff survey, rank what you find by the data it touches, replace the risky tools with approved ones, and keep monitoring in a proportionate way.
Frequently asked questions
What is the best self-hosted ChatGPT alternative?
There is no single best. Open WebUI is closest to the ChatGPT experience with local models. LibreChat is strongest for many providers under an MIT licence. Pilot two against your own requirements and users before you commit.
Is Open WebUI really open source?
Its code is public and free to run, but from v0.6.6 it carries a branding clause, and the project's own licence page says it is not an OSI-approved open-source licence. For internal use that keeps the branding the practical effect is small.
Is a self-hosted ChatGPT alternative private by default?
The interface runs on your server, but privacy depends on the model backend. With a model you host, prompts stay on your infrastructure. If you connect a hosted API, prompts go to that provider.
Can I use Open WebUI with Ollama and vLLM?
Yes. Open WebUI connects to Ollama through OLLAMA_BASE_URL and to any OpenAI-compatible server, including vLLM, through a connection URL ending in /v1 and an API key.
Do I need a GPU to run a private ChatGPT?
Not for a pilot with a small model on a modern workstation, and not at all if you point the interface at an API. A shared team with larger models needs a GPU server. The interface itself needs little.
Who is the administrator in Open WebUI?
The first account created on a fresh installation is automatically the Admin. Later sign-ups are Pending until approved, by default. Create your admin account yourself immediately after the first start.
How Swfte can help
This guide works without Swfte. If you want the layers around the chat window, Swfte has a governed desktop client and a model gateway.
- Cortex: a governed AI desktop that runs local by default and answers from company files
- Swfte Connect: the gateway that controls provider access and logs model traffic
- Company brain platform page: the knowledge layer behind a company-wide assistant
The company brain is partly in progress: asking questions across company documents is not yet generally available. Check the platform page for current status.
Missing a step or found a command that no longer works? Tell us, or request a how-to.
Sources and last verified
Commands, versions and facts in this guide were checked against the sources below on . Tools change quickly: if something differs from what you see, trust the official documentation and let us know.
- Open WebUI Docker quick start: docker run commands, :main, :cuda and :ollama images, data volume, WEBUI_SECRET_KEY advice, version pinning advice
- Open WebUI environment variable reference: OLLAMA_BASE_URL, OPENAI_API_BASE_URL, OPENAI_API_KEY, WEBUI_SECRET_KEY, ENABLE_SIGNUP, DEFAULT_USER_ROLE, ENABLE_OAUTH_SIGNUP, OPENID_PROVIDER_URL, persistent config behaviour
- Open WebUI: connect a provider: adding providers in Settings, Admin, Connections
- Open WebUI roles: first account is Admin, Pending role, ENABLE_ADMIN_CHAT_ACCESS
- Open WebUI RBAC overview: roles, groups, permissions, additive model
- Open WebUI connection error troubleshooting: --network=host, OLLAMA_HOST=0.0.0.0, host.docker.internal, base URL fixes
- Open WebUI updating guide: backup command, one-way migrations, pinned versions, docker update commands
- Open WebUI licence page: branding clause, 50 user threshold, not OSI-approved, v0.6.6 date
- Ollama Linux install: install script, systemctl status ollama
- Ollama quickstart: ollama pull and run with gemma4:e2b, /api/chat curl example
- Ollama FAQ: default bind 127.0.0.1:11434, OLLAMA_HOST, systemd environment override steps
- Ollama OpenAI compatibility: base URL http://localhost:11434/v1/, /v1/models
- Docker port publishing: 127.0.0.1 port binding and default all-address publishing
- Caddy reverse proxy quick start: Caddyfile with a site address and reverse_proxy, caddy run
- Caddy reverse_proxy directive: WebSocket connections supported
- LibreChat Docker setup: git clone, .env copy, docker compose up -d, port 3080, update commands
- LibreChat repository: MIT licence, OAuth2 LDAP email login, MCP support, agents
Topics
- open webui
- ollama
- chat interface
- self-hosting
- team workspace
Machine-readable copies: this guide as markdown, index of all guides (JSON). Canonical address: https://www.swfte.com/how-to-self-host-chatgpt-alternative.