> For the complete documentation index, see [llms.txt](https://wiki.crosswatch.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.crosswatch.app/crosswatch/maintenance/backup-and-restore.md).

# Backup & Restore

Use **Backup & Restore** in **Settings → Maintenance** to protect local CrossWatch data.

It was added in `v0.9.23`.

{% hint style="warning" %}
Backups are ZIP files.

They are not encrypted.

If a backup includes `config.json` and `.cw_master_key`, treat it like credentials.
{% endhint %}

### What you can do

Use Backup & Restore to:

* create a backup
* import an older backup
* validate before restore
* restore a saved backup
* schedule automatic backups
* download or delete stored archives

Backups are stored under:

```
/config/backups
```

### Pick the right backup type

| Type       | Best for                                     | Includes                                                                               |
| ---------- | -------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Config** | App settings only                            | `config.json` and `.cw_master_key` when present                                        |
| **Normal** | Routine backups                              | Config plus core app state                                                             |
| **Full**   | Upgrades, migrations, or larger cleanup work | Everything in **Normal**, plus snapshots, tracker data, reports, and backup cache data |

{% hint style="info" %}
**Full** backups can get large fast.

That is normal when many snapshots or reports exist.
{% endhint %}

### Common tasks

#### Create a backup

1. Open **Settings → Maintenance → Backup & Restore**.
2. Open **Manual Backup**.
3. Choose **Config**, **Normal**, or **Full**.
4. Add a label.
5. Select **Create Backup**.

<figure><img src="/files/BIq5ApDfH9TYH8Ow93GQ" alt=""><figcaption></figcaption></figure>

The label shows in the UI.

It is saved in metadata only.

#### Validate a backup

Validate before restore, especially for imported or older files.

1. Open **Backup & Restore**.
2. Find the backup.
3. Select the validation icon.

Success shows **Successfully validated**.

#### Restore a backup

1. Open **Backup & Restore**.
2. Find the backup.
3. Validate it if needed.
4. Select the restore icon.
5. Confirm the restore.

Before restore, CrossWatch creates a fresh **Normal** backup with the `pre_restore` trigger.

After restore, CrossWatch requests a restart.

Your container or service manager should start it again.

{% hint style="warning" %}
Restore replaces only files inside the backup.

It does not delete extra local files outside the archive.
{% endhint %}

#### Import a backup

1. Open **Manual Backup**.
2. Select **Import**.
3. Choose a `.zip` file.
4. Wait for upload and validation.

Imported backups are stored under:

```
/config/backups/imported
```

Limits:

* only `.zip` files are accepted
* maximum upload size is `2 GB`
* failed validation deletes the imported file

#### Download or delete a backup

Each backup entry lets you:

* download
* validate
* restore
* delete

Deleting removes the ZIP from disk.

Keep a second copy for long-term retention.

### Schedule backups

Use **Scheduled Backups** to run backups automatically.

You can set:

* enabled or disabled
* backup type
* start time
* weekdays
* retention days
* maximum backup count

Default values:

* **Scope:** `Normal`
* **Time:** `03:00`
* **Retention:** `30` days
* **Maximum backups:** `10`
* **Automatic deletion:** enabled

If no weekdays are selected, the schedule runs every day.

CrossWatch uses the main scheduling timezone.

If none is set, it uses the host or container local time.

If a sync is running, the backup waits until that sync ends.

#### Retention rules

Retention can use both age and count.

CrossWatch:

1. deletes backups older than the age limit
2. deletes the oldest remaining backups until the count limit is met

{% hint style="warning" %}
Retention applies to the whole backup directory.

It can delete manual, imported, and `pre_restore` backups too.
{% endhint %}

<figure><img src="/files/I2siUUfXlYGj0BNSNmnV" alt=""><figcaption></figcaption></figure>

### Recommended use

* Use **Normal** for regular protection.
* Use **Full** before bigger changes.
* Download important backups outside `/config/backups`.
* Validate imported backups before restore.
* Keep the original external config key.
* Confirm the service restarts automatically.
* Test restore before you need it.

### Advanced reference

<details>

<summary>Exact contents of each backup type</summary>

Only the listed files and directories are included.

The backup directory itself is excluded.

Symbolic links are excluded too.

#### Config contents

* `config.json`
* `.cw_master_key`

#### Normal contents

* `config.json`
* `.cw_master_key`
* `state.json`
* `last_sync.json`
* `statistics.json`
* `watchlist_hide.json`
* `.cw_state`
* `tls`

#### Full contents

Everything in **Normal**, plus:

* `snapshots`
* `.cw_provider`
* `sync_reports`
* `.cw_cache`

Files such as `tombstones.json`, arbitrary files under `/config`, and the regular cache directory are not included by the standard interface.

</details>

<details>

<summary>Manifest, encryption, and key handling</summary>

Every backup includes `manifest.json`.

The manifest records:

* backup type and schema version
* created time and CrossWatch version
* selected scope and user label
* trigger, such as `manual`, `scheduler`, or `pre_restore`
* included files, sizes, and SHA256 checksums
* total file count and total uncompressed size
* encryption and key requirements

The current schema version is `1`.

Backups are compressed.

They are not encrypted.

When `.cw_master_key` exists, CrossWatch includes it in **Config**, **Normal**, and **Full** backups.

Key state is recorded as one of:

* **Key included**
* **External key required**
* **No key needed**

If a backup requires an external key, restore is blocked unless `CW_CONFIG_KEY` or `CROSSWATCH_CONFIG_KEY` is configured.

The value must match the original key.

Related: [Config encryption](/crosswatch/configuration-config-json/config-encryption.md)

</details>

<details>

<summary>Validation and restore behavior</summary>

Validation checks:

* file exists under `/config/backups`
* archive is a ZIP
* size is no larger than `2 GB`
* entry count is no larger than `100000`
* ZIP integrity test succeeds
* `manifest.json` exists and is no larger than `5 MB`
* backup type and schema version are valid
* every path resolves to an allowed restore location
* every expected file exists
* archived sizes match the manifest
* SHA256 checksums match

Validation also blocks path traversal and writes outside the CrossWatch config directory.

Restore runs in this order:

1. validate the backup
2. check external key requirements
3. create a fresh **Normal** `pre_restore` backup
4. extract only listed files
5. write each restored file to a temporary file
6. replace the current file
7. request a restart

Each file replacement is atomic.

The full restore is not one atomic transaction.

If one file fails, earlier restored files stay changed.

</details>

<details>

<summary>Scheduled retention internals and security protections</summary>

Scheduled runs are recorded so the same slot does not run twice.

If CrossWatch starts after the scheduled time passed, it marks that slot as missed.

It does not run a catch-up backup.

Retention cleanup runs only after a scheduled backup succeeds.

Built-in safeguards include:

* fixed allowed backup and restore paths
* rejection of absolute paths and `..` traversal
* fixed restore allowlist
* symbolic link exclusion
* labels never used in archive paths
* validation before imported backups are kept
* checksum and size checks on every restored file
* fixed public API error codes
* no internal exception details returned to the browser
* backup downloads disable browser caching and content-type guessing

</details>

<details>

<summary>API endpoints</summary>

* `GET /api/backups/list`
* `POST /api/backups/create`
* `GET /api/backups/download`
* `POST /api/backups/validate`
* `POST /api/backups/restore`
* `POST /api/backups/delete`
* `POST /api/backups/upload`
* `GET /api/backups/schedule`
* `POST /api/backups/schedule`
* `POST /api/backups/retention`

All backup API responses disable browser caching.

Common error codes:

* `backup_create_failed`
* `backup_validate_failed`
* `backup_restore_failed`

</details>

### Related pages

* [Maintenance](/crosswatch/maintenance.md)
* [Settings](/crosswatch/navigation/settings.md)
* [Config encryption](/crosswatch/configuration-config-json/config-encryption.md)
* [Configuration (config.json)](/crosswatch/configuration-config-json.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.crosswatch.app/crosswatch/maintenance/backup-and-restore.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
