> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dograh.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update

> Update your self-hosted Dograh stack to a newer image version

This guide covers updating a Dograh stack you've already deployed with [Docker](/deployment/docker) or a [custom domain](/deployment/custom-domain). You run commands from the same directory that contains your `docker-compose.yaml` (this is the `dograh/` directory if you used `setup_remote.sh`).

There are three update flows depending on how you deployed:

* **Remote, prebuilt mode** (most users) — use [`update_remote.sh`](#remote-prebuilt-mode-recommended) below.
* **Local Docker** — pull images and restart; see [Local deployment](#local-deployment).
* **Remote, build mode** (you have a `docker-compose.override.yaml`) — update via git; see [Updating a source build](#updating-a-source-build).

## Find an image version

Dograh publishes two images — `dograh-api` and `dograh-ui` — to both container registries:

* **GitHub Container Registry** — [github.com/orgs/dograh-hq/packages](https://github.com/orgs/dograh-hq/packages)
* **Docker Hub** — [hub.docker.com/u/dograhai](https://hub.docker.com/u/dograhai)

Each release is published under release tags. Note the formats differ between GitHub releases and Docker image tags — `update_remote.sh` understands both and normalizes for you.

| Where                       | Tag format      | Example          | When to use                                        |
| --------------------------- | --------------- | ---------------- | -------------------------------------------------- |
| GitHub release tag          | `dograh-vX.Y.Z` | `dograh-v1.28.0` | Use when copying the version from a GitHub release |
| Docker image tag (semver)   | `X.Y.Z`         | `1.28.0`         | Stable, recommended for production                 |
| Docker image tag (`latest`) | `latest`        | `latest`         | Tracks the most recent release tag                 |

<Warning>
  Always update **`dograh-api`** and **`dograh-ui`** to the **same tag**. The two images are built from the same commit and the UI expects API responses in a matching shape — mixing versions will break the app. `update_remote.sh` handles this for you automatically.
</Warning>

## Remote, prebuilt mode (recommended)

`update_remote.sh` is the supported path for updating a stack created with `setup_remote.sh`. In one shot it:

* Asks for a target version (defaults to the latest release tag on GitHub).
* Pulls `docker-compose.yaml` at that version and pins both `api` and `ui` images to it.
* Refreshes the remote helper bundle (`remote_up.sh` plus shared templates/helpers).
* Synchronizes the canonical remote keys in `.env` and validates the runtime config that `dograh-init` will render from it.
* Backs up every file it changes with a `.bak.<timestamp>` suffix.

From your install directory:

```bash theme={null}
cd dograh
curl -o update_remote.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/update_remote.sh
bash update_remote.sh
```

You'll be prompted for the target version, defaulting to the most recent release. Accepted forms: bare semver (`1.28.0`), v-prefixed (`v1.28.0`), the full GitHub tag (`dograh-v1.28.0`), or `main` to refresh deployment files from the default branch — the script normalizes them. Non-interactive callers can set it via environment variable and skip the confirmation prompt:

```bash theme={null}
TARGET_VERSION=1.28.0 DOGRAH_UPDATE_YES=1 bash update_remote.sh
```

After the script finishes, apply the update through the validated startup wrapper:

```bash theme={null}
./remote_up.sh
```

<Note>
  The script overwrites `docker-compose.yaml` and the remote helper bundle (`remote_up.sh`, `scripts/run_dograh_init.sh`, `scripts/lib/setup_common.sh`, and `deploy/templates/*`) from the shared upstream deployment bundle. If you've made local edits to any of these, check the `.bak.<timestamp>` files after the update and re-apply your edits.
</Note>

## Local deployment

For local Docker installs (the [Quick Start](/deployment/docker#quick-start) flow or `setup_local.sh` / `setup_local.ps1`), refresh `docker-compose.yaml` and the startup script, stop the stack, then run the startup script. The script preserves existing `.env` secrets, creates `REDIS_PASSWORD` and MinIO credentials if they are missing, and only creates `POSTGRES_PASSWORD` for brand-new `.env` files. If a retained local Postgres volume already exists, it syncs the database user's password to `.env` before starting the full stack:

<CodeGroup>
  ```bash macOS/Linux theme={null}
  curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml
  curl -o start_docker.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.sh && chmod +x start_docker.sh
  docker compose down
  ./start_docker.sh
  ```

  ```powershell Windows theme={null}
  Invoke-WebRequest -OutFile docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml; Invoke-WebRequest -OutFile start_docker.ps1 https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.ps1; docker compose down; .\start_docker.ps1
  ```
</CodeGroup>

To pin a specific version instead of `latest`, edit `docker-compose.yaml` and change both `image:` lines for `api` and `ui` to the same tag (e.g. `:1.28.0` — Docker image tags use bare semver, no `v` prefix), then run the commands above.

## Verify the update

Check the running image tags:

```bash theme={null}
docker compose ps --format "table {{.Service}}\t{{.Image}}"
```

You should see the API and UI both running the tag you pinned.

Hit the health endpoint to confirm the API is responding:

```bash theme={null}
curl -k https://YOUR_SERVER_IP/api/v1/health      # remote
curl http://localhost:8000/api/v1/health           # local
```

## Roll back

`update_remote.sh` saves backups of every file it touched. To roll back, restore them and recreate the stack — the exact commands (including the timestamp it used) are printed at the end of the script's output. The generic form:

```bash theme={null}
cd dograh
for f in docker-compose.yaml nginx.conf turnserver.conf .env remote_up.sh scripts/run_dograh_init.sh scripts/lib/setup_common.sh deploy/templates/nginx.remote.conf.template deploy/templates/turnserver.remote.conf.template; do
    [[ -f "$f.bak.<timestamp>" ]] && cp "$f.bak.<timestamp>" "$f"
done
./remote_up.sh
```

Your Postgres data volume persists across `down`/`up` cycles, so agents and call history are preserved.

<Warning>
  Rolling back across a database migration is not always safe — if the newer release ran a schema migration, downgrading may leave the DB in a state the older API doesn't understand. If in doubt, [open an issue](https://github.com/dograh-hq/dograh/issues) before rolling back.
</Warning>

## Updating a source build

If you deployed in **build mode** (you'll have a `docker-compose.override.yaml` in your install directory), `update_remote.sh` deliberately refuses to run — you already have the full repo locally and update via git:

```bash theme={null}
cd dograh
git fetch

# Track latest main:
git pull
# Or pin to a specific release (git tag format is dograh-vX.Y.Z):
git checkout dograh-v1.28.0

# Pick up pipecat and other submodule bumps
git submodule update --init --recursive

# Rebuild and restart
sudo docker compose --profile remote build
sudo docker compose --profile remote up -d
```

<Warning>
  If you update the `pipecat` submodule, you **must** run `git submodule update --init --recursive` before rebuilding, or the Docker build will not pick up `pipecat` changes.
</Warning>

If you maintain a fork with local customizations on top of upstream, merging conflicts in `docker-compose.yaml`, `remote_up.sh`, `scripts/run_dograh_init.sh`, `deploy/templates/*`, or `setup_remote.sh` is up to you — resolve them as you would any other git merge. Leave `OSS_JWT_SECRET`, `TURN_SECRET`, `POSTGRES_PASSWORD`, `REDIS_PASSWORD`, `MINIO_ROOT_USER`, and `MINIO_ROOT_PASSWORD` in `.env` unchanged across updates to preserve sessions, WebRTC auth, and service credentials.

The same migration warning above applies: rolling back across a schema change can leave the DB in a state the older API can't read.
