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

# Upgrading

> Upgrade a self-hosted Entri instance with Docker Compose or Helm, how migrations run, and what to do if you need to roll back.

## Versions and release channels

Entri releases follow [semantic versioning](https://semver.org). Each release `vX.Y.Z` publishes:

| Artifact | Tags |
| - | - |
| Image `ghcr.io/nt3-io/entri` (amd64 and arm64) | `X.Y.Z`, `X.Y`, `X`, `latest` (stable releases only), `sha-<commit>` |
| Helm chart `oci://ghcr.io/nt3-io/charts/entri` | `X.Y.Z` (chart version equals app version) |

Pin an exact version (`1.2.3`) in production, or `1.2` to receive patch releases with each pull. Avoid `latest`, which can jump to a new major version.

Read the [CHANGELOG](https://github.com/nt3-io/platform/blob/main/CHANGELOG.md) and the [release notes](https://github.com/nt3-io/platform/releases) for every version between yours and the target before you upgrade. Breaking changes are listed there, and a new major version signals them.

## Before you upgrade

**1. Back up MongoDB**

Migrations change data in place. Take a backup right before the upgrade. See [Docker backups](https://docs.nt3.io/self-hosting/docker.md#backups) or [Kubernetes backups](https://docs.nt3.io/self-hosting/kubernetes.md#bundled-databases). For managed MongoDB, take a snapshot.

**2. Check your secrets are safe**

Make sure you have a copy of `ENCRYPTION_KEY` and `BETTER_AUTH_SECRET` outside the deployment.

**3. Note your current version**

You need it if you roll back:

```bash theme={null}
grep ENTRI_VERSION .env                                  # Docker Compose
helm -n entri list                                       # Helm (CHART and APP VERSION columns)
```

## Docker Compose

```bash theme={null}
cd deploy/docker
# 1. set ENTRI_VERSION in .env to the new version, e.g. ENTRI_VERSION=1.3.0
# 2. pull and restart
docker compose pull
docker compose up -d
# 3. check
docker compose logs migrate
docker compose ps
```

On `up`, the `migrate` service runs with the new image and applies pending migrations. `entri` starts only after `migrate` exits successfully. If a migration fails, `entri` is not started with the new image. Read `docker compose logs migrate`, fix the cause, and run `docker compose up -d` again.

If you pass profiles explicitly, pass them here too (`docker compose --profile tls up -d`), or set `COMPOSE_PROFILES` in `.env`.

When you upgrade from a newer copy of the repository, compare your `docker-compose.yml` and `.env` with the new `docker-compose.yml` and `.env.example`, and bring over new settings.

## Helm

```bash theme={null}
helm upgrade entri oci://ghcr.io/nt3-io/charts/entri \
  --version 1.3.0 -n entri -f values.yaml
```

The migration Job (`entri-migrate`) runs as a `pre-upgrade` hook, using the new image, before the Deployment changes. If it fails, the upgrade fails and the old pods keep serving traffic. The failed Job is kept so you can read its log:

```bash theme={null}
kubectl -n entri logs job/entri-migrate
```

Prefer `-f values.yaml` over `--reuse-values`. `--reuse-values` reuses the previous release's values and ignores defaults that the new chart version adds.

Generated secrets (`BETTER_AUTH_SECRET`, `ENCRYPTION_KEY`, bundled database passwords) are read back from the cluster and reused on every upgrade.

If you render plain manifests with `helm template`, run the migration Job yourself before you roll out the new Deployment. See [Plain manifests](https://docs.nt3.io/self-hosting/kubernetes.md#plain-manifests-helm-template).

## How migrations work

Migrations live in [`migrations/`](https://github.com/nt3-io/platform/tree/main/migrations) and run with [migrate-mongo](https://github.com/seppevs/migrate-mongo) through the image's `migrate` command. Applied migrations are recorded in the `changelog` collection, so each runs once. Running `migrate` when nothing is pending does nothing.

Separately, Entri creates any missing MongoDB indexes when it starts (unless `AUTO_INDEX=false`). On large collections the first start after an upgrade that adds indexes can take longer.

To see which migrations are applied, run migrate-mongo's `status` command with the image:

```bash theme={null}
# Docker Compose
docker compose run --rm migrate \
  node node_modules/migrate-mongo/bin/migrate-mongo.js status -f migrate-mongo-config.js
```

## Rolling back

> [!WARNING]
>
> Do not just switch back to the old image after migrations have run. The old version may not understand the migrated data.

**The reliable way to roll back is to restore the backup you took before the upgrade**, then run the previous version:

1. Stop Entri (`docker compose stop entri`, or `kubectl -n entri scale deploy/entri --replicas=0`).
2. Restore the MongoDB backup ([Docker](https://docs.nt3.io/self-hosting/docker.md#backups)).
3. Set the previous version (`ENTRI_VERSION` in `.env`, or `helm rollback entri <revision> -n entri`) and start Entri again.

Any changes made after the upgrade are lost with this approach.

**Reverting migrations** with `migrate-mongo down` is possible only for migrations that implement a `down` step, and it undoes one migration per run. Today the only migration (`20260212000000_convert-string-ids-to-objectid`) has one. Future migrations may not, and a reverted migration cannot always restore data exactly. Read the migration files for your versions before relying on it.

**Stop Entri first**, and keep it stopped until the old version runs: the newer version must not write to data that is being reverted, and it does not understand the reverted schema.

```bash theme={null}
docker compose stop entri        # Kubernetes: kubectl -n entri scale deploy/entri --replicas=0
docker compose run --rm migrate \
  node node_modules/migrate-mongo/bin/migrate-mongo.js down -f migrate-mongo-config.js
# then set the previous ENTRI_VERSION and start it: docker compose up -d
```

Run `down` with the **newer** image, which contains the migration files, before you switch back to the older one. Start Entri again only once it runs the old version. `helm rollback` does not revert migrations. It only rolls back Kubernetes resources, and the pre-upgrade hook does not run on rollback.

If the upgrade applied no migrations (`migrate` prints a `MIGRATED UP` line for each one it applies, so check `docker compose logs migrate` or the Job log), switching back to the previous image is usually safe. Still read the release notes first.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.