# Update, back up, fix

**Time:** 5 minutes for an update or a backup.

This guide keeps your runner healthy: how to update it, undo an update, back it up, and read what it says when something is wrong. Run every command in the `loopgate` folder (`cd ~/loopgate`). New words are explained in [The words we use](words.md).

## Update

Each release of Loopgate is a new `compose.yaml`. An update downloads only what changed, about 14 MB.

1. Keep a copy of the current file, so you can go back, then download the new one and restart. Your settings are kept.

   ```sh
   cp compose.yaml compose.previous.yaml
   curl -fsSLO https://loopgate.dev/runner/compose.yaml
   docker compose pull && docker compose up -d
   ```

   You should see: each container `Started` or `Running`, and `Runner ready at …` in `docker compose logs runner`.

Browsers stay signed in across a restart, but a temporary address changes, so on one each person opens the runner from the portal again. A step that was working when the runner restarted shows as interrupted, with **Retry**.

## Undo an update

2. Put the previous file back and restart.

   ```sh
   cp compose.previous.yaml compose.yaml
   docker compose up -d
   ```

## Back up

A backup copies everything the runner keeps: its runs and settings, your code on the box, and the coding tools' sign-ins. It holds those sign-ins, so store it like a password.

3. Stop the runner, copy everything into one file, and start it again.

   ```sh
   docker compose stop
   docker run --rm -v loopgate-runner_data:/data -v loopgate-runner_repos:/repos -v loopgate-runner_home:/home/node -v "$PWD":/backup debian:bookworm-slim tar czf /backup/loopgate-runner.tgz /data /repos /home/node
   docker compose start
   ```

   You should see: a file `loopgate-runner.tgz` in the folder. Copy it off the box to somewhere safe.

## Stop a task or the whole runner

- Stop one task: **Stop** on the task in the workbench or in its Slack thread, or `docker compose exec runner loopgate cancel <run>` (the run's id is in its workbench address).
- Shut the door for everyone: revoke the runner in the portal's **Devices** page, or run `docker compose exec runner loopgate logout`. Within a minute nobody can open it. Tasks already working carry on until they need a person or end, within their limits.

## What the runner says

Read the runner's messages with `docker compose logs runner`, and the Slack app's with `docker compose logs slack`.

| It says                                                                          | What it means and what to do                                                                                               |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `Runner ready at https://…`                                                      | All is well. `(temporary address)` after it is the quick tunnel's, which changes at a restart.                             |
| `This runner is signed out. Run loopgate login on its host.`                     | Paste a fresh line from the portal's Devices → Add a runner, or run `docker compose exec runner loopgate login --no-open`. |
| `The install token was refused: …`                                               | The rest of the line says why. Paste a fresh line from the portal's Devices → Add a runner.                                |
| `The runner is fetching its org policy.`                                         | It is starting. Wait a minute.                                                                                             |
| `This runner belongs to another org. Give it a fresh data directory.`            | The box was signed in to a different Loopgate org before. Ask us for help.                                                 |
| `This data directory has runs from before it was a runner. Give it a fresh one.` | The box's data predates the runner. Ask us for help.                                                                       |
| `Loopgate Slack worker is connected for T…`                                      | The Slack app is working. Settings → Slack says the same, or the worker's error in one sentence.                           |
| `No Loopgate daemon answers in /data: …`                                         | The runner is not up. Check `docker compose ps` and the runner's messages.                                                 |

## What people see

**"This link expired. Open the runner from the portal again."** The portal's pass lasts one minute and works once. Open the portal, go to **Devices** and press **Open** again.

**"Not a current member of this org."** The person is not a member of your Loopgate org, or was removed. An owner or admin adds them in the portal. A new member can get in within about two minutes.

**"Ask an owner or admin of your org to … on this runner."** Signing in engines, saving GitHub or Slack and adding workspaces on a runner are an owner's or admin's.

What Slack says is in [Connect Slack](slack.md).

## Ask for help

Write to us where we shared these guides with you. Send:

- what you did and what you expected;
- the last lines the runner printed: `docker compose logs --tail 50 runner`;
- the output of `docker compose ps`.

Look through what you send first. Never send a token, a key, `runner.env`, `slack.env`, `tunnel.env` or a backup file.

## Doing it by hand

`slack.env`'s own messages and every file's lines are in [By hand](by-hand.md).
