---
title: Installation
description: Install Hubzoid with pip, from source or as a Docker image, add PostgreSQL support, and confirm the install with the doctor command.
canonical_url: https://hubzoid.com/docs/getting-started/installation
last_updated: 2026-09-27
---

# Installation

Install Hubzoid with pip, from source or as a Docker image, add PostgreSQL support, and confirm the install with the doctor command.

One package contains everything `hubzoid run` needs: the bridge, the three agent runtimes (OpenAI Agents SDK, Claude Agent SDK and local Codex), LiteLLM model routing, the bundled Open WebUI chat app, the channel adapters, the durable workflow engine (DBOS), the hosted MCP server and the Console. There are no optional extras for the runtime itself.

## Requirements

| Requirement | Detail |
| --- | --- |
| Python | 3.11 or 3.12. Newer versions do not work because the bundled Open WebUI requires Python 3.12 or older. |
| Operating system | macOS or Linux for a native install. Any host that runs Docker for the image. |
| Memory | 2 GB RAM for one Hub on a server, 4 GB for two or three Hubs on the same machine. |
| SQLite | On Python 3.12, the workflow engine needs SQLite 3.42 or newer. See [platform notes](https://hubzoid.com/docs/getting-started/installation#platform-notes). |
| Model access | The `claude` CLI logged in to a Claude subscription, the Codex CLI 0.147.0 logged in to a Codex account, or an API key for OpenAI, Anthropic, Azure OpenAI or OpenRouter. The CLIs are installed separately. See the [quickstart](https://hubzoid.com/docs/getting-started/quickstart#choose-a-model) and [agents and models](https://hubzoid.com/docs/concepts/agents-and-models#runtimes). |

## Install

### pip

Create a virtual environment with Python 3.11 or 3.12 and install the package from PyPI.

```bash
python3.12 -m venv .venv
source .venv/bin/activate
pip install hubzoid
hubzoid version
```

`hubzoid version` prints the installed version. `python -m hubzoid` works anywhere the `hubzoid` command does.

To store Hubzoid's data in PostgreSQL instead of SQLite, install the `postgres` extra. It adds the psycopg 3 driver.

```bash
pip install "hubzoid[postgres]"
```

Then point the Hub (or the gateway and every bridge) at the database with the `postgresql+psycopg://` form of the URL:

```bash title=".env"
DATABASE_URL=postgresql+psycopg://hubzoid:<password>@db.internal:5432/hubzoid
```

With `DATABASE_URL` set, Hubzoid's own `hz_*` tables, the workflow engine's `dbos` schema and Open WebUI's tables share that database, and each owner upgrades its tables at start. [Deployment topologies](https://hubzoid.com/docs/deploy/topologies) explains when to choose PostgreSQL.

### From source

Install from a clone when you want to read or change the source. The repository includes a ready Hub in `demo-hub/`.

```bash
git clone https://github.com/hubzoid/hubzoid.git
cd hubzoid
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
hubzoid run demo-hub
```

`pip install -e .` installs without the test tools. The `dev` extra adds pytest and the packaging tools used by contributors. `demo-hub/AGENTS.md` sets `model: claude-local`. To use a provider key instead, create `demo-hub/.env` with `MODEL` and the matching key, because `.env` wins over the frontmatter.

### Docker

Build the image from a clone of the repository. The `Dockerfile` installs the checked-out source with the reviewed dependency set in `requirements.lock`, so the image version is the version you checked out. Each release is also published to the GitHub Container Registry for amd64 and arm64, as described in [Docker deployment](https://hubzoid.com/docs/deploy/docker#published-images).

```bash
git clone https://github.com/hubzoid/hubzoid.git
cd hubzoid
docker build -t hubzoid .
```

Run it with your Hub folder mounted at `/hub`:

```bash
docker run -d --restart unless-stopped \
  -p 3080:3080 \
  -v "/path/to/my-hub:/hub" \
  --env-file "/path/to/my-hub/.env" \
  hubzoid
```

The image runs `hubzoid run /hub` as an unprivileged `hubzoid` user on Python 3.12 (Debian 13, SQLite 3.46). Pass other arguments after the image name, for example `run /hub --slack` to add the Slack surface. State stays in the mounted Hub folder (`.hubzoid/` and `.openwebui-data/`), so it survives container restarts and `hubzoid backup` covers it.

Publish only port 3080. The edge on that port serves the chat app, file downloads, the Console and MCP, while the bridge listens on 127.0.0.1 inside the container.

`MODEL=claude-local` and `MODEL=codex-local` do not work inside the image because it has no `claude` or Codex CLI. Set `MODEL` and a provider key in the Hub's `.env`.

**Docker Compose.** `docker/docker-compose.yml` runs one Hub with SQLite. `docker/docker-compose.postgres.yml` adds a PostgreSQL 17 container whose port is not published.

```bash
# SQLite: state lives in the mounted Hub folder
HUB_PATH=/path/to/my-hub docker compose -f docker/docker-compose.yml up -d

# PostgreSQL: add the override file
HUB_PATH=/path/to/my-hub POSTGRES_PASSWORD=<letters and digits> \
  docker compose -f docker/docker-compose.yml -f docker/docker-compose.postgres.yml up -d
```

| Variable | Default | Purpose |
| --- | --- | --- |
| `HUB_PATH` | `../demo-hub` | Hub folder mounted at `/hub`. |
| `HUBZOID_IMAGE` | `hubzoid:local` | Image to run. Compose builds it from the checkout. |
| `HUBZOID_PUBLISH` | `3080` | Host port published for the edge. |
| `POSTGRES_PASSWORD` | none | Required by the PostgreSQL override. |

Run operator commands inside the container:

```bash
docker compose -f docker/docker-compose.yml exec hubzoid hubzoid doctor /hub
```

On Linux the container user must be able to write the mounted folder, for example `chown -R 999:999 my-hub`, or run with `--user "$(id -u):$(id -g)"`. See [Docker deployment](https://hubzoid.com/docs/deploy/docker) for production settings.

> **Warning: The image listens on all interfaces**
>
> The image sets `HUBZOID_HOST=0.0.0.0`, so the published port accepts connections from other machines. Turn on sign-in before anyone else can reach it. [Authentication](https://hubzoid.com/docs/deploy/authentication) covers the settings.

## Platform notes

**macOS.** The default `python3` on recent macOS is newer than 3.12. Create the virtual environment with `python3.12 -m venv` explicitly. If pip starts building `av` (PyAV) from source, install its build dependencies first:

```bash
brew install pkg-config ffmpeg
```

**Ubuntu and Debian.** Install Python 3.12 and the PyAV build dependencies:

```bash
sudo apt update && sudo apt install -y \
  python3.12 python3.12-venv pkg-config ffmpeg build-essential git curl
```

**SQLite for scheduled work.** On Python 3.12 the workflow engine needs SQLite 3.42 or newer. Python builds that link an older system SQLite (Debian 12, Ubuntu 22.04) cannot run scheduled tasks or workflows, and the bridge logs that the workflow engine did not start. Use a Python build with a newer SQLite (python.org, Homebrew, Debian 13, Ubuntu 24.04) or PostgreSQL. Chat is not affected. `hubzoid doctor` reports this as the `deps.sqlite` check.

## Verify the install

`hubzoid doctor` checks a Hub and its deployment without changing anything. Run it against any Hub folder, for example the one `hubzoid init` creates in the [quickstart](https://hubzoid.com/docs/getting-started/quickstart):

```bash
hubzoid init my-hub
hubzoid doctor my-hub
```

Each line shows a status mark, a summary and a stable check id. The command exits with code 1 when any check fails, so it also works in scripts and CI. `--json` prints the same checks as JSON.

| Check id | What it confirms |
| --- | --- |
| `hub.agents_md` | `AGENTS.md` exists at the Hub root. |
| `runtime.build` | The agent builds with its tools, skills, knowledge and connectors. |
| `deps.versions` | Installed versions of Hubzoid, Open WebUI, DBOS, LiteLLM and the agent SDKs. |
| `deps.sqlite` | The SQLite build can run the workflow engine. |
| `auth.bridge_keys` | `BRIDGE_API_KEYS` is set and is not the public default `dev`. |
| `auth.chat_signin` | Whether chat sign-in is on. Off is reported as information on a local-only Hub and as a failure when the port is exposed. |
| `model.credentials` | The configured model has credentials: a provider key, `CLAUDE_CODE_OAUTH_TOKEN`, or a `claude` login. |

`hubzoid init` writes a random bridge key into `.env`, so `auth.bridge_keys` passes on a new Hub. The [doctor reference](https://hubzoid.com/docs/reference/doctor) lists every check.

## Next steps

- [Quickstart](https://hubzoid.com/docs/getting-started/quickstart): Create a Hub, choose a model and start chatting.
- [Project structure](https://hubzoid.com/docs/getting-started/project-structure): Every file and folder in a Hub.
- [Deployment topologies](https://hubzoid.com/docs/deploy/topologies): One Hub or many, SQLite or PostgreSQL.
