# Manual installation

> Deploy PentAGI by hand with Docker Compose — create the working directory, fill in the .env file, add an LLM provider and start the stack.

Use the manual path when you want full control over the configuration or cannot run the interactive installer.

## [1. Create a working directory](https://pentagi.com/docs/getting-started/manual-installation/#1-create-a-working-directory)

```bash
mkdir -p ~/pentagi && cd ~/pentagi
```

## [2. Download the environment file](https://pentagi.com/docs/getting-started/manual-installation/#2-download-the-environment-file)

```bash
test -f .env || curl -fo .env.new https://raw.githubusercontent.com/vxcontrol/pentagi/main/.env.example
test -f .env.new && openssl rand -hex 32 | xargs -I VALUE sed -E -i.bak 's/^COOKIE_SIGNING_SALT=salt( .*)?$/COOKIE_SIGNING_SALT=VALUE/' .env.new
test -f .env.new && openssl rand -hex 16 | xargs -I VALUE sed -E -i.bak 's/^PENTAGI_POSTGRES_PASSWORD=postgres( .*)?$/PENTAGI_POSTGRES_PASSWORD=VALUE/' .env.new
test -f .env || mv .env.new .env
```

The compose file mounts three [provider](https://pentagi.com/docs/glossary/#provider) config files, so create them — empty files are fine:

```bash
touch example.custom.provider.yml example.ollama.provider.yml example.bedrock.provider.yml
```

If you plan to use a custom OpenAI-compatible endpoint or Ollama, fetch the example configs instead of the empty files and point `LLM_SERVER_CONFIG_PATH` or `OLLAMA_SERVER_CONFIG_PATH` in `.env` at `/opt/pentagi/conf/custom.provider.yml` or `/opt/pentagi/conf/ollama.provider.yml`. The custom example names OpenAI models, among them `o3-mini`, which OpenAI retires on 23 October 2026 — set each [agent](https://pentagi.com/docs/glossary/#agent)'s `model` to one your endpoint serves:

```bash
curl -o example.custom.provider.yml https://raw.githubusercontent.com/vxcontrol/pentagi/main/examples/configs/custom-openai.provider.yml
curl -o example.ollama.provider.yml https://raw.githubusercontent.com/vxcontrol/pentagi/main/examples/configs/ollama-llama318b.provider.yml
```

## [3. Add at least one LLM provider](https://pentagi.com/docs/getting-started/manual-installation/#3-add-at-least-one-llm-provider)

Edit `.env` and set the key of at least one provider:

```bash
OPEN_AI_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key
GEMINI_API_KEY=your_gemini_key
```

Other providers — AWS Bedrock, Ollama, DeepSeek, GLM, Kimi, Qwen, MiniMax, Mistral, xAI and custom endpoints — are described in [LLM providers](https://pentagi.com/docs/configuration/llm-providers/). [Search engines](https://pentagi.com/docs/glossary/#search-engine) are optional; DuckDuckGo and Sploitus need no key:

```bash
DUCKDUCKGO_ENABLED=true
SPLOITUS_ENABLED=true
TAVILY_API_KEY=your_tavily_key
```

## [4. Start the stack](https://pentagi.com/docs/getting-started/manual-installation/#4-start-the-stack)

```bash
curl -O https://raw.githubusercontent.com/vxcontrol/pentagi/main/docker-compose.yml
test -f .env && docker compose up -d
```

The web UI is served at `https://localhost:8443`. Sign in with `admin@pentagi.com` / `admin` and change the password.

The web UI and the other services are bound to localhost, but each [flow](https://pentagi.com/docs/glossary/#flow)'s [sandbox](https://pentagi.com/docs/glossary/#sandbox) publishes two callback ports, from `28000`–`29999` by default, on every interface of the Docker host, and ufw does not filter them. On a host others can reach, restrict that range first — see [Network exposure](https://pentagi.com/docs/configuration/security/#network-exposure). To update the installation later, follow [Upgrading](https://pentagi.com/docs/deployment/upgrade/).

## [Optional stacks](https://pentagi.com/docs/getting-started/manual-installation/#optional-stacks)

Each optional service ships as its own compose file that you layer on top of the base one:

| Stack                                              | Compose file                                                                                       | What it adds                                          |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| LLM observability                                  | [`docker-compose-langfuse.yml`](https://pentagi.com/docs/configuration/observability/#langfuse)                       | Langfuse with ClickHouse, Redis and MinIO             |
| [Knowledge graph](https://pentagi.com/docs/glossary/#knowledge-graph) | [`docker-compose-graphiti.yml`](https://pentagi.com/docs/concepts/memory/#knowledge-graph-optional)                   | Graphiti and Neo4j                                    |
| System observability                               | [`docker-compose-observability.yml`](https://pentagi.com/docs/configuration/observability/#grafana-and-opentelemetry) | Grafana, OpenTelemetry, VictoriaMetrics, Jaeger, Loki |

> [!WARNING]
> For production and any environment where untrusted code runs, isolate the [tool](https://pentagi.com/docs/glossary/#tool) containers on a dedicated [worker node](https://pentagi.com/docs/deployment/worker-node/).