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 sudo privileges.
  • 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 to your_server_ip.
  • Nginx installed, and UFW allowing OpenSSH and Nginx 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 ports entry 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:

  1. Click your avatar and open Admin Panel.
  2. Go to Settings > General.
  3. Use Enable New Sign Ups to turn self-registration off entirely, or Default User Role to choose between pending and user.
  4. 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.

Step 6 - Chatting with documents

Open WebUI includes retrieval augmented generation (RAG), so a model can answer questions using your files:

  1. In a new chat, click the + button next to the message box and upload a PDF, Markdown or text file.
  2. 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.