> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sovseal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Back Up and Recover Your sovseal Self-Hosted Instance

> Strategies and commands for backing up Postgres snapshots, LanceDB local collections, and recovering agent memory state via lineage replay after a failure.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

A complete backup strategy for a self-hosted sovseal deployment covers two independent data structures: the Postgres relational database and the LanceDB files on each client device. Both must be backed up to guarantee full recoverability — Postgres holds the replicated encrypted snapshot chain, while LanceDB holds the live local memory state and sync queue. This guide walks through both backup methods, restoration procedures, and the crash-recovery behaviour built into the sovseal client.

<Warning>
  Your encryption keys are **never stored on the server**. If you lose the OS-keychain master key (or the `SOVSEAL_KEY_FALLBACK=file` key file on headless machines), every snapshot — local and replicated — becomes **permanently unreadable**. There is no escrow and no reset. Export and securely store your key material before any infrastructure migration or hardware change.
</Warning>

***

## Postgres Schema and Snapshot Backups

Self-hosted sovseal runs its Postgres schema on **your own Supabase project** — there is no local database container to manage. All API key hashes, sequence numbers, and AES-256-GCM encrypted snapshot payloads live there. Use Supabase's own backup tooling, or `pg_dump` directly against the project's connection string, for hot logical backups.

<Note>
  Supabase projects on paid plans include automatic daily backups and point-in-time recovery (PITR) out of the box — check your project's **Database → Backups** settings before building custom tooling. The commands below are for teams that want an independent, self-managed copy.
</Note>

### Create a Logical Backup

```bash theme={null}
pg_dump "$(supabase status -o env | grep DB_URL | cut -d= -f2-)" \
  > backup_$(date +%F).sql
```

Or use the connection string directly from your Supabase project settings. Schedule this in a cron job or CI pipeline. Because every payload column contains ciphertext, the dump file itself is safe to store in ordinary object storage (S3, R2, etc.) for an additional layer of protection.

### Restore from a SQL Dump

<Steps>
  <Step title="Provision a clean target">
    Restoring into the *same* project risks colliding with live traffic. For a real disaster-recovery drill, restore into a fresh Supabase project and re-point `supabase link` at it once verified.
  </Step>

  <Step title="Import the backup file">
    ```bash theme={null}
    psql "$(supabase status -o env | grep DB_URL | cut -d= -f2-)" \
      < backup_2026-01-15.sql
    ```
  </Step>

  <Step title="Redeploy the function">
    Re-run `supabase functions deploy v2-agent-state` so the function's connection pool picks up the restored schema cleanly.
  </Step>
</Steps>

***

## Local LanceDB Snapshot Backups

Each client device stores the live memory database at `~/.sovseal/db/`. LanceDB uses an append-only Arrow transaction log, so a directory copy produces a consistent snapshot even if taken while the process is running.

### Back Up the Database Directory

```bash theme={null}
# Compress and archive the entire LanceDB directory
tar -czf sovseal_lancedb_$(date +%F).tar.gz ~/.sovseal/db/
```

Store this archive alongside your Postgres dump. If you override the database location with `SOVSEAL_DB_DIR`, substitute that path.

### Restore LanceDB from Archive

```bash theme={null}
# Stop your agent or MCP server process first, then:
rm -rf ~/.sovseal/db/
tar -xzf sovseal_lancedb_2025-01-15.tar.gz -C ~/
```

Restart the agent after extraction. On next boot, the SDK re-opens the restored database and resumes sync from the last `synced` sequence number.

***

## Crash Recovery via Lineage Replay

If a client device loses its local LanceDB state (disk failure, accidental deletion, fresh machine), the sovseal SDK can reconstruct the memory database from the replicated snapshot chain in Postgres without any manual intervention.

<Steps>
  <Step title="Restore config.json">
    Place the client config file at `~/.sovseal/config.json` with the original `project_id` and `endpoint`. The file must **not** contain key material — that lives in the OS keychain:

    ```json theme={null}
    {
      "schema_version": 1,
      "project_id": "8435d886-f288-466c-8ee1-eb836e2b6912",
      "api_key": "sov_live_your-key-here",
      "endpoint": "https://your-endpoint.example.com"
    }
    ```
  </Step>

  <Step title="Restore the master key">
    Re-import the master key into the OS keychain (macOS example):

    ```bash theme={null}
    security add-generic-password \
      -s sovseal \
      -a master \
      -w "your-base64-master-key"
    ```

    On Linux, use `secret-tool store --label="sovseal" service sovseal username master`. On headless machines with `SOVSEAL_KEY_FALLBACK=file`, copy the backup key file to `~/.sovseal/` and set permissions to `0600`.
  </Step>

  <Step title="Rebuild local state from the replication log">
    <Warning>
      This step is **not automatic.** Neither SDK repopulates the local database for you on boot — `restore()` and `lineage()` are primitives, and reconstructing state from them is a pattern you implement, the same way [Verified Semantic Recall](/platform/core-concepts/verified-semantic-recall) is a pattern you implement on top of `restore()`.
    </Warning>

    Walk `client.lineage({ agentId })` to get the sequence of prior snapshots, then for each one: `restore()` it, fetch the ciphertext, `decryptJson` it, and re-derive the hash to compare against `receipt.client_payload_hash` before trusting it — exactly the VSR pattern. Write each verified payload back into a fresh local LanceDB instance yourself.
  </Step>
</Steps>

<Note>
  If you restore a Postgres backup that predates recent client writes, the parent-snapshot chain for those later writes will not resolve — `lineage()` walks will stop at the restored point. Memories written after the backup date exist only in a surviving LanceDB archive on the device that wrote them, if one exists.
</Note>

***

## Key Backup Best Practices

Because key loss is irreversible, treat your encryption keys with the same care as private signing certificates:

* Export the master key from the OS keychain immediately after first setup and store it in an offline, encrypted vault (e.g. a hardware security key or air-gapped secrets manager).
* For `SOVSEAL_KEY_FALLBACK=file` deployments, include `~/.sovseal/` in your off-device backup rotation alongside the LanceDB directory.
* Never commit key material to version control or include it in container image layers.
* Rotate the master key only through the sovseal re-encryption workflow — not by deleting and regenerating it, which would invalidate all existing snapshots.
