---
title: Backup & Restore
description: What to back up, how to restore it, and how to migrate Sencho to a new host.
---

Sencho stores all its state in two places: the **data directory** (SQLite database and encryption key) and your **compose directory** (your actual stack files). Both need to be backed up for a complete recovery.

<Note>
  Every tier also has access to [Fleet-Wide Backups](/features/fleet-backups), which snapshot compose files across all nodes directly from the dashboard. This page covers lower-level backup of the Sencho instance itself.
</Note>

---

## What to back up

### 1. Data directory (`DATA_DIR`)

Default path: `/app/data` inside the container, mapped to wherever you mounted it on the host (e.g. `./sencho-data`).

Contains:
- `sencho.db` - SQLite database with all settings, users, nodes, alerts, metrics history, and notification config
- `encryption.key` - Key used to encrypt sensitive values stored in the database: registry credentials, node tokens for remote nodes, Git source credentials, [Fleet Secrets](/features/fleet-secrets) bundles, SSO and MFA secrets, Recovery Vault credentials, and the contents of every [Fleet Snapshot](/features/fleet-backups)

<Warning>
  Both files are required for a full restore. If you restore `sencho.db` without the matching `encryption.key`, every encrypted value in the database becomes permanently unreadable: registry credentials, remote node tokens, Git source and Fleet Secrets bundles, SSO/MFA configuration, and the compose file contents inside any existing fleet snapshot. There is no way to recover this data without the original key; you would need to re-enter each credential, re-enroll remote nodes, and re-capture any snapshots you rely on.
</Warning>

### 2. Compose directory (`COMPOSE_DIR`)

The directory containing your stack subdirectories: your `compose.yaml` files, `.env` files, and any bind-mounted config files stored there.

This is your actual application data. It lives entirely outside Sencho and you almost certainly already back it up on a schedule, but include it in any Sencho backup plan.

---

## Backing up

### Simple file copy

```bash
# Stop Sencho to ensure no active transactions (recommended but not strictly required)
docker stop sencho

# Copy the data directory (includes both sencho.db and encryption.key)
cp -r /path/to/sencho-data /path/to/backup/sencho-data-$(date +%Y%m%d)

# Copy compose stacks
cp -r /opt/compose /path/to/backup/compose-$(date +%Y%m%d)

# Restart
docker start sencho
```

<Note>
  Sencho uses SQLite's default journal mode (not WAL), so you will not see `-wal` or `-shm` sidecar files alongside `sencho.db`. If a `-journal` file exists when you copy, it indicates an interrupted write. SQLite will automatically resolve it the next time the database is opened.
</Note>

### SQLite online backup (without stopping)

SQLite supports hot backups via its `.backup` command. This is safe to run while Sencho is running, and requires the `sqlite3` CLI to be installed on the host:

```bash
sqlite3 /path/to/sencho-data/sencho.db ".backup '/path/to/backup/sencho.db'"
```

Remember to also copy `encryption.key` from the same directory.

### Built-in backup command (no host tooling required)

Sencho ships an equivalent online backup as a CLI command that runs inside the container, so you do not need `sqlite3` on the host:

```bash
docker compose exec sencho node dist/cli/backupData.js [destination-dir]
```

With no destination argument it writes a timestamped folder under `DATA_DIR/backups`, copies `sencho.db` and `encryption.key` together, and records the action in the audit log. See [Emergency command-line recovery](/operations/emergency-cli#back-up-the-data-directory) for the full command reference.

### Automated daily backup (cron example)

```cron
0 3 * * * cp /path/to/sencho-data/encryption.key /backups/encryption.key && sqlite3 /path/to/sencho-data/sencho.db ".backup '/backups/sencho-$(date +\%Y\%m\%d).db'" && find /backups -name "sencho-*.db" -mtime +30 -delete
```

This copies the encryption key, backs up the database at 3 AM daily, and deletes database backups older than 30 days. If the host does not have `sqlite3` installed, substitute `docker compose exec sencho node dist/cli/backupData.js /backups/sencho-$(date +\%Y\%m\%d)` for the same effect.

---

## Restoring

### Restore from backup

1. Stop Sencho:
   ```bash
   docker stop sencho
   ```

2. Replace the data directory with your backup:
   ```bash
   rm -rf /path/to/sencho-data/*
   cp /path/to/backup/sencho.db /path/to/sencho-data/sencho.db
   cp /path/to/backup/encryption.key /path/to/sencho-data/encryption.key
   ```

3. Restore your compose directory if needed:
   ```bash
   cp -r /path/to/backup/compose /opt/compose
   ```

4. Start Sencho:
   ```bash
   docker start sencho
   ```

Sencho will read the restored database and resume with all your previous settings, nodes, and alert rules intact.

---

## Migrating to a new host

### Step 1: Prepare the new host

Install Docker and Docker Compose on the new machine. Create the same directory structure you use for your compose files, following the [1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule).

### Step 2: Copy data

Transfer your backup files to the new host:

```bash
scp -r /path/to/sencho-data newhost:/path/to/sencho-data
scp -r /opt/compose newhost:/opt/compose
```

### Step 3: Deploy Sencho on the new host

Use the same `docker-compose.yml` you used on the old host (with the same `COMPOSE_DIR` and `DATA_DIR` paths):

```bash
docker compose up -d
```

### Step 4: Update remote node references

If other Sencho instances were pointing to your old host as a remote node, update their node config to use the new host's IP or hostname. Node tokens are JWTs signed with a secret stored in `sencho.db`, so any token issued before the move is copied along with your data and keeps working automatically; you only need to update the URL, not regenerate the token. Generate a fresh one from **Settings → Infrastructure → Nodes** only if you want to rotate it for its own sake.

### Step 5: Verify

- Log in and confirm your stacks, nodes, and alerts are all present
- Check that at least one stack deploys correctly
- Verify the node switcher shows the expected nodes with green status

---

## What is NOT backed up by this process

| Item | Location | Notes |
|------|----------|-------|
| Container data volumes | Wherever each stack's volumes are mounted on the host | Back these up separately per-application |
| Actual container images | Docker image cache | These are re-pulled on next deploy; no backup needed |
| Sencho logs (docker logs) | Container stdout | Not persisted beyond container lifetime |
