# Upgrading

> Update an installation to a new release, and what to change when you move from 2.1.0 to 2.2.0.

An update replaces the PentAGI images and, when the release changed them, the compose files. Your `.env` and the data volumes stay, and database migrations run when PentAGI starts.

## [Before you start](https://pentagi.com/docs/deployment/upgrade/#before-you-start)

* Read the [release notes](https://pentagi.com/changelog/) of every version after the one you run; since 2.1.0 they include upgrade notes.
* Back up the database. Neither the installer nor PentAGI does it, and migrations cannot be rolled back without losing data. With the default `PENTAGI_POSTGRES_USER` and `PENTAGI_POSTGRES_DB`:

  ```bash
  docker exec pgvector pg_dump -U postgres -Fc pentagidb > pentagi-backup.dump
  ```

  Keep copies of `.env` and the compose files as well: the installer replaces compose files without a backup.
* Finish the [flows](https://pentagi.com/docs/glossary/#flow) you no longer need. A [sandbox](https://pentagi.com/docs/glossary/#sandbox) that is still running is reused as it was created, with the settings of the release that created it.
* Coming from 2.1.0, make the changes in [From 2.1.0 to 2.2.0](#from-210-to-220) to `.env` and the files next to it before the new release starts. With Google or GitHub sign-in on, empty `OAUTH_GOOGLE_CLIENT_ID` and `OAUTH_GITHUB_CLIENT_ID` now; the section explains why.

## [Docker Compose](https://pentagi.com/docs/deployment/upgrade/#docker-compose)

1. Download the compose files of the new release next to your `.env`: `docker-compose.yml` and the file of each optional stack you run. The PentAGI container receives only the variables its compose file lists, so new settings in `.env` have no effect behind an older file.

   ```bash
   cd ~/pentagi
   curl -O https://raw.githubusercontent.com/vxcontrol/pentagi/main/docker-compose.yml
   # and the file of each optional stack you run, for example:
   curl -O https://raw.githubusercontent.com/vxcontrol/pentagi/main/docker-compose-langfuse.yml
   ```

2. Pull the images and restart, with the same `-f` files you start the stack with. Without `pull`, `up -d` keeps the images already on the host.

   ```bash
   docker compose pull && docker compose up -d
   ```

3. Refresh the sandbox image on the Docker host that runs the flows, which `docker compose pull` does not do. Flows created afterwards use it.

   ```bash
   docker pull vxcontrol/kali-linux
   ```

The `latest` image tag follows the main branch. To stay on one release, set `PENTAGI_IMAGE=vxcontrol/pentagi:<version>` in `.env`.

## [Installer](https://pentagi.com/docs/deployment/upgrade/#installer)

1. Download the installer of the new release from [Quick start](https://pentagi.com/docs/getting-started/quickstart/) and run it with your `.env`. The 2.1.0 installer cannot update itself.
2. To replace the compose files, change a setting so that **Apply Changes** appears in the menu, choose it and answer `y` when the installer lists the out-of-date files.
3. In the maintenance menu, run **Update PentAGI** to pull the new images, and **Update Worker Image** when it is offered. **Update PentAGI** on its own keeps the old compose files.

## [From 2.1.0 to 2.2.0](https://pentagi.com/docs/deployment/upgrade/#from-210-to-220)

### [Files](https://pentagi.com/docs/deployment/upgrade/#files)

* The compose file mounts `example.bedrock.provider.yml` next to it. The installer creates it; on a manual install create it yourself, an empty file is enough: `touch example.bedrock.provider.yml`.
* Replace `docker-compose-langfuse.yml` if you run Langfuse: the 2.1.0 file names the `minio/minio` image, which is no longer published, so `docker compose pull` fails with it. If your `.env` sets `MINIO_IMAGE=minio/minio:…`, remove that line.
* For the [knowledge graph](https://pentagi.com/docs/glossary/#knowledge-graph), put `examples/neo4j` from the repository at `./neo4j` — Graphiti needs its APOC plugin — and see [Memory and knowledge](https://pentagi.com/docs/concepts/memory/#knowledge-graph-optional) for the model presets. `GRAPHITI_MODEL_NAME` is no longer read.
* Eight database migrations run at the first start. `docker compose logs pentagi` shows "Database schema updated successfully" when they are done.

### [Sign-in and access](https://pentagi.com/docs/deployment/upgrade/#sign-in-and-access)

* Everyone signs in again: sessions from 2.1.0 are refused. API tokens keep working, and scripts log out with `POST /api/v1/auth/logout`.
* An API token gets 403 on the REST `/users`, `/roles` and `/tokens` routes: manage accounts, roles and tokens from a signed-in browser session.
* Google and GitHub sign-in now signs a provider-verified email into the existing account with that address, local accounts included, with that account's role. 2.1.0 cannot change an account's email, so if sign-in is on, upgrade with `OAUTH_GOOGLE_CLIENT_ID` and `OAUTH_GITHUB_CLIENT_ID` empty, move `admin@pentagi.com` to an address you control under **Settings → Account**, then turn sign-in back on. The installer's **Reset Admin Password** finds the administrator only by `admin@pentagi.com`.
* Behind a reverse proxy, set `TRUSTED_PROXIES`, or every user shares the proxy's address and one burst of failed sign-ins locks everyone out for 15 minutes — see [Network exposure](https://pentagi.com/docs/configuration/security/#network-exposure).

### [Sandboxes](https://pentagi.com/docs/deployment/upgrade/#sandboxes)

* With `DOCKER_INSIDE=true` — the 2.1.0 `.env` template and installer default — 2.1.0 mounted the host Docker socket into every sandbox. 2.2.0 gives [agents](https://pentagi.com/docs/glossary/#agent) Docker only from a separate daemon set in `DOCKER_INSIDE_HOST`; without it they get none, and the log says `sandbox DISABLED`. With `DOCKER_INSIDE_HOST`, set `DOCKER_SOCKET=` empty, or the template's `/var/run/docker.sock` is still mounted. See [Worker node](https://pentagi.com/docs/deployment/worker-node/).
* Finish the flows started on 2.1.0: their sandboxes keep the old socket mount and capabilities until the flow is finished.
* Leave `TENANT_ID` empty: on an existing installation it points PentAGI at a new, empty schema.

### [Models and prompts](https://pentagi.com/docs/deployment/upgrade/#models-and-prompts)

* The custom [provider](https://pentagi.com/docs/glossary/#provider) needs `LLM_SERVER_KEY`: with an empty key it is disabled, so for a server without authentication set any non-empty value.
* `LLM_SERVER_LEGACY_REASONING` is removed. The custom provider sends `reasoning_effort` and turns a `reasoning.max_tokens` budget into an effort level; on Kimi K2, GLM before 5.2 and MiniMax M models a budget now fails the call, so remove it from those agents.
* In provider config files, an agent entry that leaves `max_tokens`, `temperature`, `top_p` or `n` blank now gets the provider type's defaults instead of sending nothing.
* Built-in default models changed for every provider except Bedrock; providers saved in **Settings → Providers** keep their models. Five configs bundled in the image changed models — `openrouter`, `deepinfra`, `ollama-cloud`, `moonshot` and `deepseek`. If `LLM_SERVER_CONFIG_PATH` or `OLLAMA_SERVER_CONFIG_PATH` points at one of them under `/opt/pentagi/conf/`, keep the 2.1.0 file on the host and mount it as the custom or Ollama config instead.
* With `EMBEDDING_URL` on a server other than OpenAI's, set `EMBEDDING_KEY`: `OPEN_AI_KEY` is no longer sent there.
* Agents search through one `web_search` [tool](https://pentagi.com/docs/glossary/#tool). Custom prompts with `{{.GoogleToolName}}` and the other per-engine variables are ignored, with a warning in the log, until they use `{{.WebSearchToolName}}`; rebase custom searcher and pentester prompts on the new defaults.

### [Other changes](https://pentagi.com/docs/deployment/upgrade/#other-changes)

* Within two minutes of starting and then every three hours, PentAGI reports its version and a summary of the installation to `update.pentagi.com`; [Update check](https://pentagi.com/docs/configuration/security/#update-check) lists what it sends, and `UPDATE_CHECK_INTERVAL=0` turns it off.
* The profiler no longer listens on port 7777 unless `PPROF_ADDR` is set.
* New optional settings include [provider failover](https://pentagi.com/docs/configuration/llm-providers/#failover) with `LLM_FALLBACK_PROVIDER`, `DOCKER_PORTS_BASE` for [several instances](https://pentagi.com/docs/deployment/production/#several-instances-tenant_id), `DOCKER_IMAGE_SELECTION_MODE` and `DOCKER_ALLOWED_IMAGES`, the internal [search engine](https://pentagi.com/docs/glossary/#search-engine) `WEB_SEARCH_INTERNAL_ENABLED`, and the Mistral, xAI, MiniMax and Firecrawl keys.

## [Back up and roll back](https://pentagi.com/docs/deployment/upgrade/#back-up-and-roll-back)

PentAGI never runs migrations backwards, and running them by hand deletes data, so the way back to 2.1.0 is the backup. Stop the services that use the database, recreate it and restore the dump:

```bash
docker compose stop pentagi pgexporter
docker exec pgvector dropdb -U postgres pentagidb
docker exec pgvector createdb -U postgres pentagidb
docker exec -i pgvector pg_restore -U postgres -d pentagidb < pentagi-backup.dump
```

Then put back the saved `.env` and compose files, set `PENTAGI_IMAGE=vxcontrol/pentagi:2.1.0` and start the stack. Keep the new `docker-compose-langfuse.yml`: the MinIO image of the 2.1.0 file can no longer be pulled.