# Update

Move to a new version with one command. Runs keep going and the address keeps answering.

## 1. Before you update

1. Back up the database and the files. If the update stops partway, it puts `.env` and the bundle’s files back as they were, but it never copies your data. See [Back up and restore](https://docs.gorunner.io/self-host/backups).
2. Read the new release’s page in the [Changelog](https://docs.gorunner.io/changelog): what changed for you, and anything to do before or after.
3. Check the License card. With no license in force, the installation pauses as soon as the update finishes. See [When a license ends](https://docs.gorunner.io/self-host/license-ends).

## 2. Run the update

In the install folder, run `deploy.sh` with the new version.

> **Warning** On v2026.10.56 or older, update to v2026.10.57 and let it finish before you go to v2026.10.58 or later. Straight across, the older containers can’t read the database until each one is replaced: the API answers `500`, and workers’ saves fail and are retried.

It fetches that version’s bundle from the registry the install used, runs its check, applies the database changes, then replaces the workers and the API one at a time.

The old bundle files go to `.previous/`. `.env` and your `docker-compose.override.yml` are never touched. Caddy reloads in place; for a new Caddy image or changed ports it is replaced, and refuses connections for about a second. The output says which.

You should see `Deployed v2026.10.30 (was v2026.10.29).`

If the check finds a problem, the update stops and changes nothing. The old version keeps running. [deploy.sh’s flags](https://docs.gorunner.io/self-host/settings#deploy-flags) go past it.

**What happens on Kubernetes?**

Back up the database first. Give `helm upgrade` the new version without its `v`.

- **The migrations Job**: Runs the new version’s check, then the migrations. If the check refuses, nothing is updated, and its log says why.
- **The app pods**: Start one at a time, and take requests once ready. Nobody sees an error.
- **The workers**: Start beside the old ones. An old worker takes no new runs, and finishes its own for up to 5½ minutes.

Check the version from inside a pod: `kubectl --namespace gorunner exec deploy/gorunner-api -- wget -qO- http://127.0.0.1:3001/api/health`. If the Job fails, the new pods keep waiting and the old ones keep serving: fix the cause and run `helm upgrade` again.

**Docker**

```bash
cd gorunner
./deploy.sh v2026.10.30
```

**Kubernetes**

```bash
helm upgrade gorunner oci://ghcr.io/ralve-org/charts/gorunner \
  --version 2026.10.30 --namespace gorunner -f values.yaml
```

```text
==> Fetching the install bundle for v2026.10.30 (ghcr.io/ralve-org/gorunner-selfhost:v2026.10.30)
==> Pulling ghcr.io/ralve-org/gorunner-selfhost:v2026.10.30
…
==> Checking everything v2026.10.30 depends on, with v2026.10.30’s own check
…
Everything GoRunner needs is in place (1.8 s).
==> Applying migrations
==> Starting the new worker generation alongside the old one
==> Replacing the old worker generation
==> Retiring the rollout workers
==> Rolling the API: the twin first, while api answers
==> Rolling the API: api, while the twin answers
==> Reloading Caddy's configuration (no gap)
==> The API reports v2026.10.30

Deployed v2026.10.30 (was v2026.10.29). .env now says GORUNNER_TAG=v2026.10.30.
```

## 3. On several servers, go in order

Update the main server first, then each worker server, with the same version. See [Several servers](https://docs.gorunner.io/self-host/several-servers).

```bash
# on the main server, then on each worker server
./deploy.sh v2026.10.30
```

## After the update

1. The last lines say `The API reports v2026.10.30` and `.env now says GORUNNER_TAG=v2026.10.30`.
2. `docker compose ps`: every line’s STATUS starts with `Up`, with `(healthy)` where shown.
3. Sign in, to check the dashboard answers.
4. In **Platform › Settings › General**, the License card still lists what it did, such as **Embedding**.

Your customers’ embeds keep working; an open one may offer a reload. New switches for customers [arrive off](https://docs.gorunner.io/embed/switches#new-switches-arrive-off).

**How do I check what I download?**

Each release’s notes name its image’s digest, `sha256:` and 64 characters. The `Digest:` line must match:

```bash
docker buildx imagetools inspect \
  ghcr.io/ralve-org/gorunner-selfhost:v2026.10.30
```

To install exactly that image, use the digest in place of the version:

```bash
docker run --rm \
  ghcr.io/ralve-org/gorunner-selfhost@sha256:<digest> \
  install | tar -x
```

A bundle sent as a file comes with `SHA256SUMS`: run `sha256sum -c SHA256SUMS` beside it. On Kubernetes, `image.digest` pins the image.

## Go back to the version before

Run `deploy.sh` with the older version. That works while the newer version hasn’t changed the database. Once it has, the older version’s check refuses: “the database was updated by a newer GoRunner than this one”.

```bash
./deploy.sh v2026.10.29
```

Go past that refusal with `--skip-check` only when the [release notes](https://docs.gorunner.io/changelog) of every version you go back over say that going back past their database changes is safe, and the check of the version you run now (`docker compose run --rm check`) reports no problem. Otherwise, the backup you took before the update is the way back. v2026.10.0 to v2026.10.2 have no such check: go back to them only with a backup.

**When is going back refused?**

`deploy.sh` refuses to go back to v2026.10.2 or older, and changes nothing, when the installation uses something those versions can’t run:

- your own database, Redis or file storage, or no file storage;
- several servers;
- no mail, or SMTP over TLS from the first byte (port 465, or `SMTP_SECURE=tls`);
- certificates in `certs/`;
- a company proxy.

Going back to v2026.10.0 or v2026.10.1 behind your own proxy is refused too. The way back is then a backup taken before the update.

> **Warning** Once an installation has run v2026.10.58, it can’t go back below v2026.10.57. v2026.10.58 removes database columns that older versions still read, so sign-in, organizations and workspaces fail on them and a run’s steps can’t be saved. An older version’s check may still offer `--skip-check`: don’t use it. The way back is the backup you took before the update.

> **Warning** Going back from v2026.10.22 or later to an earlier version needs the OAuth rollback guard run on the database first, or an AI app could open without a click. Ask GoRunner for it before you go back.

On Kubernetes, `helm rollback gorunner --namespace gorunner` is safe only while the newer version hasn’t changed the database; its Job’s log says whether it did. Nothing stops it after that: the older Job’s check fails, yet its pods still start on a database they don’t fully know. Use the backup instead.

**How do I apply a change to .env?**

Run the update with the version you already run. It checks the new settings, then restarts what changed the same way.

```bash
./deploy.sh "$(cat VERSION)"
```

## Related

- [Back up and restore](https://docs.gorunner.io/self-host/backups): The database, the files and the key · 10 min
- [The preflight check](https://docs.gorunner.io/self-host/preflight-check): Every line it prints, and its exit statuses
- [Troubleshooting](https://docs.gorunner.io/self-host/troubleshooting): An update that stops

Source: https://docs.gorunner.io/self-host/update
