# Storage and backup

Jatevo stores console state and encrypted provider credentials under `DATA_DIR`. Native source installs default to `./data`; the Mac installer uses `~/Library/Application Support/Jatevo/data`; Docker uses the named `data` volume mounted at `/data`.

| Path | Contents |
| --- | --- |
| `console.db` | SQLite users, sessions, team keys, provider connections, usage and events |
| `secrets.json` | Session/encryption secrets and optional engine bootstrap credentials, mode 0600 |
| `sidecar-client-key`, `sidecar-mgmt-key` | Optional engine credentials |
| `sidecar/config.yaml` | Optional sidecar configuration |
| `auth/` | Connected subscription authentication files |

The optional codex-lb engine stores its database and encryption key in the separate `codexlb-data` volume. The `engine-bootstrap` volume contains only its generated bootstrap token; it can be recreated from `secrets.json` by initialization.

## Encrypted backup

Requirements: Node 24 or later, GnuPG, OpenSSL and tar. A backup contains provider credentials and must remain private.

For the default Docker deployment:

```bash
COMPOSE=1 bash scripts/backup.sh /path/to/backups
```

For Docker with subscription engines:

```bash
COMPOSE=1 COMPOSE_FILE=compose.yml:compose.engines.yml bash scripts/backup.sh /path/to/backups
```

The script briefly stops the running console and engines, copies the actual container-mounted volumes, checks the console database, and restarts services that were previously running. Stopping the writers keeps the console and engine databases consistent. Services are also restarted if a backup step fails. Schedule this short interruption outside busy periods. Do not run concurrent backups or change the Compose project during a backup.

For a native installation:

```bash
COMPOSE=0 DATA_DIR=/path/to/jatevo/data bash scripts/backup.sh /path/to/backups
```

The native path uses SQLite's backup API and includes secrets, provider credentials and authentication files. Stop native services while backing up if you need all file changes and database changes captured at exactly the same point. Any separately managed engine database or external database server needs its own backup.

`COMPOSE=auto` is the default: it detects the current project's console container, otherwise it uses local `DATA_DIR`. Explicit `COMPOSE=1` refuses to silently fall back if the expected container is missing. `COMPOSE_FILE` and `COMPOSE_PROJECT_NAME` select the deployment.

The output is a dated `.tar.gz.gpg` archive. The script refuses missing console database or encryption secrets, checks database integrity, then verifies that the archive decrypts and can be listed. Diagnostic payload logs are excluded. Retain your deployment's `.env` separately and securely if it carries externally supplied secrets; it is outside the data volume.

The passphrase file defaults to `~/.config/jatevo/backup.pass` and is generated with mode 0600 on the first backup. Keep a separate copy off the host. **An encrypted archive without its passphrase cannot be restored.** `BACKUP_PASS_FILE`, `BACKUP_DIR` and `BACKUP_KEEP_DAYS` override the passphrase location, destination and 14-day archive retention. A positional destination takes precedence over `BACKUP_DIR`.

## Restore

Test a restore into a separate installation before relying on a backup. Extract privately:

```bash
umask 077
mkdir restored
gpg --decrypt --output backup.tar.gz /path/to/jatevo-backup.tar.gz.gpg
tar -xzf backup.tar.gz -C restored
```

The extracted directory contains `MANIFEST.txt`, `data/` and, when enabled, `codexlb/`. Stop the target services, then replace their data with the corresponding saved directories. Do not overlay a live database or retain an unrelated `console.db-wal`/`console.db-shm` from the target installation. Preserve `secrets.json` with its database so encrypted credentials remain readable.

For Docker, create the target containers without starting them (`docker compose create`), copy the saved `data/.` into `console:/data/`, and copy saved `codexlb/.` into `codexlb:/var/lib/codex-lb/` when present. Use the same Compose override as the original deployment. Restore file ownership before starting: console data belongs to the image's `node` user; codex-lb data belongs to its `app` user. For example, after copying into an empty console volume:

```bash
docker compose run --rm --no-deps --user root console sh -c 'chown -R node:node /data'
```

With the engine override, use the `init` service instead of `console` for that ownership command. A stopped sidecar has no network namespace for the console to join, while `init` can mount the data volume independently:

```bash
docker compose run --rm --no-deps --user root init sh -c 'chown -R node:node /data'
```

For a codex-lb volume, use its image with `--user root --entrypoint sh` to run `chown -R app:app /var/lib/codex-lb`. Start with `docker compose up -d`; the initializer reconstructs the separate bootstrap token volume from the restored secret. Check sign-in, key policy and one request through each provider before routing team traffic to the restored gateway.

## Retention

Request metadata is kept for 90 days and history for 180 days by default. Adjust `requests_retention_days` and `events_retention_days` with the operator CLI. The console records request attribution and token usage rather than retaining message bodies. Optional upstream engines have their own logging behavior; sidecar diagnostic logs use a temporary filesystem in Docker.
