Open WebUI is a self-hosted web interface for large language models, similar in look and feel to ChatGPT. It supports multiple users, conversation history, document chat (RAG) and connections to both Ollama and any OpenAI-compatible API. In this tutorial you will run Open WebUI and Ollama together with Docker Compose on Ubuntu 24.04, download a model, create the admin account, control who can sign up and publish the interface over HTTPS with Nginx.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS. Small models such as Llama 3.2 3B run on CPU with 8 GB of RAM; larger models need more RAM or an NVIDIA GPU.
- A non-root user with
sudoprivileges. - Docker Engine and the Docker Compose plugin installed from Docker's official repository.
- A domain name, such as
chat.your_domain, with a DNS A record pointing toyour_server_ip. - Nginx installed, and UFW allowing
OpenSSHandNginx Full. - About 20 GB of free disk space for the images and a couple of models.
Step 1 - Creating the Docker Compose project
Running both services in one Compose project puts them on a private Docker network, so Open WebUI reaches Ollama by its service name and Ollama is never exposed. Create a project directory:
sudo mkdir -p /opt/open-webui
sudo chown "$USER":"$USER" /opt/open-webui
cd /opt/open-webui
Open WebUI signs session tokens with a secret key. Generate one and store it in an .env file next to the Compose file:
echo "WEBUI_SECRET_KEY=$(openssl rand -hex 32)" > /opt/open-webui/.env
chmod 600 /opt/open-webui/.env
Create the Compose file:
nano /opt/open-webui/compose.yaml
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
volumes:
- ollama:/root/.ollama
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
depends_on:
- ollama
ports:
- "127.0.0.1:3000:8080"
environment:
OLLAMA_BASE_URL: http://ollama:11434
WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY}
WEBUI_URL: https://chat.your_domain
volumes:
- open-webui:/app/backend/data
restart: unless-stopped
volumes:
ollama:
open-webui:
Replace chat.your_domain with your domain. Key points of this file:
- Open WebUI listens on port 8080 inside the container and is published only on
127.0.0.1:3000. Docker bypasses UFW for published ports, so binding to localhost is what keeps it off the public Internet until Nginx is in front. - The Ollama service has no
portsentry at all; only Open WebUI talks to it. - The named volumes keep models, users and chat history when containers are recreated.
Step 2 - Starting the stack
Pull the images and start both containers in the background:
docker compose up -d
Check that both are running:
docker compose ps
NAME IMAGE COMMAND SERVICE STATUS PORTS
ollama ollama/ollama:latest "/bin/ollama serve" ollama Up 30 seconds 11434/tcp
open-webui ghcr.io/open-webui/open-webui:main "bash start.sh" open-webui Up 30 seconds (healthy) 127.0.0.1:3000->8080/tcp
The first start of Open WebUI downloads an embedding model for document search and can take a minute before it reports healthy. Confirm that the web server answers:
curl -s http://127.0.0.1:3000/health
{"status":true}
Step 3 - Downloading a model with Ollama
Ollama needs at least one model before you can chat. Pull Llama 3.2 3B (about 2 GB), which runs acceptably on CPU:
docker compose exec ollama ollama pull llama3.2
List the installed models:
docker compose exec ollama ollama list
NAME ID SIZE MODIFIED
llama3.2:latest a80c4f17acd5 2.0 GB 10 seconds ago
Models pulled this way appear automatically in Open WebUI's model selector. Browse other models at ollama.com/library and choose sizes that fit your RAM or VRAM.
Using an NVIDIA GPU (optional)
If the server has an NVIDIA GPU with the driver and the NVIDIA Container Toolkit installed, give the Ollama container access to it by adding a deploy block to the ollama service in compose.yaml:
ollama:
image: ollama/ollama:latest
container_name: ollama
volumes:
- ollama:/root/.ollama
restart: unless-stopped
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Apply the change with docker compose up -d, then run a prompt and check nvidia-smi: an ollama process should appear with GPU memory in use.
Step 4 - Publishing Open WebUI with Nginx and HTTPS
Create an Nginx server block for your domain:
sudo nano /etc/nginx/sites-available/open-webui
server {
listen 80;
listen [::]:80;
server_name chat.your_domain;
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 300s;
}
}
The Upgrade and Connection headers allow the WebSocket connection Open WebUI uses for live updates, proxy_buffering off lets streamed answers reach the browser token by token, and client_max_body_size allows document uploads. Enable the site and reload Nginx:
sudo ln -s /etc/nginx/sites-available/open-webui /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Install Certbot and request a certificate. Certbot edits the server block to add HTTPS and a redirect from HTTP:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d chat.your_domain
Verify the HTTPS endpoint:
curl -s https://chat.your_domain/health
{"status":true}
Step 5 - Creating the admin account and controlling sign-ups
Open https://chat.your_domain in a browser right away. The first account created becomes the administrator, so do this before sharing the URL. Click Get started and register with your name, email and a strong password.
By default, later sign-ups are created with the pending role: they can register but cannot use the interface until an admin approves them. You can change this in the admin panel:
- Click your avatar and open Admin Panel.
- Go to Settings > General.
- Use Enable New Sign Ups to turn self-registration off entirely, or Default User Role to choose between
pendinganduser. - Click Save.
To approve or add users, open Admin Panel > Users. You can change a pending user's role to user, or add accounts yourself with the + button when sign-ups are disabled.
NoteSettings such as sign-up behavior can also be passed as environment variables (for example
ENABLE_SIGNUP), but Open WebUI stores them in its database after the first start and the admin panel values take precedence. Changing the environment variable later usually has no effect, so manage these settings from the admin panel.
Step 6 - Chatting with documents
Open WebUI includes retrieval augmented generation (RAG), so a model can answer questions using your files:
- In a new chat, click the + button next to the message box and upload a PDF, Markdown or text file.
- Ask a question about it, for example "Summarize the main points of this document".
For documents you reuse, create a collection under Workspace > Knowledge, upload files to it, then type # in the message box and pick the collection to attach it to the conversation. The first start already downloaded a local embedding model, so documents are indexed on your server without an external API.
Step 7 - Connecting an OpenAI-compatible API (optional)
Open WebUI can use other backends alongside Ollama, such as a vLLM server or a hosted provider. Go to Admin Panel > Settings > Connections, click + in the OpenAI API section, and enter the base URL (for example http://your_vllm_host:8000/v1) and its API key. The models exposed by that endpoint are added to the model selector.
A backend running on the Docker host itself is not reachable at 127.0.0.1 from inside the container. Add this to the open-webui service in compose.yaml, then use http://host.docker.internal:8000/v1 as the URL:
extra_hosts:
- "host.docker.internal:host-gateway"
Step 8 - Updating and backing up
The main tag always points to the latest release. To update, pull the new images and recreate the containers; the volumes keep your data:
cd /opt/open-webui
docker compose pull
docker compose up -d
Users, settings and chats live in the open-webui volume. Back it up with a temporary container that archives it to the current directory:
docker run --rm -v open-webui_open-webui:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/open-webui-backup.tar.gz -C /data .
Compose prefixes volume names with the project name, which is the directory name open-webui. Check the exact name with docker volume ls if the command reports a missing volume.
Troubleshooting
The model selector is empty. Open WebUI cannot reach Ollama or no model is installed. Check that Ollama answers from inside the Open WebUI container:
docker compose exec open-webui curl -s http://ollama:11434/api/tags
An empty {"models":[]} means you still need to pull a model; a connection error means the ollama container is not running (docker compose logs ollama).
Answers arrive all at once instead of streaming. Nginx is buffering the response. Make sure proxy_buffering off; is in the location block and reload Nginx.
502 Bad Gateway from Nginx. The container is still starting or has stopped. Run docker compose ps and docker compose logs open-webui.
Responses are very slow. The model is too large for CPU inference or does not fit in VRAM. Try a smaller model such as llama3.2:1b, or add a GPU as shown in step 3.
Conclusion
Open WebUI and Ollama now run on your Ubuntu 24.04 server behind Nginx with HTTPS, with an admin account and controlled sign-ups. Next, you can pull task-specific models such as coding models, connect a GPU inference server like vLLM for faster responses, and schedule the volume backup from step 8 with cron.
