# Self-host Open WebUI on a VPS: your own private ChatGPT

> Self-host Open WebUI on a VPS as a private ChatGPT: Docker, nginx, HTTPS, OpenAI-compatible APIs or Ollama, safe defaults, by hand or with ZoPanel.

Source: https://zopanel.net/blog/self-host-chatgpt-open-webui  
Updated: 2026-10-21

## Key takeaways

- Open WebUI is an open-source chat interface for OpenAI-compatible APIs and local Ollama models.
- With an API, a VPS with about 2 GB of RAM for Open WebUI is enough; local models need far more memory and ideally a GPU.
- The first account created on Open WebUI becomes the administrator, so create it right after installing.
- Published Docker ports can bypass UFW; bind to 127.0.0.1 and let nginx handle HTTPS.

To self-host Open WebUI, run its Docker image on a VPS, bind it to localhost, put nginx with HTTPS in front on your own domain, create the admin account immediately, and connect it to the OpenAI API (or any OpenAI-compatible provider) or to local models through Ollama. You get a ChatGPT-style interface your whole team can share, chat history stored on your server, and API costs that follow actual use instead of a per-seat subscription.

This guide covers the manual install on Ubuntu 24.04 or Debian 12 (Docker, nginx, SSL and the safety settings people forget), the one-click route with ZoPanel, and the things worth knowing first: cost, data privacy, whether local models are realistic on a VPS, and Open WebUI's licence.

## What is Open WebUI, and why self-host it?

[Open WebUI](https://docs.openwebui.com/) is a web interface for language models: chat, history, multiple users with roles and groups, document uploads you can ask questions about, and a model picker per conversation. It is not a model; it is the front end that talks to models over an API.

Reasons to run your own:

- **One shared place for the team**, with individual accounts and admin approval for newcomers.
- **Pay for what you use.** You bring your own API key; light users do not cost a fixed monthly seat.
- **Any model.** Use OpenAI, other OpenAI-compatible providers or open models through Ollama side by side.
- **History and documents stay on your server**, not in each employee's SaaS account.

One honest caveat on privacy: with OpenAI or another API provider, the content of each prompt still goes to that provider under its data policy. Only local models keep data entirely on your server.

## What VPS do you need to self-host Open WebUI?

| Use | Suggested RAM | Notes |
| --- | --- | --- |
| Open WebUI + an API (OpenAI or compatible) | About 2 GB for Open WebUI, plus the system | No GPU needed; an ordinary VPS works |
| Open WebUI + a small CPU model via Ollama | Considerably more, depending on the model | Works, but slowly; fine for experiments |
| Large local models for a team | A GPU server | Far more expensive than a regular VPS |

For most individuals and small teams, the practical setup is Open WebUI on a 2-4 GB VPS talking to an API, with about 2 vCPUs and a few gigabytes of disk for chats and documents.

## How to self-host Open WebUI by hand

### Step 1: Point a domain and install Docker

Point an A record (for example `chat.example.com`) at the VPS. Then install Docker from Docker's own repository, following [Docker's install guide](https://docs.docker.com/engine/install/ubuntu/):

```bash
sudo apt update && sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

On Debian, replace `ubuntu` with `debian` in both URLs.

### Step 2: Run Open WebUI with Docker Compose

Create `/opt/open-webui/compose.yaml`:

```yaml
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:8080"
    volumes:
      - open-webui:/app/backend/data
    env_file: .env
volumes:
  open-webui:
```

Create a `.env` with a fixed secret key (without one, everyone is signed out whenever the container is recreated):

```bash
cd /opt/open-webui
echo "WEBUI_SECRET_KEY=$(openssl rand -hex 32)" | sudo tee .env >/dev/null
sudo chmod 600 .env
sudo docker compose up -d
sudo docker compose logs -f   # wait until the server has started
```

Note `127.0.0.1:3000:8080`. Open WebUI's quick start uses `-p 3000:8080`, which publishes on every address. As [Docker's documentation](https://docs.docker.com/engine/network/packet-filtering-firewalls/) explains, traffic to published ports is routed **before** UFW's rules see it, so port 3000 would be open to the internet even with UFW blocking it. Binding to `127.0.0.1` means only nginx on the same server can reach it.

To control upgrades, replace `:main` with a specific version tag.

### Step 3: nginx, HTTPS and streaming

```bash
sudo apt install -y nginx certbot python3-certbot-nginx
```

Create `/etc/nginx/sites-available/open-webui`:

```nginx
server {
    listen 80;
    server_name chat.example.com;

    client_max_body_size 50m;   # allow document uploads (nginx's default is 1 MB)

    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;        # stream answers token by token
        proxy_read_timeout 600s;    # long answers are not cut off at 60 seconds
    }
}
```

```bash
sudo ln -s /etc/nginx/sites-available/open-webui /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d chat.example.com
```

`proxy_buffering off` and WebSocket headers are the two settings most often missed: without them answers appear only when complete, or sending messages fails.

### Step 4: Create the admin account and connect a model

1. **Open the domain right after installing** and create the first account. The first account is the administrator; leave the page open to the world and a stranger may get there first.
2. In **Admin Panel → Settings → Connections**, add an OpenAI connection with `https://api.openai.com/v1` and your key, or the URL of another OpenAI-compatible provider.
3. According to Open WebUI's docs, sign-ups are closed once the admin exists; if you open them for your team, new accounts wait as pending until you approve them. Keep it that way. Use groups to decide who can use which models.
4. Set a **spending limit** on the API key in your provider's dashboard, so a loop or a single user cannot run up the bill.

### Step 5: Local models with Ollama?

You can add an Ollama container to the same compose file and point Open WebUI at it over the Compose network (`OLLAMA_BASE_URL=http://ollama:11434`). Never publish Ollama's port 11434 to the internet: its API has no authentication. On a VPS without a GPU, small models run, but slowly, and larger models need much more RAM than Open WebUI itself. Try a small model before buying a bigger server.

### Updates and backups

```bash
cd /opt/open-webui
sudo docker compose pull && sudo docker compose up -d
```

Every user, chat and setting lives in the `open-webui` volume. Back it up **before every update** and on a schedule, for example with restic as in [how to back up a VPS to S3](/blog/backup-vps-to-s3).

## Self-hosting Open WebUI with ZoPanel

In ZoPanel, Open WebUI is in the **App Store**:

1. Install Docker if it is not there yet: **App Store → Install Docker**.
2. Choose **Open WebUI**, enter the domain and click **Install**. ZoPanel creates a website for the domain, starts the container and proxies the domain to it; SSL is issued automatically once the domain points to the server. The app has a 2048 MB memory limit.
3. **New apps are locked to you until setup is finished**: visitors see "This app is being set up". On the app's **Docker** tab, press **Open the app (only for me)**, create your admin account, then **Setup finished — open to everyone**. Nobody can grab the first admin account.
4. Add your API key in Open WebUI's **Admin Panel → Settings → Connections**. You pay the model provider directly; ZoPanel never sees the key.

The container runs in a user namespace, listens on 127.0.0.1 only, has memory and CPU limits, and is cut off from the server's internal network. One consequence to know: it cannot reach loopback or private addresses, so Open WebUI from the App Store is meant for APIs reached over the internet (OpenAI or compatible providers), not an Ollama running on the same server. **Update to latest** on the **Docker** tab pulls the new image and keeps your data, which is stored in a folder only root and the container can read. See [App Store and S3 storage](/docs/apps) and [What each app does](/docs/app-catalog).

## Open WebUI's licence: what to know

Since v0.6.6 (April 2025), according to [Open WebUI's licence page](https://docs.openwebui.com/license/), the project uses a BSD-3-style licence with a branding clause: you may not alter, remove or obscure the "Open WebUI" branding unless your deployment has 50 or fewer users in a 30-day period, you have written permission, or you hold an enterprise licence. For ordinary internal use this changes nothing; if you plan to sell a rebranded chat service to many customers, read the terms carefully.

## Common mistakes

- **Publishing port 3000** and trusting UFW to block it. Bind to 127.0.0.1.
- **Leaving a fresh install open**, so a stranger creates the admin account first.
- **No fixed `WEBUI_SECRET_KEY`**, so everyone is signed out after each update.
- **Forgetting `client_max_body_size`**, so document uploads fail with 413.
- **No API spending limit.**
- **No volume backup** before upgrading.

## Conclusion

Self-hosting Open WebUI is one of the most worthwhile self-hosting projects: a cheap VPS, one shared AI chat for the team, your choice of models and the history on your own server. By hand it takes Docker, nginx, SSL and a few easy-to-miss safety settings; in ZoPanel it is an App Store install with a setup lock and container isolation built in. You can [start on the Free plan](/pricing) and run Open WebUI next to your websites on the same VPS.

## Frequently asked questions

### Is self-hosting Open WebUI free?

The software is free. You pay for the VPS and for API usage with your model provider. With local models through Ollama there is no API bill, but you need a much stronger server.

### Does Open WebUI work with Claude or DeepSeek?

Open WebUI connects to any OpenAI-compatible API, and many providers offer an OpenAI-compatible endpoint. Add the provider's URL and key under Admin Panel → Settings → Connections; check the provider's documentation for the exact URL.

### Are my chats completely private?

Chat history, accounts and documents are stored on your server. The content of each prompt is still sent to the API provider for processing, under its data policy. Only local models keep everything on your server.

### Can a VPS without a GPU run AI models?

It can run small models on the CPU through Ollama, slowly and with a lot of RAM, which is fine for experiments. For a team using it every day, an API or a GPU server gives a much better experience.

### How do I let several people use Open WebUI?

Create the admin account first, then enable sign-ups in the admin settings: new accounts wait as pending until you approve them. Groups let you grant permissions and control which models each group can use.
